В объектно-ориентированном программировании, конечно, нет точного правила о максимальной длине метода, но я все же обнаружил, что эти две цитаты несколько противоречат друг другу, поэтому я хотел бы услышать, что вы думаете.
В « Чистом коде: справочник по мастерству гибкого программного обеспечения» Роберт Мартин говорит:
Первое правило функций состоит в том, что они должны быть маленькими. Второе правило функций заключается в том, что они должны быть меньше, чем это. Функции не должны быть длиной в 100 строк. Функции едва ли должны быть длиной в 20 строк.
и он приводит пример из кода Java, который он видит из Кента Бека:
Каждая функция в его программе была длиной всего две, три или четыре строки. Каждый был прозрачно очевиден. Каждый рассказал историю. И каждый привел вас к следующему в убедительном порядке. Вот как коротко должны быть ваши функции!
Это звучит великолепно, но с другой стороны, в Code Complete Стив Макконнелл говорит что-то совсем другое:
Рутине нужно дать возможность органически расти до 100-200 строк, десятилетия доказательств говорят, что процедуры такой длины не более подвержены ошибкам, чем более короткие процедуры.
И он дает ссылку на исследование, в котором говорится, что рутины длиной 65 строк или более дешевые в разработке.
Так что, хотя существуют различные мнения по этому вопросу, есть ли функциональная передовая практика для вас?
источник
switch
Заявление с 100case
условиями становится более сопровождаемым , чем 10 уровнейif
заявлений , вложенных в друг друга.Ответы:
Функции обычно должны быть короткими, от 5 до 15 строк - мое личное «правило» при кодировании на Java или C #. Это хороший размер по нескольким причинам:
Но я не думаю, что полезно устанавливать абсолютное правило, так как всегда будут действительные исключения / причины отклоняться от правила:
Так что, в основном, руководствуйтесь здравым смыслом , в большинстве случаев придерживайтесь небольших размеров функций, но не будьте догматичными, если у вас есть действительно веская причина сделать необычно большую функцию.
источник
Хотя я согласен с комментариями других, когда они сказали, что нет строгого правила относительно правильного номера LOC, я держу пари, если мы оглянемся назад на проекты, которые мы рассматривали в прошлом, и определим каждую функцию выше, скажем, 150 строк кода, я Я предполагаю, что мы придем к общему мнению, что 9 из 10 этих функций нарушают SRP (и, скорее всего, также OCP), имеют слишком много локальных переменных, слишком большой поток управления и, как правило, их трудно читать и поддерживать.
Таким образом, хотя LOC не может быть прямым индикатором плохого кода, это, безусловно, приличный косвенный показатель того, что определенная функция может быть написана лучше.
В моей команде я стал лидером, и по какой-то причине люди, кажется, меня слушают. В общем, я остановился на том, чтобы сказать команде, что, хотя абсолютного ограничения нет, любая функция, содержащая более 50 строк кода, должна как минимум поднимать красный флаг во время проверки кода, чтобы мы взглянули на него еще раз и пересмотрели его. за сложность и нарушения SRP / OCP. После этого второго взгляда мы можем оставить его в покое или изменить его, но, по крайней мере, это заставляет людей задуматься об этих вещах.
источник
Я вошел в проект, который не заботился о правилах кодирования. Когда я изучаю код, я иногда нахожу классы с более чем 6000 строками кода и менее чем с 10 методами. Это ужасный сценарий, когда нужно исправлять ошибки.
Общее правило о том, насколько большим должен быть метод, иногда не очень хорошо. Мне нравится правило Роберта К. Мартина (дядя Боб): «Методы должны быть маленькими, меньше маленьких». Я стараюсь использовать это правило все время. Я пытаюсь сделать мои методы простыми и маленькими, разъясняя, что мой метод делает только одно и больше ничего.
источник
Дело не в количестве строк, а в SRP. Согласно этому принципу, ваш метод должен делать одно и только одно.
Если ваш метод делает это И это И это ИЛИ это => это, вероятно, делает много. Попробуйте взглянуть на этот метод и проанализировать: «здесь я получаю эти данные, сортирую их и получаю нужные мне элементы» и «здесь я обрабатываю эти элементы» и «здесь я, наконец, объединяю их, чтобы получить результат». Эти «блоки» должны быть реорганизованы для других методов.
Если вы просто следуете SRP, большая часть вашего метода будет маленькой и с четким намерением.
Неправильно говорить «этот метод> 20 строк, поэтому он неправильный». Это может быть признаком того, что с этим методом что-то не так, не более.
В методе может быть переключение на 400 линий (часто это происходит в телекоммуникациях), и это все равно единственная ответственность, и с ней все в порядке.
источник
Серьезно, это зависит от того , действительно ли нет точного ответа на этот вопрос, потому что язык, с которым вы работаете, имеет значение, пять-пятнадцатая строки, упомянутые в этом ответе, могут работать для C # или Java, но в других языках это не дает с вами много работать. Аналогично, в зависимости от домена, в котором вы работаете, вы можете обнаружить, что задаете значения параметров кода в большой структуре данных. С некоторыми структурами данных у вас могут быть десятки элементов, которые вам нужно установить, стоит ли разбивать их на отдельные функции только потому, что ваша функция выполняется долго?
Как уже отмечали другие, лучшим практическим правилом является то, что функция должна быть единым логическим объектом, который обрабатывает одну задачу. Если вы попытаетесь применить драконовские правила, которые говорят, что функции не могут быть длиннее, чем n строк, и вы сделаете это значение слишком маленьким, ваш код станет труднее читать, поскольку разработчики пытаются использовать хитрые трюки, чтобы обойти это правило. Точно так же, если вы установите его слишком высоко, это не будет проблемой и может привести к плохому коду из-за лени. Лучше всего просто провести проверку кода, чтобы убедиться, что функции выполняют одну задачу, и оставить все как есть.
источник
Я думаю, что одна проблема здесь в том, что длина функции ничего не говорит о ее сложности. LOC (Lines of Code) - плохой инструмент для измерения чего-либо.
Метод не должен быть слишком сложным, но есть сценарии, в которых длинный метод может быть легко поддержан. Обратите внимание, что в следующем примере не говорится, что он не может быть разбит на методы, просто методы не изменят возможность сопровождения.
например, обработчик для входящих данных может иметь большой оператор switch и затем простой код для каждого случая. У меня есть такой код - управление входящими данными из ленты. 70 (!) Численно закодированных обработчиков. Теперь можно сказать «использовать константы» - да, за исключением того, что API не предоставляет их, и мне нравится оставаться здесь рядом с «источником». Методы? Конечно, к сожалению, все они имеют дело с данными из тех же двух огромных структур. Нет смысла разделять их, кроме, возможно, наличия большего количества методов (удобочитаемость). Код по сути не сложен - один переключатель, в зависимости от поля. Затем в каждом случае есть блок, который анализирует x элементов данных и публикует их. Нет обслуживания кошмар. Существует одно повторяющееся условие «если», которое определяет, есть ли у поля данные (pField = pFields [x], если pField-> IsSet () {blabla}) - то же самое в значительной степени для каждого поля.
Замените это на гораздо меньшую подпрограмму, содержащую вложенный цикл и множество реальных операторов переключения, а также огромный метод, который проще поддерживать, чем один меньший.
Так что, извините, LOC не очень хорошее измерение для начала. Если что-то, то должны быть использованы точки сложности / решения.
источник
Я просто добавлю еще одну цитату.
Очень маловероятно, что функции, возрастающие до 100-200, следуют этому правилу
источник
Я был в этой безумной ракетке, так или иначе, с 1970 года.
За все это время, за двумя исключениями, которые я получу через мгновение, я НИКОГДА не видел хорошо разработанную «подпрограмму» (метод, процедуру, функцию, подпрограмму и т. Д.), Которой НУЖНО быть более одной напечатанной страницы ( около 60 строк) длиной. Подавляющее большинство из них были довольно короткими, порядка 10-20 строк.
Я, однако, видел МНОГО кода «потока сознания», написанного людьми, которые, очевидно, никогда не слышали о модульности.
Два исключения были очень частными случаями. Один из них - это на самом деле класс исключительных случаев, которые я объединяю: большие конечные автоматы, реализованные в виде больших уродливых операторов переключения, обычно потому, что не существует более чистого способа их реализации. Эти вещи обычно обнаруживаются в автоматизированном тестовом оборудовании, анализируя журналы данных с тестируемого устройства.
Другой была рутина фотонной торпеды из игры STARTRK Матушека-Рейнольдса-МакГирти-Коэна, написанная на CDC 6600 FORTRAN IV. Он должен был проанализировать командную строку, затем смоделировать полет каждой торпеды, с возмущениями, проверить взаимодействие между торпедой и каждой вещью, на которую он может поразить, и, между прочим, имитировать рекурсию, чтобы сделать соединение с 8 путями на цепях новые от торпедирования звезды, которая была рядом с другими звездами.
источник
Если я найду длинный метод, я мог бы поспорить, что этот метод не проверен должным образом, или в большинстве случаев он вообще не имеет модульного тестирования. Если вы начнете работать с TDD, вы никогда не создадите 100-строчные методы с 25 различными обязанностями и 5 вложенными циклами. Тесты обязывают вас постоянно проводить рефакторинг своего беспорядка и писать чистый код дяди Боба.
источник
Не существует абсолютных правил относительно длины метода, но были полезны следующие правила:
источник
Авторы подразумевают одно и то же под «функцией» и «рутиной»? Обычно, когда я говорю «функция», я имею в виду подпрограмму / операцию, которая возвращает значение и «процедуру» для той, которая не имеет (и чей вызов становится единым оператором). Это не распространенное различие в SE в реальном мире, но я видел это в текстах пользователей.
В любом случае, нет правильного ответа на это. Предпочтение тому или иному (если оно вообще есть) - это то, что, как я ожидаю, будет сильно отличаться между языками, проектами и организациями; так же, как и со всеми соглашениями кода.
Один бит, который я бы добавил, состоит в том, что утверждение «длинные операции не более подвержены ошибкам, чем короткие операции» не является строго верным. В дополнение к тому факту, что больше кода равно большему пространству потенциальных ошибок, совершенно очевидно, что разбиение кода на сегменты сделает как ошибки проще, так и их легче обнаружить. Иначе не было бы никакой причины разбивать код на части, кроме повторения. Но это, возможно, верно только в том случае, если указанные сегменты документированы достаточно хорошо, чтобы вы могли определить результаты вызова операции, не читая или не отслеживая фактический код (проектирование по контракту на основе спецификаций, а не конкретная зависимость между областями кода).
Кроме того, если вы хотите, чтобы более длинные операции работали хорошо, вы можете принять более строгие соглашения по коду для их поддержки. Бросок оператора return в середине операции может быть подходящим для короткой операции, но в более длинных операциях это может создать большой фрагмент кода, который является условным, но не обязательно условным для быстрого чтения (только для одного примера).
Поэтому я думаю, что стиль, который с меньшей вероятностью будет наполнен ошибками, будет во многом зависеть от того, какие соглашения вы придерживаетесь для остальной части своего кода. :)
источник
ИМХО, вам не нужно использовать полосу прокрутки, чтобы прочитать свою функцию. Как только вам нужно переместить полосу прокрутки, потребуется еще немного времени, чтобы понять, как работает функция.
Соответственно, это зависит от обычной среды программирования вашей командной работы (разрешение экрана, редактор, размер шрифта и т. Д.). В 80-х годах было 25 строк и 80 столбцов. Теперь в моем редакторе я отображаю почти 50 строк. Количество отображаемых столбцов не изменилось, так как я разделил экран на две части, чтобы одновременно отображать два файла.
Вкратце, это зависит от настроек ваших коллег.
источник
Я думаю, что ответ TomTom был близок к тому, как я к этому отношусь.
Я все больше и больше сталкиваюсь с цикломатической сложностью, а не с линиями.
Я обычно стремлюсь не более одной структуры управления на метод, за исключением того, сколько циклов требуется для обработки многомерного массива.
Иногда я помещаю однострочные if в случаи переключения, потому что по какой-то причине это, как правило, случаи, когда разделение его скорее мешает, чем помогает.
Обратите внимание, что я не считаю охранную логику против этого предела.
источник
В ООП все вещи возражают и есть такие особенности:
Когда вы соблюдаете эти правила, тогда ваши методы обычно невелики, но для маленьких или очень маленьких (например, 2-3 строчных) правил не существует. Преимущество маленького метода (маленькая единица, например, метод или функция):
источник