В последнее время я переработал некоторый код на работе, и я подумал, что хорошо поработал. Я опустил 980 строк кода до 450 и сократил вдвое количество классов.
Показывая это моим коллегам, некоторые не соглашались, что это улучшение.
Они сказали - «меньше строк кода не обязательно лучше»
Я вижу, что могут быть крайние случаи, когда люди пишут действительно длинные строки и / или помещают все в один метод, чтобы сохранить несколько строк, но это не то, что я сделал. Код, на мой взгляд, хорошо структурирован и проще для понимания / поддержки, так как он в два раза меньше.
Я изо всех сил пытаюсь понять, почему кто-то захочет работать с двойным кодом, который необходим для выполнения работы, и мне интересно, чувствует ли кто-нибудь то же самое, что и мои коллеги, и может привести несколько хороших примеров для того, чтобы больше кода было меньше ?
источник
Ответы:
Худой человек не обязательно здоровее, чем человек с избыточным весом.
Детскую историю из 980 строк легче читать, чем физическую диссертацию из 450 строк.
Есть много атрибутов, которые определяют качество вашего кода. Некоторые просто вычисляются, такие как цикломатическая сложность и сложность Холстеда . Другие более свободно определены, такие как сплоченность , читаемость, понятность, расширяемость, надежность, корректность, самодокументирование, чистота, тестируемость и многое другое.
Это может быть, например, то, что, уменьшая общую длину кода, вы вводите дополнительную необоснованную сложность и делаете код более загадочным.
Разделение длинного куска кода на крошечные методы может быть как вредным, так и полезным .
Попросите ваших коллег предоставить вам конкретные отзывы о том, почему они считают, что ваши усилия по рефакторингу дали нежелательный результат.
источник
Интересно, что мы с коллегой в настоящее время занимаемся рефакторингом, который увеличит количество классов и функций чуть менее чем вдвое, хотя строки кода останутся прежними. Так что у меня есть хороший пример.
В нашем случае у нас был один уровень абстракции, которого действительно должно было быть два. Все было забито слоем пользовательского интерфейса. Разделив его на два слоя, все становится более сплоченным, а тестирование и обслуживание отдельных частей становится намного проще.
Это не размер кода, который беспокоит ваших коллег, это нечто другое. Если они не могут сформулировать его, попробуйте посмотреть на код самостоятельно, как если бы вы никогда не видели старую реализацию, и оцените его по достоинству, а не просто для сравнения. Иногда, когда я выполняю длительный рефакторинг, я как бы теряю из виду исходную цель и захожу слишком далеко. Взгляните критически на «общую картину» и верните ее в нужное русло, возможно, с помощью программиста, чей совет вы цените.
источник
На ум приходит цитата, которую часто приписывают Альберту Эйнштейну:
Когда вы уклоняетесь от лишних усилий, это может затруднить чтение кода. Поскольку «легко / трудно читаемый» может быть очень субъективным термином, я объясню, что именно я имею в виду под этим: мера степени сложности, с которой опытный разработчик будет сталкиваться при определении «что делает этот код?» просто глядя на источник, без помощи специализированных инструментов.
Такие языки, как Java и Pascal, печально известны своей многословностью. Люди часто указывают на определенные синтаксические элементы и насмешливо говорят, что «они просто существуют, чтобы упростить работу компилятора». Это более или менее верно, за исключением «справедливой» части. Чем более явной является информация, тем легче читать и понимать код не только компилятором, но и человеком.
Если я скажу
var x = 2 + 2;
, сразу видно, чтоx
это целое число. Но если я скажуvar foo = value.Response;
, гораздо менее ясно, чтоfoo
представляет или каковы его свойства и возможности. Даже если компилятор может легко сделать вывод, он прилагает гораздо больше познавательных усилий к человеку.Помните, что программы должны быть написаны для того, чтобы люди могли читать, и только для машин. (По иронии судьбы эта цитата взята из учебника, посвященного печально известному языку, который чрезвычайно труден для чтения!) Хорошая идея - удалять ненужные вещи, но не убирайте код, который облегчает жизнь вашим собратьям. выяснить, что происходит, даже если это не является строго необходимым для написания программы.
источник
var
пример не является особенно хорошим упрощения , так как большая часть времени на чтение и понимание кода включает в себя выяснение поведения на определенном уровне абстракции, поэтому зная фактические типы специфических переменных , как правило, ничего не меняет (это только помогает понять нижние абстракции). Лучшим примером может быть несколько строк простого кода, сжатых в одно замысловатое утверждение - например,if ((x = Foo()) != (y = Bar()) && CheckResult(x, y))
требуется время, чтобы понять, что за типы,x
илиy
не помогает ни в малейшей степени.Более длинный код может быть проще для чтения. Обычно все наоборот, но есть множество исключений - некоторые из них описаны в других ответах.
Но давайте посмотрим с другой стороны. Мы предполагаем, что новый код будет рассматриваться как превосходящий большинству опытных программистов, которые видят 2 части кода, не имея дополнительных знаний о культуре компании, кодовой базе или дорожной карте. Даже тогда есть много причин возражать против нового кода. Для краткости я буду называть «Люди, критикующие новый код» Pecritenc :
источник
Какой код лучше, может зависеть от опыта программистов, а также от инструментов, которые они используют. Например, вот почему то, что обычно считается плохо написанным кодом, может быть более эффективным в некоторых ситуациях, чем хорошо написанный объектно-ориентированный код, который полностью использует наследование:
(1) Некоторые программисты просто не имеют интуитивного понимания объектно-ориентированного программирования. Если ваша метафора для программного проекта представляет собой электрическую цепь, то вы ожидаете много дублирования кода. Вам понравится видеть более или менее одинаковые методы во многих классах. Они заставят вас чувствовать себя как дома. И проект, в котором вам нужно искать методы в родительских или даже в родительских классах, чтобы увидеть, что происходит, может показаться враждебным. Вы не хотите понимать, как работает родительский класс, а затем понимать, чем отличается текущий класс. Вы хотите непосредственно понять, как работает текущий класс, и вы находите факт, что информация распределена по нескольким файлам, сбивает с толку.
Кроме того, когда вы просто хотите исправить конкретную проблему в определенном классе, вам может не понравиться думать, решать ли проблему непосредственно в базовом классе или перезаписывать метод в вашем текущем интересующем классе. (Без наследования вам не пришлось бы принимать осознанное решение. По умолчанию просто игнорируются похожие проблемы в похожих классах, пока они не будут сообщены как ошибки.) Этот последний аспект не является действительным аргументом, хотя он может объяснить некоторые из оппозиции.
(2) Некоторые программисты часто используют отладчик. Хотя в целом я твердо на стороне наследования кода и предотвращения дублирования, я разделяю некоторые разочарования, описанные в (1), при отладке объектно-ориентированного кода. Когда вы следите за выполнением кода, он иногда переходит между классами (предками), даже если он остается в том же объекте. Кроме того, при установке точки останова в хорошо написанном коде она с большей вероятностью срабатывает, когда это не помогает, поэтому вам, возможно, придется потратить усилия на то, чтобы сделать ее условной (где это целесообразно), или даже на ручное продолжение много раз перед соответствующим триггером.
источник
Это полностью зависит. Я работал над проектом, который не допускает использование булевых переменных в качестве параметров функции, но вместо этого требует выделенных
enum
для каждой опции.Так,
намного более многословен, чем
Тем не мение,
гораздо более читабельным, чем
Компилятор должен сгенерировать один и тот же код для обоих, поэтому при использовании более короткой формы ничего не получится.
источник
Я бы сказал, что сплоченность может быть проблемой.
Например, в веб-приложении допустим, что у вас есть страница администратора, на которой вы индексируете все продукты, что по сути является тем же кодом (индексом), который вы использовали бы в ситуации на домашней странице, чтобы просто индексировать продукты.
Если вы решите сделать все по частям, чтобы оставаться СУХИМЫМ и гладким, вам придется добавить множество условий, касающихся того, просматривает ли пользователь права администратора или нет, и загромождать код ненужными вещами, что сделает его крайне нечитаемым, скажем так дизайнер!
Таким образом, в такой ситуации, даже если код в значительной степени такой же, просто потому, что он может масштабироваться до чего-то другого, а варианты использования могут немного измениться, было бы плохо следовать каждому из них, добавляя условия и ifs. Таким образом, хорошей стратегией было бы отказаться от концепции СУХОЙ и разбить код на обслуживаемые части.
источник
Когда меньше кода менее обслуживаемо / расширяемо, чем больше кода. Рефакторинг для краткости кода часто удаляет «ненужные» конструкции кода в интересах LoC. Проблема в том, что эти конструкции кода, такие как объявления параллельного интерфейса, извлеченные методы / подклассы и т. Д., Необходимы, если этот код должен когда-либо делать больше, чем в настоящее время, или делать это иначе. В крайнем случае, некоторые решения, специально разработанные для конкретной проблемы, могут вообще не работать, если определение проблемы немного меняется.
Один пример; у вас есть список целых чисел. Каждое из этих целых чисел имеет дублирующее значение в списке, кроме одного. Ваш алгоритм должен найти это непарное значение. В общем случае решение состоит в том, чтобы сравнивать каждое число с любым другим числом, пока не найдете число, которое не имеет дублирования в списке, что является N ^ 2-кратной операцией. Вы также можете построить гистограмму, используя хеш-таблицу, но это очень мало места. Тем не менее, вы можете сделать это линейным и постоянным пространством, используя побитовую операцию XOR; XOR каждое целое число против бегущей «суммы» (начиная с нуля), и, в конце, бегущая сумма будет значением вашего непарного целого числа. Очень элегантный. Пока требования не изменятся, и более одного числа в списке могут быть непарными, или целые числа включают ноль. Теперь ваша программа либо возвращает мусор, либо неоднозначные результаты (если она возвращает ноль, означает ли это, что все элементы являются парными, или что непарный элемент равен нулю?). Такова проблема «умных» реализаций в реальном программировании.
источник
Компьютерный код должен сделать несколько вещей. «Минималистский» код, который этого не делает, не является хорошим кодом.
Например, компьютерная программа должна охватывать все возможные (или, как минимум, все возможные случаи). Если фрагмент кода охватывает только один «базовый случай» и игнорирует другие, это не очень хороший код, даже если он краткий.
Компьютерный код должен быть «масштабируемым». Загадочный код может работать только для одного специализированного приложения, в то время как более длинная, но более открытая программа может упростить добавление в новые приложения.
Компьютерный код должен быть понятным. Как показал другой ответчик, для хардкорного кодера возможно создать однострочную функцию «алгоритмического» типа, которая выполняет эту работу. Но одну строку нужно было разбить на пять разных «предложений», прежде чем это станет понятно среднему программисту.
источник
Вычислительная производительность. При оптимизации параллельной или конвейерной части вашего кода может быть полезно, например, не цикл от 1 до 400, а от 1 до 50 и поместить 8 экземпляров аналогичного кода в каждый цикл. Я не предполагаю, что это имело место в вашей ситуации, но это пример, где больше строк лучше (с точки зрения производительности).
источник