Сколько параметров - это слишком много?[закрыто]

StackOverflow https://stackoverflow.com/questions/174968

  •  05-07-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

Это было полезно?

Решение

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

Я ненавижу делать жесткие и быстрые правила, подобные этому, потому что ответ меняется не только в зависимости от размера и масштаба вашего проекта, но я думаю, что он меняется даже до уровня модуля. В зависимости от того, что делает ваш метод, или от того, что должен представлять класс, вполне возможно, что 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 * поможет вам.

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

В Чистый код Роберт С. Мартин посвятил этой теме четыре страницы , Вот суть:

  

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

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

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

(Обычно.)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

<Ол>
  • логическое отношение к основной цели функции в сравнении с одноразовыми настройками

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

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

    По словам Стива Макконнелла из Code Complete , вам следует

      

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

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

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

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

    <Ол>
  • Название функции
  • Возвращаемое значение функции
  • Назначение функции
  • Параметр 1
  • Параметр 2
  • Параметр 3
  • Параметр 4
  • В Худшие 5 фрагментов кода , проверьте второй, " Это конструктор " ;. Это как более 37 & # 8901; 4 & # 8776; 150 параметров:

      

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

         

    с более чем 150 параметрами

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

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

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

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

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

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

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

    97 звучит как раз правильно.

    Чуть меньше, и вы теряете гибкость.

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

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

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

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

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

    <Ол>
  • Ваш метод выполняет слишком много задач, и вам необходимо провести рефакторинг.
  • Возможно, вы захотите использовать коллекцию или некоторую структуру данных.
  • Переосмыслите дизайн своего класса, возможно, некоторые вещи не нужно обменивать.
  • С точки зрения простоты использования или простоты чтения кода, я думаю, что когда вам нужно что-то вроде «перенос слов» " подпись вашего метода, которая должна заставить вас остановиться и задуматься, если вы не чувствуете себя беспомощным, и все усилия по уменьшению подписи не приводят ни к какому результату. Некоторые очень хорошие библиотеки в прошлом и настоящем используют более 4-5 колясок.

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

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

    Вы можете создать объект со свойствами для хранения параметров и передать его, если вы превысите установленный предел. См. Книгу Мартина Фаулера Книга по рефакторингу и глава о том, как упростить вызовы методов.

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

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

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

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

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

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

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

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

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

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

    По словам Джеффа Безоса из Amazon, не более чем можно кормить с помощью двух пицц :

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top