Длинные методы всегда плохи? [закрыто]

64

Поэтому, оглядываясь назад, я заметил несколько комментариев о том, что длинные методы являются плохой практикой.

Я не уверен, что всегда согласен с тем, что длинные методы плохие (и хотел бы узнать мнение других).

Например, у меня есть несколько представлений Django, которые выполняют небольшую обработку объектов перед отправкой их в представление, длинный метод состоит из 350 строк кода. Мой код написан так, чтобы он работал с параметрами - сортировка / фильтрация набора запросов, затем по крупицам выполняется некоторая обработка объектов, возвращенных моим запросом.

Таким образом, обработка в основном является условной агрегацией, которая имеет достаточно сложные правила, которые не могут быть легко выполнены в базе данных, поэтому у меня есть некоторые переменные, объявленные вне основного цикла, которые затем изменяются во время цикла.

variable_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

Таким образом, в соответствии с теорией, я должен разложить весь код на более мелкие методы, чтобы у меня был метод view с максимальной длиной в одну страницу.

Однако, работая в прошлом с различными базами кода, я иногда обнаруживаю, что он делает код менее читабельным, когда вам нужно постоянно переходить от одного метода к другому, выясняя все его части, сохраняя при этом самый внешний метод в своей голове.

Я обнаружил, что с длинным методом, который хорошо отформатирован, вы можете легче увидеть логику, так как она не скрывается во внутренних методах.

Я мог бы разделить код на более мелкие методы, но часто есть внутренний цикл, используемый для двух или трех вещей, так что это приведет к более сложному коду или методам, которые не выполняют одну вещь, а две или три (альтернативно Я мог бы повторить внутренние циклы для каждой задачи, но тогда будет падение производительности).

Так есть ли случаи, когда длинные методы не всегда плохи? Всегда ли есть случаи написания методов, когда они будут использоваться только в одном месте?

ОБНОВЛЕНИЕ: Похоже, я задавал этот вопрос более года назад.

Поэтому я реорганизовал код после (смешанного) ответа, разделив его на методы. Это приложение Django, которое извлекает сложные наборы связанных объектов из базы данных, поэтому аргумент тестирования отсутствует (вероятно, потребовалось бы большую часть года для создания соответствующих объектов для тестовых случаев. У меня есть тип «это нужно сделать вчера») рабочая среда, прежде чем кто-либо жалуется). Исправлять ошибки в этой части кода теперь немного легче, но не так массово.

до :

#comment 1 
bit of (uncomplicated) code 1a  
bit of code 2a

#comment 2 
bit of code 2a
bit of code 2b
bit of code 2c

#comment 3
bit of code 3

в настоящее время:

method_call_1
method_call_2
method_call_3

def method_1 
    bit of (uncomplicated) code 1a  
    bit of code 2a

def method_2 
    bit of code 2a
    bit of code 2b
    bit of code 2c

def method_3
    bit of code 3
wobbily_col
источник
156
Все абсолюты плохие. Всегда.
Йоахим Зауэр
30
Я вижу аргумент «извлекать методы, если вы можете использовать их повторно» довольно часто (в этой или аналогичных формах), но я не покупаю его: если метод выполняет более чем одну вещь, вы должны извлечь из него методы для удобства чтения / ремонтопригодность, даже если эти новые методы вызываются только из одного места в вашем коде.
Иоахим Зауэр
4
@gnat: вау, не будет ли какое-то ручное наложение (через препроцессор) на этапе сборки лучшим решением?
Иоахим Зауэр
11
Один из лучших моих знакомых программистов прокомментировал, что если вам действительно нужна мера, то число локальных переменных лучше, чем фактическая длина. Он работал над сложным оптимизатором пути, где кишки были одним методом длиной в несколько сотен строк, но количество сохраняемых состояний (локальных переменных) было очень мало.
Чуу
2
Длинные методы не всегда плохи; но это то, на что вы всегда должны смотреть и спрашивать себя "это плохо?"
Carson63000

Ответы:

80

Нет, длинные методы не всегда плохи.

В книге Code Complete измеряется, что длинные методы иногда быстрее и проще в написании, и не приводят к проблемам обслуживания.

На самом деле, что действительно важно, так это оставаться сухим и уважать разделение интересов. Иногда вычисление просто долго писать, но в будущем оно не вызовет проблем.

Тем не менее, исходя из моего личного опыта, в большинстве длительных методов, как правило, отсутствует разделение интересов. На самом деле, длинные методы - это простой способ обнаружить, что что-то МОЖЕТ быть неправильным в коде, и это требует особой осторожности при проверке кода.

РЕДАКТИРОВАТЬ: как комментарии сделаны, я добавляю интересный момент в ответ. На самом деле я бы также проверил метрики сложности для функции (NPATH, цикломатическая сложность или даже лучше CRAP).

На самом деле, я рекомендую не проверять такие метрики в длинных функциях, но включать оповещение о них с помощью автоматических инструментов (таких как checkstyle для java, например) НА КАЖДУЮ ФУНКЦИЮ.

deadalnix
источник
41
+1: «Нет, длинные методы не всегда плохие», но они почти всегда плохие
Binary Worrier
67
Длинные тела методов - это классический запах кода : это само по себе не проблема, но это признак того, что там, вероятно, есть проблема.
Иоахим Зауэр
6
+1, но я все же рекомендую проверить цикломатическую сложность метода long. Высокие значения указывают на методы, которые фактически невозможно выполнить модульным тестом (а длинные методы очень редко лишены логики потока управления).
Даниэль Б
11
Я использую имена методов, чтобы минимизировать комментарии. Это иногда приводит к таким вещам, как «getSelectedNodeWithChildren», но мой коллега постоянно говорит мне, что мой код хорошо читается. Я также стараюсь избегать сокращений, их приятно писать, но не так приятно читать.
K ..
4
@ da_b0uncer Это тоже политика, которой я следую. Читать код сложнее, чем писать, поэтому дополнительные усилия при написании кода делают его более читабельным и окупаются.
Deadalnix
55

Кажется, что основное внимание здесь уделяется слову всегда . Да, абсолюты плохие, а разработка программного обеспечения - это почти столько же искусство, сколько наука, и все такое ... но я должен сказать, что для приведенного вами примера метод был бы лучше, если бы он был разделен вверх. Вот аргументы, которые я обычно использую для обоснования разделения вашего метода:

Читаемость: я не уверен насчет других, но я не могу быстро прочитать 350 строк кода. Да, если это мой собственный код, и я могу сделать много предположений по этому поводу, я мог бы просмотреть его очень быстро, но это не главное. Подумайте, насколько проще было бы прочитать этот метод, если бы он состоял из 10 вызовов других методов (каждый с описательным именем). Делая это, вы ввели код в многоуровневую структуру, а высокоуровневый метод дает читателю краткую и приятную информацию о том, что происходит.

Изменить - чтобы представить это в другом свете, подумайте об этом так: как бы вы объяснили этот метод новому члену команды? Конечно, у него есть некоторая структура, которую вы можете суммировать следующим образом: «Ну, он начинает с A, затем B, затем иногда C и т. Д.». Короткий «обзорный» метод, вызывающий другие методы, делает эту структуру очевидной. Чрезвычайно редко можно найти 350 строк кода, которые не приносят пользы; человеческий мозг не предназначен для того, чтобы иметь дело со списками сотен предметов, мы группируем их.

Возможность повторного использования: длинные методы, как правило, имеют низкую когезию - они часто делают больше, чем одно. Низкая сплоченность - враг повторного использования; если вы объедините несколько задач в один метод, он будет использоваться повторно в меньшем количестве мест, чем следовало бы.

Тестируемость и сплоченность: я упомянул цикломатическую сложность в комментарии выше - это довольно хорошая мера того, насколько сложен ваш метод. Он представляет нижнюю границу числа уникальных путей через ваш код в зависимости от входных данных (правка: исправлено согласно комментарию MichaelT). Это также означает, что для правильного тестирования вашего метода вам нужно иметь как минимум столько тест-кейсов, сколько у вас число цикломатической сложности. К сожалению, когда вы собираете куски кода, которые на самом деле не зависят друг от друга, невозможно быть уверенным в этом отсутствии зависимости, а сложность имеет тенденцию к умножению. Вы можете думать об этой мере как о количестве разных вещей, которые вы пытаетесь сделать. Если оно слишком высоко, пора делиться и побеждать.

Рефакторинг и структура: длинные методы часто являются признаками отсутствия какой-либо структуры в коде. Часто разработчик не мог понять, что общего между различными частями этого метода, и где можно провести черту между ними. Понимание того, что длинный метод - это проблема, и попытка разбить его на более мелкие методы - это первый шаг на более долгом пути к фактической идентификации лучшей структуры для всего этого. Возможно, вам нужно создать класс или два; это не обязательно будет более сложным в конце!

Я также думаю, что в этом случае оправданием для использования метода long является «... некоторые переменные, объявленные вне основного цикла, затем изменяются во время цикла». Я не эксперт по Python, но я уверен, что эта проблема может быть тривиально решена путем передачи по ссылке.

Даниэль Б
источник
13
+1 за дезавуацию всегда части вопроса и сосредоточение внимания на мясе: плохие или нет длинные методы. Я думаю, что ОП ищет оправдания, как будто его сценарий - крайний случай, хотя обычно, когда я слышу, как люди объясняют свои плохие практики, необходимые для необычного сценария, это просто потому, что они не очень старались использовать хорошие практики. Необычные сценарии действительно очень редки, но, к сожалению, длинные методы довольно распространены.
Джимми Хоффа
2
Хорошо, глядя на список выше: удобочитаемость, я бы сказал, из прошлого опыта, повышается за счет того, что метод длиннее, содержит много комментариев и хорошо отформатирован, вместо того, чтобы переходить от кода к методу, хотя это, вероятно, весьма субъективно. Я не ожидаю повторного использования частей кода. Большая часть повторного использования кода достигается за счет наследования в данный момент.
wobbily_col
1
@wobbily_col Кстати, если вы ищете хорошо написанный текст, который объясняет необходимость использования более коротких методов, прочитайте первые несколько глав « Чистого кода» , которые довольно хорошо объясняют это.
Даниэль Б
5
@wobbily_col Вы говорите, что необходимость слишком много разбираться, чтобы понять код многими методами, сбивает с толку, я думаю, что упущенный момент здесь заключается в важности именования. Если метод имеет правильное имя, вам не нужно смотреть на него, чтобы выяснить, что он делает, вызывающий метод должен быть полностью понятным без каких-либо базовых знаний о том, что делают методы, которые он вызывает, например, когда-либо вы использовали someVar.toString()и чувствовали Вам нужно было увидеть код toString, чтобы знать, что он делает? Вы только что прочитали прямо из-за хорошего названия метода.
Джимми Хоффа
4
Кроме того, наличие метода, которому требуются n параметров, также является запахом кода и указывает на то, что метод может выполнять несколько задач. То же самое касается наличия метода, который сложно назвать. И если для этого действительно нужны все эти параметры, они обычно являются частью более широкой концепции, которая может и должна быть заключена в отдельный класс. Конечно, мы могли бы придумать пример, который лучше не использовать это правило - я хочу сказать, что если вы видите такой метод, тщательно исследуйте его, он, вероятно, в некотором смысле плох.
KL
28

Длинные методы всегда плохи, но иногда лучше, чем альтернативы.

Telastyn
источник
5
без объяснения этот ответ может стать бесполезным в случае, если кто-то постит противоположное мнение. Например, если кто-то публикует утверждение типа «Длинные методы никогда не бывают плохими, но иногда они хуже, чем альтернативы». Как этот ответ поможет читателю выбрать два противоположных мнения? Подумайте об изменении его в лучшую форму
комнат
9

Длинные методы - это запах кода . Они обычно указывают, что что-то не так, но это не жесткое правило. Как правило, случаи, когда они оправданы, включают множество государственных и довольно сложных бизнес-правил (как вы уже нашли).

Что касается вашего другого вопроса, часто полезно разделить куски логики на отдельные методы, даже если они вызываются только один раз. Это облегчает понимание логики высокого уровня и может сделать обработку исключений немного чище. Так же, как вам не нужно передавать двадцать параметров для представления состояния обработки!

Melebius
источник
7

Длинные методы не всегда плохи. Они обычно являются признаком того, что может быть проблема.

В системе, над которой я работаю, у нас есть с полдюжины или около того методов длиной более 10000 строк. Одна из них в настоящее время 54 830 строк. И это нормально.

Эти смехотворно длинные функции очень просты и генерируются автоматически. Этот большой монстр длиной 54 830 строк содержит ежедневные данные о полярном движении с 1 января 1962 года по 10 января 2012 года (наш последний выпуск). Мы также выпустили процедуру, с помощью которой наши пользователи могут обновить этот автоматически созданный файл. Этот исходный файл содержит данные о полярном движении из http://data.iers.org/products/214/14443/orig/eopc04_08_IAU2000.62-now , автоматически переведенные на C ++.

Чтение этого веб-сайта на лету невозможно при безопасной установке. Нет связи с внешним миром. Загрузка веб-сайта в качестве локальной копии и синтаксический анализ в C ++ также не возможны; Парсинг идет медленно , и это должно быть быстро. Загрузка, автоматический перевод на C ++ и компиляция: теперь у вас есть что-то быстрое. (Только не компилируйте его оптимизированным. Удивительно, сколько времени оптимизирующему компилятору требуется для компиляции 50 000 строк чрезвычайно простого кода с прямыми строками. На моем компьютере уходит более получаса, чтобы скомпилировать этот оптимизированный файл. И оптимизация абсолютно ничего не дает Оптимизировать нечего. Это простой прямой код, один оператор присваивания за другим.)

Дэвид Хаммен
источник
6
«один оператор присваивания за другим» ... я бы назвал это «файлом данных». Почему это код?
Йоахим Зауэр
3
@JoachimSauer - потому что анализ большого файла данных во время выполнения в установке Монте-Карло - плохая идея. Очень, очень плохая идея.
Дэвид Хаммен
4
@DavidHammen: затем сделайте это во время инициализации, точно так же, как вы заставляете ваш компоновщик / загрузчик. Или запишите файл данных в виде структуры C в заголовочный файл вместо кода C. По крайней мере, тогда загрузчик загрузился бы как блок данных.
Хавьер
3
@Javier: Даже во время инициализации это может быть очень плохой идеей, по крайней мере, в установке Монте-Карло. Симуляция, для инициализации которой требуются минуты, а для запуска - всего несколько секунд, идет вразрез с получением десятков тысяч прогонов за ночь. Изменение ключевых задач времени инициализации для компиляции временных задач решает эту проблему. Мы испробовали несколько методов, включая подход скомпилированной структуры данных. Это просто не работает или в некоторых случаях было бы очень трудно заставить работать (например, модель с большой гравитацией). Подход с использованием линейного кода легко генерируется автоматически, легко проверяется. Это просто ужасный код.
Дэвид Хаммен
7
+1 интересная история. сгенерированный код на самом деле не является исходным кодом, поэтому можно утверждать, что это не «нарушает» правило. можно предположить, что у самого генератора кода были хорошие короткие методы
jk.
7

Скажем так, есть хорошие и плохие способы разбить длинный метод. Необходимость «[держать] самый дальний метод в вашей голове» является признаком того, что вы не разбиваете его наиболее оптимальным образом или что ваши подметоды плохо названы. Теоретически, есть случаи, когда длинный метод лучше. На практике это крайне редко. Если вы не можете понять, как сделать более короткий метод читабельным, попросите кого-нибудь просмотреть ваш код и спросить его конкретно о том, как сократить методы.

Что касается нескольких циклов, вызывающих предполагаемое снижение производительности, то нет способа узнать это без измерения. Несколько меньших циклов могут быть значительно быстрее, если это означает, что все необходимое может оставаться в кэше. Даже если производительность падает, она обычно ничтожна в пользу читабельности.

Я скажу, что часто длинные методы легче писать , хотя их сложнее читать . Вот почему они размножаются, хотя никто не любит их. Нет ничего плохого в планировании с самого начала до рефакторинга, прежде чем вы его зарегистрируете.

Карл Билефельдт
источник
1
«Нет ничего плохого в планировании с самого начала до рефакторинга, прежде чем вы отметите это». +1 за это. В настоящее время большинство IDE имеют инструменты рефакторинга, которые также делают это чрезвычайно простым. Но есть обратный метод, при котором вы делегируете вещи несуществующим функциям, а затем переходите к методам и заполняете их, но я так и не смог написать такой код, как я пытался.
Tjaart
+1 за то, что «необходимость« держать самый внешний метод в вашей голове »- это признак того, что вы не разбиваете его самым оптимальным образом»,
Майкл Шоу,
4

Длинные методы могут быть более вычислительными и компактными, легче видеть логику и легче отлаживать их. Однако эти правила действительно применяются только тогда, когда только один программист касается этого кода. Расширение кода будет затруднительно, если он не является атомарным, по сути, следующему человеку придется начинать с нуля, а затем отладка и тестирование будут длиться вечно, поскольку он не использует какой-либо известный хороший код.

Перевернутая лама
источник
34
Участвуют как минимум два программиста: «ты» и «ты, три недели спустя».
Йоахим Зауэр
3

Есть кое-что, что мы называем функциональной декомпозицией, подразумевающей разбиение ваших более длинных методов на более мелкие, где это возможно. Поскольку вы упомянули, что ваш метод включает в себя сортировку / фильтрацию, то вам лучше иметь отдельные методы или функции для этих задач.

Точно, ваш метод должен быть сосредоточен только на выполнении 1 задачи.

И если по какой-то причине необходимо вызвать другой метод, то в противном случае продолжайте работу с тем, который вы уже пишете. Также для удобства чтения вы можете добавлять комментарии. Традиционно программисты используют многострочные комментарии (/ ** / в C, C ++, C # и Java) для описания методов и используют однострочные комментарии (// в C, C ++, C # и Java). Есть также хорошие инструменты документирования, доступные для лучшей читаемости кода (например, JavaDoc ). Вы также можете посмотреть комментарии на основе XML, если вы являетесь разработчиком .Net.

Циклы влияют на производительность программы и могут вызвать перегрузку приложения, если не используются должным образом. Идея состоит в том, чтобы спроектировать ваш алгоритм так, чтобы вы использовали как можно меньше вложенных циклов.

Maxood
источник
Также известный как «Функция должна делать ОДНО».
лорддев
3

Это нормально писать длинные функции. Но это зависит от контекста, действительно ли вам это нужно или нет. Например, некоторые из лучших algorthms выражены лучше всего, когда это peice. С другой стороны, большой процент подпрограмм в объектно-ориентированных программах будет подпрограммами доступа, которые будут очень короткими. Некоторые из длинных процедур обработки, которые имеют длительные случаи переключения, если условия могут быть оптимизированы с помощью табличных методов.

В Code Complete 2 есть отличная короткая дискуссия о длине подпрограмм.

Максимальная теоретическая максимальная длина 497 часто описывается как одна или две страницы списка программ, от 66 до 132 строк. В современных программах объемы чрезвычайно коротких подпрограмм смешиваются с несколькими более длинными подпрограммами.

Десятилетия доказательств говорят, что процедуры такой длины не более подвержены ошибкам, чем более короткие процедуры. Пусть такие вопросы, как глубина вложения, количество переменных и другие соображения, связанные со сложностью, определяют 535 длину процедуры, а не навязывают длину

Если вы хотите написать подпрограммы длиной более 200 строк, будьте осторожны. Ни в одном из исследований, в которых не сообщалось о снижении стоимости, снижении частоты появления ошибок или о том и другом с более крупными подпрограммами, различающимися между размерами, превышающими 200 строк, и вы обязательно столкнетесь с верхним пределом понятности при прохождении 200 строк кода. 536 ограничение само по себе.

Сарат
источник
2

Еще один голос, что это почти всегда неправильно. Я нахожу два основных случая, когда это правильный ответ:

1) Метод, который в основном просто вызывает кучу других методов и сам по себе не работает. У вас есть процесс, который выполняет 50 шагов, вы получаете метод с 50 вызовами в нем. Обычно ничего нельзя получить, пытаясь это сломать.

2) Диспетчеры. Конструкция ООП избавилась от большинства таких методов, но входящие источники данных по своей природе являются просто данными и поэтому не могут следовать принципам ООП. В коде, который обрабатывает данные, нет ничего необычного в том, чтобы иметь какую-то диспетчерскую подпрограмму.

Я также сказал бы, что не следует даже рассматривать вопрос при работе с автоматически сгенерированным материалом. Никто не пытается понять, что делает автоматически сгенерированный код, не имеет значения ни на йоту, легко ли это понять человеку.

Лорен Печтель
источник
1
Процесс 50 шагов, вероятно, может быть сведен к нескольким ведрам через. Шаг 1 - 9 - проверка параметров, поэтому создайте новый метод, называемый проверкой параметров. (Я уверен, что есть несколько примеров, когда это невозможно. Мне было бы интересно увидеть их).
sixtyfootersdude
@sixtyfootersdude: Конечно, вы можете разбить его. Я не сказал, что это невозможно, я сказал, что нечего получить, разбив его. Хотя прошло не 50 шагов, я наткнулся на нечто подобное: создание игрового мира. # 1 создал пустой мир, # 2 создал ландшафт, а затем целый ряд шагов после этого так или иначе массировали его.
Лорен Печтел
& sixtyfootersdude: Удивительно, как вы знаете код, который вы никогда не видели, и как его улучшить.
gnasher729
2

Я хотел бы привести пример, который вы привели:

Например, у меня есть несколько представлений Django, которые выполняют небольшую обработку объектов перед отправкой их в представление, длинный метод состоит из 350 строк кода. Мой код написан так, что он касается параметров - сортирует / фильтрует набор запросов, затем постепенно обрабатывает объекты, возвращенные моим запросом.

В моей компании наш самый большой проект построен на Django, и у нас также есть функции длинного просмотра (многие из них более 350 строк) Я бы сказал, что наши не должны быть такими длинными, и они причиняют нам боль.

Эти функции представления выполняют много свободно связанной работы, которая должна быть извлечена в модель, вспомогательные классы или вспомогательные функции. Кроме того, мы заканчиваем тем, что повторно используем представления, чтобы делать разные вещи, которые вместо этого должны быть разделены на более связные представления.

Я подозреваю, что ваши взгляды имеют схожие характеристики. В моем случае я знаю, что это вызывает проблемы, и я работаю, чтобы внести изменения. Если вы не согласны с тем, что это вызывает проблемы, вам не нужно это исправлять.

phasetwenty
источник
2

Я не знаю, упоминал ли кто-то об этом, но одна из причин, почему длинные методы плохие, заключается в том, что они обычно включают несколько разных уровней абстракции. У вас есть переменные цикла и все виды вещей, происходящих. Рассмотрим фиктивную функцию:

function nextSlide() {
  var content = getNextSlideContent();
  hideCurrentSlide();
  var newSlide = createSlide(content);
  setNextSlide(newSlide);
  showNextSlide();
}

Если бы вы выполняли всю анимацию, вычисления, доступ к данным и т. Д. В этой функции, это было бы беспорядком. Функция nextSlide () поддерживает согласованный уровень абстракции (система состояний слайдов) и игнорирует другие. Это делает код читабельным.

Если вам нужно постоянно переходить к более мелким методам, чтобы увидеть, что они делают, то упражнение по разделению функции провалилось. То, что код, который вы читаете, не делает очевидных вещей в дочерних методах, не означает, что дочерние методы - плохая идея, просто то, что это было сделано неправильно.

Когда я создаю методы, я обычно делю их на более мелкие методы, как своего рода стратегия «разделяй и властвуй». Метод как

   if (hasMoreRecords()) { ... }

конечно более читабельно, чем

if (file.isOpen() && i < recordLimit && currentRecord != null) { ... } 

Правильно?

Я согласен с тем, что абсолютные утверждения плохи, а также согласен, что обычно длинный метод плох.

оборота Тьяарт
источник
1

Правдивая история. Однажды я столкнулся с методом длиной более двух тысяч строк. Метод имел регионы, которые описывали, что он делал в этих регионах. Прочитав регион, я решил использовать метод автоматического извлечения, назвав его в соответствии с названием региона. к тому времени, как я закончил, метод представлял собой не что иное, как 40 вызовов метода по пятьдесят строк в каждой, и все они работали одинаково.

То, что слишком велико, субъективно. Иногда метод не может быть разбит дальше, чем он есть в настоящее время. Это похоже на написание книги. Большинство людей согласны с тем, что длинные абзацы обычно должны быть разделены. Но иногда есть только одна идея, и ее разделение вызывает больше путаницы, чем было бы вызвано длиной этого абзаца.

Майкл Браун
источник
0

Суть метода заключается в том, чтобы помочь уменьшить регургитацию кода. У метода должна быть определенная функция, за которую он отвечает. Если в конечном итоге вы перефразируете код во многих местах, вы рискуете получить неожиданный результат, если спецификации программного обеспечения будут изменены.

Для метода, имеющего 350 строк, можно предположить, что многие выполняемые им задачи реплицируются в других местах, поскольку для выполнения специализированной задачи необычно требовать такого большого количества кода.

Питер
источник
Помогите уменьшить код что ?
Авнер Шахар-Каштан
@ AvnerShahar-Kashtan, он, вероятно, означает «дублирование» :-)
Péter Török
0

На самом деле плохие методы - это не длинные методы, а скорее плохие методы их применения.

Я имею в виду, что фактический акт рефакторинга вашего образца из:

varaible_1 = 0
variable_2 = 0
for object in queryset :
     if object.condition_condition_a and variable_2 > 0 :
     variable 1+= 1
     .....
     ...    
     . 
      more conditions to alter the variables

return queryset, and context 

в

Status status = new Status();
status.variable1 = 0;
status.variable2 = 0;
for object in queryset :
     if object.condition_condition_a and status.variable2 > 0 :
     status.variable1 += 1
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

а затем

class Status {
    variable1 = 0;
    variable2 = 0;

    void update(object) {
        if object.condition_condition_a and variable2 > 0 {
            variable1 += 1
        }
    }
};

Status status = new Status();
for object in queryset :
     status.update(object);
     .....
     ...    
     . 
      more conditions to alter the variables (status)

return queryset, and context 

Теперь вы находитесь на пути к не только более короткому, но и более понятному методу.

OldCurmudgeon
источник
0

Я думаю, что факт, что метод очень длинный, это то, что нужно проверить, но определенно не мгновенный анти-паттерн. Большая вещь, которую нужно искать в огромных методах - много вложений. Если у вас есть

foreach(var x in y)
{
    //do ALL the things
    //....
}

и тело цикла не очень локализовано (т. е. вы можете отправить его менее чем с 4 параметрами), тогда, вероятно, лучше преобразовать его в:

foreach(var x in y)
{
    DoAllTheThings(x);
}
...
void DoAllTheThings(object x)
{
    //do ALL the things
    //....
}

В свою очередь, это может значительно сократить продолжительность функции. Кроме того, убедитесь, что вы нашли дублирующийся код в функции и перенесите его в отдельную функцию.

Наконец, некоторые методы просто длинные и сложные, и вы ничего не можете сделать. Некоторые проблемы нуждаются в решениях, которые не поддаются легкому кодированию. Например, синтаксический анализ грамматики большой сложности может привести к созданию очень длинных методов, с которыми вы действительно не сможете ничего поделать, не сделав его хуже.

Earlz
источник
0

Правда, это зависит. Как уже упоминалось, если код не разделяет проблемы и пытается сделать все в одном методе, то это проблема. Разделение кода на несколько модулей облегчает чтение кода, а также написание кода (несколькими программистами). Для начала неплохо придерживаться одного модуля (класса) на исходный файл.

Во-вторых, когда дело доходит до функций / процедур:

void setDataValueAndCheckForRange(Data *data) {/*code*/} 

хороший метод, если он проверяет диапазон только «данных». Это плохой метод, когда один и тот же диапазон применяется для нескольких функций (пример плохого кода):

void setDataValueAndCheckForRange(Data *data){ /*code */}
void addDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void subDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}
void mulDataValuesAndCheckForRange(Data *result, Data *d1, Data *d2){ /*code*/}

Это должно быть изменено на:

bool isWithinRange(Data *d){ /*code*/ }
void setDataValue(Data *d) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void addDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void subDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 
void mulDataValue(Data *d, Data *d1, Data *d2) {/*code*/ if(isWithinRange(d)){/*continue*/}else{/*warn/abort*/} 

Повторно используйте код как можно больше. И это возможно, когда каждая функция вашей программы достаточно ПРОСТА (не обязательно проста).

Цитата: Гора состоит из крошечных зерен земли. Океан состоит из крошечных капель воды .. (- Шивананда)

Аникет Инге
источник
0

Длинные методы имеют тенденцию к «плохому» в императивных языках, которые предпочитают операторы, побочные эффекты и изменчивость именно потому, что эти функции увеличивают сложность и, следовательно, ошибки.

В функциональных языках программирования, которые предпочитают выражения, чистоту и неизменность, меньше причин для беспокойства.

Как в функциональных, так и в императивных языках всегда лучше выделить многократно используемые фрагменты кода в общие подпрограммы верхнего уровня, но в функциональных языках, которые поддерживают лексическую область видимости с вложенными функциями и т. Д., На самом деле лучше скрыть подпрограммы в верхних подпрограммах. -уровневая функция (метод), чем разбивать их на другие функции верхнего уровня.

Стивен Свенсен
источник
В функциональных языках длинные методы встречаются гораздо реже.
Брюс