Рутины могут иметь параметры, это не новость. Вы можете определить столько параметров, сколько вам нужно, но слишком много из них сделают вашу рутину трудной для понимания и поддержки.
Конечно, вы можете использовать структурную переменную в качестве обходного пути: поместить все эти переменные в одну структуру и передать ее в рутину. Фактически, использование структур для упрощения списков параметров является одним из методов, описанных Стивом Макконнеллом в Code Complete . Но как он говорит:
Осторожные программисты избегают объединения данных больше, чем это логически необходимо.
Поэтому, если ваша подпрограмма имеет слишком много параметров или вы используете структуру для маскировки большого списка параметров, вы, вероятно, делаете что-то не так. То есть вы не оставляете связь ослабленной.
У меня вопрос, когда я могу считать список параметров слишком большим? Я думаю, что более 5 параметров, это слишком много. Что вы думаете?
Ответы:
Когда что-то считается настолько непристойным, чтобы его можно было регулировать, несмотря на гарантию 1-й поправки к свободе слова? По словам судьи Поттера Стюарта, «я знаю это, когда вижу». То же самое и здесь.
Я ненавижу делать жесткие и быстрые правила, подобные этому, потому что ответ меняется не только в зависимости от размера и масштаба вашего проекта, но я думаю, что он меняется даже до уровня модуля. В зависимости от того, что делает ваш метод, или от того, что должен представлять класс, вполне возможно, что 2 аргумента - это слишком много и является признаком слишком сильной связи.
Я хотел бы предложить, задавая вопрос в первую очередь и квалифицировав свой вопрос так же, как и вы, чтобы вы действительно знали все это. Лучшее решение здесь - не полагаться на твердое и быстрое число, а вместо этого смотреть на обзоры дизайна и обзоры кода среди своих коллег, чтобы определить области, где у вас низкая сплоченность и тесная связь.
Никогда не бойся показывать своим коллегам свою работу. Если вы боитесь, это, вероятно, еще один признак того, что с вашим кодом что-то не так, и что вы уже это знаете .
источник
Функция может иметь слишком много параметров, только если некоторые параметры являются избыточными. Если используются все параметры, функция должна иметь правильное количество параметров. Возьмите эту часто используемую функцию:
Это 12 параметров (9, если вы связываете x, y, w и h в виде прямоугольника), а также параметры, полученные из имени класса. Как бы вы сократили это? Хотели бы вы сократить число до сути?
Не позволяйте количеству параметров беспокоить вас, просто убедитесь, что он логичен и хорошо документирован, и пусть intellisense * поможет вам
* Другие помощники кодирования доступны!
источник
В « Чистом коде» Роберт С. Мартин посвятил этой теме четыре страницы. Вот суть:
источник
<algorithm>
я бы воздействовал на объект диапазона. Коллекции были бы диапазонами, но не все диапазоны были бы коллекциями. И действительно, Boost уже сделал это. Во всяком случае, моя точка зрения в том , что в широком масштабе широко используется библиотека игнорирует этот совет, так что худшее , что это гарантированно произойдет с вами , если вы тоже, что многие из ваших миллионов пользователей будет возиться с небольшими упрощениями на ваш интерфейс ;-)Некоторый код, с которым я работал в прошлом, использовал глобальные переменные просто для того, чтобы избежать передачи слишком большого количества параметров.
Пожалуйста, не делай этого!
(Обычно.)
источник
Если вы начинаете мысленно отсчитывать параметры в подписи и сопоставлять их с вызовом, то пришло время провести рефакторинг!
источник
Большое спасибо за все ваши ответы:
Было немного удивительно найти людей, которые также думают (как и я), что 5 параметров - это хороший предел разумности кода.
Обычно люди склонны соглашаться с тем, что ограничение между 3 и 4 является хорошим эмпирическим правилом. Это разумно, так как люди обычно плохо проводят время, считая более 4 вещей.
Как указывает Милан , в среднем люди могут держать в голове более или менее 7 вещей одновременно. Но я думаю, что вы не можете забыть, что когда вы разрабатываете / поддерживаете / изучаете рутину, вы должны иметь в виду больше вещей, чем просто параметры.
Некоторые люди считают, что у рутины должно быть столько аргументов, сколько нужно. Я согласен, но только для нескольких конкретных случаев (обращения к API-интерфейсам ОС, подпрограммам, где важна оптимизация и т. Д.). Я предлагаю скрыть сложность этих подпрограмм, добавляя слой абстракции чуть выше этих вызовов, когда это возможно.
У Ника есть несколько интересных мыслей по этому поводу . Если вы не хотите читать его комментарии, я суммирую для вас: в двух словах, это зависит от :
Мораль здесь заключается в том, чтобы не бояться показывать свой код своим коллегам, обсуждать с ними и пытаться «определить области, где у вас низкая сплоченность и тесная связь» .
Наконец, я думаю, что wnoise очень согласен с Ником и завершает его сатирический вклад этим поэтическим видением (см. Комментарии ниже) искусства программирования:
источник
Этот ответ предполагает язык ОО. Если вы не используете один - пропустите этот ответ (другими словами, это не совсем языковой ответ).
Если вы передаете более трех или около того параметров (особенно внутренних типов / объектов), дело не в том, что это «Слишком много», а в том, что вы можете упустить шанс создать новый объект.
Ищите группы параметров, которые передаются в более чем один метод - даже группа, переданная в два метода, почти гарантирует, что у вас должен быть новый объект.
Затем вы реорганизуете функциональность в свой новый объект, и вы не поверите, насколько это помогает как вашему коду, так и вашему пониманию ОО-программирования.
источник
Кажется, есть и другие соображения, кроме простого числа, вот некоторые, которые приходят на ум:
логическое отношение к основной цели функции в сравнении с одноразовыми настройками
Если это просто флаги среды, пакетирование может быть очень удобным
источник
Одна из известных программных эпиграмм Алана Перлиса (описанная в заметках ACM SIGPLAN 17 (9), сентябрь 1982 г.) гласит: «Если у вас есть процедура с 10 параметрами, вы, вероятно, пропустили некоторые».
источник
Согласно Стиву Макконнеллу в Code Complete , вы должны
источник
Для меня, когда список пересекает одну строку в моей IDE, тогда это один параметр слишком много. Я хочу видеть все параметры в одной строке, не нарушая зрительный контакт. Но это только мое личное предпочтение.
источник
Я в целом согласен с 5, однако, если есть ситуация, когда мне нужно больше, и это самый ясный способ решения проблемы, то я бы использовал больше.
источник
Семь вещей в краткосрочной памяти?
источник
В худших 5 фрагментах кода , проверьте второй, «Это конструктор». Он имеет более 37 ⋅ 4 ≈ 150 параметров:
источник
Еще один, чем нужно. Я не хочу быть бойким, но есть некоторые функции, которые обязательно нуждаются в нескольких опциях. Например:
Есть 6 аргументов, и каждый из них необходим. Кроме того, между ними нет общей связи, которая бы оправдывала их объединение. Может быть, вы могли бы определить «struct mmapargs», но это было бы хуже.
источник
prot
иflags
можно было бы свернуть вместе, если бы дизайнер чувствовал, что 5 - это волшебное число, которое намного лучше, чем 6. Немного похоже на способ, которыйopen
сочетает режим чтения / записи со всеми другими разными флагами. И, возможно, вы могли бы избавиться отoffset
этого, указав, что отображаемый раздел начинается с текущей позиции поискаfiledes
. Я не знаю, есть ли ситуации, когда вы можетеmmap
создать регион, на который вы не способныlseek
, но если нет, то в этом нет особой необходимости.mmap
, это хорошая иллюстрация того факта, что некоторые дизайнеры и пользователи предпочитают большой длинный список параметров, в то время как другие предпочитают пройти несколько этапов, подготавливая меньшее количество параметров перед выполнением вызова.Согласно Perl Best Practices , 3 - это хорошо, 4 - это слишком много. Это просто руководство, но в нашем магазине мы стараемся придерживаться этого.
источник
Я бы нарисовал предел для публичных функций по 5 параметрам сам.
ИМХО, длинные списки параметров допустимы только в частных / локальных вспомогательных функциях, которые должны вызываться только из нескольких определенных мест в коде. В этих случаях вам может потребоваться передать много информации о состоянии, но удобочитаемость не так важна, так как только вы (или кто-то, кто будет поддерживать ваш код и должен понимать основы вашего модуля), должны заботиться о вызывая эту функцию.
источник
Смежный вопрос, который вы должны рассмотреть, заключается в том, насколько сплочена рутина. Большое количество параметров может быть запахом, который говорит вам, что сама рутина пытается сделать слишком много, и, следовательно, ее сплоченность является подозрительной. Я согласен, что жесткое и быстрое количество параметров, вероятно, невозможно, но я бы предположил, что процедура высокой когезии подразумевает небольшое количество параметров.
источник
97 звучит как раз правильно.
Меньше, и вы теряете гибкость.
источник
Я остановился на трех параметрах, как общее правило. Больше не нужно, и пришло время передать массив параметров или объект конфигурации, что также позволяет добавлять будущие параметры без изменения API.
источник
Ограничение длины в списке параметров - это еще одно ограничение. А ограничение означает применение насилия. Звучит смешно, но вы можете быть ненасильственным даже при программировании. Просто позвольте коду диктовать правила. Очевидно, что если у вас много параметров, тело метода функции / класса будет достаточно большим, чтобы использовать их. И большие фрагменты кода обычно могут быть реорганизованы и разбиты на более мелкие куски. Таким образом, вы получаете решение против использования многих параметров в качестве бесплатного бонуса, поскольку они разделены между меньшими реорганизованными частями кода.
источник
Одна вещь, которую я хотел бы отметить с точки зрения производительности, заключается в том, что в зависимости от того, как вы передаете параметры в метод, передача большого количества параметров по значению замедлит работу программы, поскольку каждый параметр должен быть скопирован и затем помещен в стек.
Использование одного класса для охвата всех параметров будет работать лучше, потому что один параметр, переданный по ссылке, будет элегантнее, чище и быстрее!
источник
По моему мнению, могут быть случаи, когда вы превысите 4 или какое-то фиксированное число. Вещи, чтобы посмотреть
С точки зрения простоты использования или простоты чтения кода, я думаю, что когда вам нужно как бы «обернуть слово» в сигнатуру вашего метода, это заставит вас задуматься, если вы не чувствуете себя беспомощным, и все усилия по уменьшению подписи ведут к безрезультатно. Некоторые очень хорошие библиотеки в прошлом и настоящем используют более 4-5 колясок.
источник
Мое эмпирическое правило заключается в том, что мне нужно уметь запоминать параметры достаточно долго, чтобы посмотреть на звонок и сказать, что он делает. Поэтому, если я не могу посмотреть на метод, а затем переключиться на вызов метода и вспомнить, какой параметр делает то, что тогда, их слишком много.
Для меня это примерно 5, но я не такой яркий. Ваш пробег может варьироваться.
Вы можете создать объект со свойствами для хранения параметров и передать его, если вы превысите установленный предел. См. Книгу Рефакторинга Мартина Фаулера и главу о том, как упростить вызовы методов.
источник
Это сильно зависит от среды, в которой вы работаете. Возьмите, например, javascript. В javascript лучший способ передачи параметров - использование объектов с парами ключ / значение, что на практике означает, что у вас есть только один параметр. В других системах сладкое пятно будет на уровне трех или четырех.
В конце концов, все сводится к личному вкусу.
источник
Я согласен с 3, все в порядке, 4 слишком много в качестве ориентира. Имея более 3 параметров, вы неизбежно выполняете более одной задачи. Более одной задачи должны быть разделены на отдельные методы.
Однако, если бы я посмотрел на последний проект, над которым работал, исключений было бы предостаточно, и в большинстве случаев было бы трудно получить три параметра.
источник
Если у меня есть 7-10 параметров в одной подпрограмме, я смотрю на объединение их в новый класс, но не в том случае, если этот класс был бы ничем иным, как связкой полей с геттерами и сеттерами - новый класс должен делать что-то кроме случайных значений в и вне. В противном случае я бы предпочел мириться с длинным списком параметров.
источник
Это известный факт, что в среднем люди могут держать в голове 7 +/- 2 вещи одновременно. Мне нравится использовать этот принцип с параметрами. Если предположить, что все программисты умнее людей среднего уровня, я бы сказал, что все 10+ - это слишком много.
Кстати, если параметры в любом случае похожи, я бы поместил их в вектор или список, а не в структуру или класс.
источник
Я бы основал свой ответ на том, как часто вызывается функция.
Если это функция инициализации, которая вызывается только один раз, то пусть это займет 10 пар или более, кого это волнует.
Если он вызывается несколько раз за кадр, то я стараюсь создать структуру и просто передать на нее указатель, поскольку это происходит быстрее (при условии, что вы также не перестраиваете структуру каждый раз).
источник
По словам Джеффа Безоса из Амазонской славы, не более, чем можно накормить двумя пиццами :
источник