Сколько параметров слишком много?

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

Конечно, вы можете использовать структурированную переменную в качестве обходного пути: поместить все эти переменные в одну структуру и передать ее в подпрограмму. Фактически, использование структур для упрощения списков параметров является одним из методов, описанных Стивом Макконнелом в Code Complete. Но, как он говорит:

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

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

Мой вопрос: , когда я могу рассмотреть слишком большой список параметров? Я думаю, что более 5 параметров слишком много. Как вы думаете?

Ответ 1

Когда что-то считается настолько непристойным, что может быть чем-то, что можно регулировать, несмотря на гарантию 1-й поправки на свободу слова? По словам юстиции Поттера Стюарта, "я знаю это, когда вижу это". То же самое имеет место и здесь.

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

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

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

Ответ 2

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

HWND CreateWindowEx
(
  DWORD dwExStyle,
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x,
  int y,
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMENU hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam
);

Эти 12 параметров (9, если вы связываете x, y, w и h как прямоугольник), а также параметры, полученные из имени класса. Как бы вы это уменьшили? Хотели бы вы уменьшить число до точки?

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

* Другие помощники по кодированию доступны!

Ответ 3

В Clean Code Роберт К. Мартин посвятил четыре страницы теме. Здесь суть:

Идеальное число аргументов для функция равна нулю (niladic). Далее идет один (монадический), за ним следуют два (Диадический). Три аргумента (триадные) следует избегать, где это возможно. Больше чем три (полиадикальные) особое оправдание - и затем не следует использовать в любом случае.

Ответ 4

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

Пожалуйста, не делай этого!

(Обычно.)

Ответ 5

Если вы начнете мысленно подсчитывать параметры в сигнатуре и сопоставлять их с вызовом, то пришло время рефакторирования!

Ответ 6

Большое спасибо за все ваши ответы:

  • Было немного удивительно найти людей, которые также думают (как и я), что 5 параметров являются хорошим пределом для здравого смысла кода.

  • Как правило, люди склонны соглашаться с тем, что ограничение между 3 и 4 является хорошим правилом. Это разумно, поскольку люди обычно имеют плохое время, считая более чем 4 вещи.

  • Как Милан точки, в среднем люди могут хранить более или менее 7 вещей в голове за раз. Но я думаю, что вы не можете забыть об этом, когда вы разрабатываете/поддерживаете/изучаете рутину, вы должны иметь в виду больше вещей, чем просто параметры.

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

  • Ник имеет некоторые интересные мысли об этом. Если вы не хотите читать его комментарии, я резюмирую для вас: в двух словах, зависит от:

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

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

  • Наконец, я думаю, что wnoise очень согласен с Ником и завершает свой сатирический вклад в это поэтическое видение (см. комментарии ниже ) в области программирования:

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

Ответ 7

Этот ответ предполагает язык OO. Если вы не используете один из них - пропустите этот ответ (это не совсем язык-агностический ответ, другими словами.

Если вы передаете более 3 или около того параметров (особенно внутренние типы/объекты), это не значит, что это "слишком много", но у вас может отсутствовать возможность создать новый объект.

Ищите группы параметров, которые передаются более чем одному методу - даже группа, переданная в два метода, почти гарантирует, что у вас должен быть новый объект.

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

Ответ 8

Похоже, что есть другие соображения, кроме простого числа, вот некоторые из них, которые приходят на ум:

  • логическое отношение к основной цели функции против одноразовых настроек

  • Если это только флаги среды, объединение может быть очень удобным

Ответ 9

Одна из известных программируемых эпиграмм Алана Перлиса (описанная в ACM SIGPLAN Notes 17 (9), сентябрь 1982 г.) гласит: "Если у вас есть процедура с 10 параметрами, вы, вероятно, пропустили некоторые из них".

Ответ 10

Согласно Стив Макконнелл в Code Complete, вы должны

Ограничьте количество подпрограмм параметры примерно до семи

Ответ 11

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

Ответ 12

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

Ответ 13

Семь вещей в краткосрочной памяти?

  • Название функции
  • Возвращаемое значение функции
  • Назначение функции
  • Параметр 1
  • Параметр 2
  • Параметр 3
  • Параметр 4

Ответ 14

В Худшие 5 фрагментов кода, проверьте второй, "Является ли это конструктором". Он имеет более 37 ⋅ 4 ≈ 150 параметров:

Здесь программист написал этот конструктор [... S] ome из вас может подумать, что это его большой конструктор, но он использовал инструменты автоматического генерации кода eclipse [.] NOO, в этом конструкторе была крошечная ошибка, которую я обнаружил, что заставило меня сделать вывод, что этот конструктор был написан вручную. (кстати, это только верхняя часть конструктора, но не полная).

constructor with over 150 parameters

Ответ 15

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

void *
mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset);

Существует 6 аргументов, и каждый из них имеет важное значение. Более того, нет общей связи между ними, чтобы оправдать их объединение. Возможно, вы могли бы определить "struct mmapargs", но это было бы хуже.

Ответ 16

Я бы нарисовал предел для публичных функций по 5 параметрам.

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

Ответ 17

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

Ответ 19

Согласно Perl Best Practices, 3 в порядке, 4 слишком много. Это просто руководство, но в нашем магазине это то, к чему мы пытаемся придерживаться.

Ответ 20

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

Ответ 21

Ограничение длины в списке параметров - это еще одно ограничение. И ограничение означает применение насилия. Это звучит смешно, но вы можете быть ненасильственным даже при программировании. Просто дайте коду диктовать правила. Очевидно, что если у вас много параметров, тело метода function/class будет достаточно большим, чтобы использовать их. И большие фрагменты кода обычно можно реорганизовать и разделить на более мелкие куски. Таким образом, вы получаете решение против наличия множества параметров в качестве бесплатного бонуса, так как они разделены между меньшими реорганизованными фрагментами кода.

Ответ 22

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

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

Ответ 23

По моим словам, могут быть случаи, когда вы превысите 4 или какое-то фиксированное число. Вещи для наблюдения могли быть

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

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

Ответ 24

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

Для меня это равно примерно 5, но я не настолько яркий. Ваш пробег может отличаться.

Вы можете создать объект со свойствами для хранения параметров и передать это, если вы превысите все установленные вами ограничения. Подробнее см. Martin Fowler Рефакторинг и глава о более простых вызовах методов.

Ответ 25

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

В конце концов, все это сводится к личным вкусам.

Ответ 26

Я согласен с 3 в порядке, 4 слишком много в качестве ориентира. При более чем 3 параметрах вы неизбежно выполняете более одной задачи. Более чем одна задача должна быть разделена на отдельные методы.

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

Ответ 27

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

Ответ 28

Известно, что в среднем люди могут хранить 7 +/- 2 вещи в голове за раз. Мне нравится использовать этот принцип с параметрами. Предполагая, что программисты - это люди с более высоким уровнем интеллекта, я бы сказал, что все 10+ слишком много.

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

Ответ 29

Я бы основывал свой ответ на том, как часто вызывается функция.

Если это функция init, которая когда-либо вызывается только один раз, то пусть это займет 10 парм или более, кто заботится.

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

Ответ 30

По словам Джеффа Безоса из славы Амазонки, не более, чем можно кормить две пиццы: