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

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

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

Careful programmers avoid bundling data any more than is logically necessary.

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

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

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

Gideon 20.08.2015 03:23

В JavaScript 65537 параметров слишком много: jsfiddle.net/vhmgLkdm

Aadit M Shah 11.03.2016 21:29

просто посмотрите на компоненты apache http, практически невозможно создать из них что-то динамическое

Andrew Scott Evans 12.07.2016 20:11
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
228
3
138 081
34
Перейти к ответу Данный вопрос помечен как решенный

Ответы 34

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

Это хорошо, пока вы с некоторыми разработчиками не попробуете foo (int a, float b, string c, double d). Думаю, лучше избегать работы с ними. : D

Rontologist 06.10.2008 20:27

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

finnw 06.10.2008 21:05

Могу я познакомить вас с «возвратом каретки»?

user172783 24.10.2009 14:10

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

Kaiserludi 28.08.2015 14:27

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

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

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

Это очень хороший ответ. Если параметры организованы логически (x, y, w, h), легко запомнить их все в правильном порядке. Намного труднее вспомнить, где поместить указатель FILE в putc (который имеет только два параметра), тем более, что fprintf - противоположность.

user877329 29.05.2016 13:06

Самый приятный ответ. Очень хорошо сказано

Anwar 18.02.2017 13:41

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

  1. логическая связь с основной целью функции по сравнению с одноразовыми настройками

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

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

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

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

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

wnoise 06.10.2008 20:29

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

Eran Galperin 06.10.2008 20:35

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

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

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

yeoman 03.09.2017 09:40

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

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

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

Я думаю, что фактическое число действительно зависит от того, что имеет логический смысл в контексте функции. Я согласен, что вокруг 4-5 параметров начинает скучать.

В случае установки флагов отличный способ справиться с этой ситуацией - перечислить значения и объединить их с помощью ИЛИ.

Ответ принят как подходящий

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

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

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

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

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

Michaelangel007 31.03.2016 17:10

@ Michaelangel007 относительно ответа, который вы комментируете, вы не должны так говорить, потому что он говорит об отсутствии правила. Кроме того, количество параметров зависит от удобочитаемости, а не производительности.

clemp6r 08.09.2016 10:36

@ clemp6r Неправильно - это и то и другое. Ребятам, занимающимся компиляцией, постоянно приходится иметь дело с "утечкой регистров". Авторитетный ответ Только - проверить сборку того, что генерирует ваш компилятор. Количество регистров не меняется волшебным образом на платформе такой же. en.wikipedia.org/wiki/Register_allocation

Michaelangel007 09.09.2016 18:11

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

The ideal number of arguments for a function is zero (niladic). Next comes one (monadic), followed closely by two (dyadic). Three arguments (triadic) should be avoided where possible. More than three (polyadic) requires very special justification -- and then shouldn't be used anyway.

Включает ли этот абсолютный верхний предел в 3 слово «this» в объектно-ориентированных языках или исключает его?

Steve Jessop 24.11.2008 16:00

Я сомневаюсь, что он включает «это», потому что это контекст исполнения. В функциональном программировании контекст является глобальным, а в oop контекст - это объект, к которому вы применяете метод. Кроме того, если бы вы включили "this" в список параметров, было бы невозможно иметь 0 параметров (идеальный вариант).

Tom 24.11.2008 16:07

Нет, это не включает "это".

Patrick McElhaney 25.11.2008 00:50

Кроме того, Мартин должен поговорить с комитетом по стандартизации C++. Половина <algorithm> принимает более 3 параметров, потому что диапазон одного итератора уже равен 2. Это просто природа программирования с итераторами (то есть общее программирование с коллекциями STL).

Steve Jessop 27.11.2008 16:49

@SteveJessop: ошибка <algorithm> в том, что он всегда работает на срезе. Если бы алгоритм и коллекцию были переработаны, я бы сделал так, чтобы алгоритмы всегда занимали всю коллекцию, и у вас был бы способ разрезать представление коллекции, чтобы алгоритмы работали по частям; в качестве альтернативы я бы также определил сокращенное переопределение, чтобы упростить работу с общим регистром.

Lie Ryan 14.08.2013 10:31

@LieRyan: тогда как если бы я перепроектировал <algorithm>, я бы заставил его воздействовать на объект диапазона. Коллекции будут диапазонами, но не все диапазоны будут коллекциями. И действительно, Boost уже сделал это. В любом случае, я хочу сказать, что широко используемая библиотека игнорирует этот совет, поэтому худшее, что гарантированный может случиться с вами, если вы это сделаете, - это то, что многие из ваших миллионов пользователей будут возиться с небольшими упрощениями вашего интерфейса ;-)

Steve Jessop 14.08.2013 18:36

Это правило имеет смысл, поскольку все методы объекта имеют доступ ко всем частным переменным. А как насчет конструктора? Если это правило применимо и к конструкторам, то как мы должны внедрять в конструктор более 2-3 зависимостей? Есть мысли по этому поводу?

Milos Mrdovic 05.09.2016 18:04

@MilosMrdovic Может быть, объект слишком много делает сам по себе? Можете ли вы взять 2-3 параметра, использовать их для создания более специализированного объекта и передать этот объект конструктору?

Patrick McElhaney 05.09.2016 19:10

Это просто ориентир. Иногда вы смотрите на код и думаете: «Я знаю, что это могло бы быть лучше, но я не знаю, как это сделать прямо сейчас». Так что оставьте это и идите дальше. Всегда будут возможности для улучшения. Вы никогда не добьетесь совершенства.

Patrick McElhaney 05.09.2016 19:14

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

alvinc 16.11.2016 18:06

@alvinc Вы имеете в виду, что они передают массив в качестве первого (и единственного) аргумента? Или что-то вроде оператора распространения в JavaScript?

Patrick McElhaney 16.11.2016 18:53

@PatrickMcElhaney Да, я имел в виду передачу массива в качестве единственного аргумента, а не оператора распространения JavaScript. Вы в конечном итоге просматриваете документацию и / или сам код, чтобы попытаться выяснить, каковы аргументы. Я сам предпочитаю строительный шаблон.

alvinc 16.11.2016 19:25

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

Patrick McElhaney 18.11.2016 00:01

Передача массива - ужасная вещь. Лучше передать объект, который, очевидно, упаковывает необходимую информацию (а если объект достаточно большой, то ничем не отличается от передачи непристойного количества параметров). Большое количество аргументов? Массивы? Жирные предметы? Все это запахи кода, намекающие на плохую связь или отсутствие достаточной абстракции IMO. Не всегда, но в большинстве случаев.

luis.espinal 13.10.2017 21:24

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

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

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

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

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

Auron 06.10.2008 20:36

Сборка x86 определенно имеет подпрограммы (вызов / возврат). Другие могут потребовать комбинации cmp / jmp.

Brian Knoblauch 06.10.2008 20:40

Извините, "ret", а не "return". Вздыхает. Это был уже долгий день.

Brian Knoblauch 06.10.2008 20:42

Извините за двусмысленную формулировку Аурона, я думаю, что исправил. Это был мой ответ, специфичный для языка, а не вопрос.

Bill K 06.10.2008 20:44

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

user172783 24.10.2009 14:09

Не все языки позволяют передавать структуры. Кроме того, передача структуры означает, что принимающий метод должен иметь код для обработки структуры и, следовательно, может потребоваться больше параметров. Кроме того, на языке, отличном от oo, вам обычно нужен дополнительный параметр - все языки OO имеют параметр «Hidden» для «this», который в противном случае должен быть передан (или, в более ужасном языке / дизайне, может быть глобально доступный)

Bill K 27.10.2009 21:38

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

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

(Как правило.)

В некотором коде, над которым я работал, использовались члены класса для достижения того же самого. В то время я был программистом на C и спросил, почему существует так много глобальных переменных, почему ввод / вывод не могут быть явно параметрами?

user3528438 03.02.2015 00:32

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

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

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

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

Что ж, prot и flags можно было бы объединить, если бы разработчик почувствовал, что 5 - это какое-то магическое число, которое намного лучше, чем 6. Немного похоже на то, как open сочетает режим чтения / записи со всеми другими разными флагами. И, возможно, вы мог избавитесь от offset, указав, что отображаемый раздел начинается с текущей позиции поиска filedes. Я не знаю, есть ли ситуации, когда вы можете использовать mmap для региона, в котором вы не можете lseek, но если нет, то это не является строго необходимым.

Steve Jessop 17.08.2013 14:47

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

Steve Jessop 17.08.2013 14:49

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

Ben Voigt 26.09.2015 19:15

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

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* помочь вам.

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

Почему вы должны указывать так много вещей при создании окна? Разве вы не можете указать это позже в коде?

Auron 06.10.2008 20:45

Я голосую за это. Я поражен, как все остальные ответы говорят «3» и «4»! Правильный ответ: минимум необходимого, которого иногда может быть довольно много.

Tony Andrews 06.10.2008 20:49

@Auron - Я видел систему, о которой вы говорите. Они были ужасны, потому что люди, устанавливающие эти параметры позже в коде, требовали уничтожения и воссоздания окна. Это было очень медленно.

Torlack 06.10.2008 20:50

@Auron - эта функция из Win32 API. Окно можно нарисовать до возврата из функции, поэтому все параметры необходимы.

Skizz 06.10.2008 20:54

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

Auron 06.10.2008 21:06

Если бы эта функция была разработана сегодня, она, вероятно, выглядела бы немного иначе. x, y, nWidth и nHeight могут быть объединены в объект Rectangle. style и xStyle могут быть объединены в набор перечислений или строк. Теперь у вас всего 8 параметров.

finnw 06.10.2008 21:07

«Теперь у вас всего 8 параметров». Точно! Удвойте максимум, заявленный другими. @Skizz - в этом я согласен с вами.

Jeffrey L Whitledge 07.10.2008 00:06

@finnw Если бы эта функция была разработана сегодня? Он уже был переработан. Форма f = новая форма (); имеет 0 параметров.

Nick 07.10.2008 00:24

@Nick Угадайте, что вызывается внутри f.show ()? :) Легко завернуть эту вещь и сделать ее теплой и приятной.

user172783 24.10.2009 14:13

Это C и winapi. Я не могу придумать худшего примера.

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 13.10.2011 23:32

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

Jan Turoň 12.06.2012 13:03

Этот код появился в древние времена от ботаников, гордо создававших запутанный код. Даже название функции плохое: что означает Бывший? Исключить, выполнить, исключить, исключение? Если бы это был хороший дизайн, не создавались бы MFC или .NET.

Jan Turoň 12.06.2012 13:13

Я считаю своим долгом указать, что все стили окон в этом вызове уже объединены в аккуратный DWORD; иначе у него было бы намного больше параметров. О, и @ JanTuroň, вы намеренно упустили правильное значение Ex, не так ли?

Mr Lister 29.03.2013 15:10

+1 @ JanTuroň, если вы передаете такое количество аргументов, вам следует подумать, связаны ли некоторые из них концептуально вместе и подходят ли они для совокупного класса (например, Rect, как указано finnw)

AlexFoxGill 15.04.2013 13:04

Ребята, не забывайте: этот код, вероятно, был написан примерно в 1987 году, до того, как такие вещи, как объектно-ориентированное программирование, стали обычным явлением для пользовательского интерфейса. Хотя ООП не тянет вниз систему, подобную Core i5, мы говорим о системах вроде 286.

Joe Plante 05.02.2014 00:35

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

Dariux 09.03.2015 12:26

эта старая вещь была такой по нескольким причинам: тогда программы, написанные на 100% ассемблере, были довольно распространены, и многие функции api были сделаны либо для большей совместимости, либо были написаны на ассемблере сами. Многие из этих вызовов были написаны действительно (действительно) очень давно, когда использовались классы, и (то, что мы называем сегодня) «минимальный C++» считался раздутым кодом. Как вы думаете, в наши дни, сколько людей пишут на 100% ассемблере ...? (вы слышите звук сверчков)

osirisgothra 23.04.2015 06:32

Я не могу придумать худшего примера. Просто потому, что он существует, это не делает его великим. Раньше мне приходилось иметь дело с этим API. Мы застряли на нем по историческим причинам и из-за широкого распространения. Но ни в коем случае нельзя рассматривать это как пример того, что «правильное» количество параметров каким-то образом «контекстно-зависимо» (это не так). Это похоже на естественный язык, в котором нет ничего, кроме простых предложений и никаких союзов любых типа вообще. Этот фрагмент API наиболее близок к этому.

luis.espinal 13.10.2017 21:21

@ luis.espinal: Я думаю, вы неверно истолковали то, что я пытался сказать, не существует "правильного" количества параметров или диапазона параметров. Если функции требуются параметры X для выполнения своей работы, тогда ей нужны параметры X независимо от значения X, нет правильного или неправильного количества параметров, и большую часть времени не о чем беспокоиться. Этому ответу уже более 9 лет, и пример из API еще старше, языки программирования появились в то время, но основная идея та же, идея «слишком много» бесполезна.

Skizz 16.10.2017 02:26

Понимаю, возможно, я слишком поспешил судить о твоем ответе. Я понимаю вашу точку зрения.

luis.espinal 16.10.2017 16:46

ИМО, оправдание длинного списка параметров заключается в том, что данные или контекст являются динамическими по своей природе, подумайте о printf (); хороший пример использования varargs. Лучший способ справиться с такими случаями - передать поток или структуру xml, что снова минимизирует количество параметров.

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

Ты сумасшедший, мужик? XML-структура? Для передачи параметров? Что у вас так много против использования массивов, что вы должны пройти через все накладные расходы на написание xml, а затем проанализировать его через 5 циклов процессора?

Leahn Novash 03.07.2009 20:49

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

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

Leahn Novash 03.07.2009 20:51

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

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

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

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

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

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

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

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

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

    I hate making hard and fast rules like this because the answer changes not only depending on the size and scope of your project, but I think it changes even down to the module level. Depending on what your method is doing, or what the class is supposed to represent, it's quite possible that 2 arguments is too many and is a symptom of too much coupling.

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

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

    Programming is not engineering. Organization of code is an art because it depends on human factors, which depend too much on context for any hard rule.

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

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

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

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

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

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

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

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

По словам Стива МакКоннелла в Код завершен, вам следует

Limit the number of a routine's parameters to about seven

/: Число, указывающее, что фактоид составлен: xkcd.com/899

user877329 29.05.2016 13:22

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

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

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

Я согласен с цитатой Роберта Мартина из «Чистого кода» (как указано выше): чем меньше параметров, тем лучше. Сложно понять более 5-7 параметров и вызовов методов. Ситуация становится особенно плохой, если некоторые параметры являются необязательными (и поэтому принимают нулевые значения) или если все параметры имеют один и тот же тип (что еще больше затрудняет определение того, какой параметр является каким). Если вы можете объединить параметры в связанные объекты домена, такие как Customer и Account, с вашим кодом будет намного приятнее работать.

Есть крайний случай: если у вас есть вызов метода, который принимает переменное количество параметров которые образуют логический набор, меньше когнитивных издержек при большем количестве параметров. Например, вам может понадобиться метод, определяющий количество повторных попыток HTTP-запроса, выраженное в миллисекундах между повторными попытками. Три попытки с интервалом в 1, 2 и 3 секунды могут быть указаны как:

retries(1000, 2000, 3000)

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

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

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

В 5 худших фрагментов кода проверьте второй: «Это конструктор». Он имеет примерно 37 ⋅ 4 ≈ 150 параметров:

Here a programmer wrote this constructor [... S]ome of you may think yes its a big constructor but he used eclipse automatic code generation tools[.] NOO, in this constructor there was a tiny bug that I discovered, which made me conclude that this constructor was written by hand. (by the way this is only the top part of the constructor, its not complete).

constructor with over 150 parameters

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

yeoman 03.09.2017 09:57

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

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

Я даю этому ответу +1, потому что это единственный ответ, который обсуждает что-либо, кроме чистоты кода или произвольных ограничений, которые являются субъективными. Некоторые люди могут не думать о том, что вы делаете со стеком, когда вы находитесь в цикле и отправляете десятки аргументов в стек и из него. Если это цикл, вам следует подумать об использовании количества аргументов, передаваемых REGISTERS в ABI, для которого вы компилируете. Например, в MS x64 ABI максимальное количество аргументов, передаваемых через регистры, равно 4. ABI "System V" (используемый в ОС, отличных от Windows) использует больше регистров, поэтому использование 4 аргументов довольно переносимо.

Lakey 13.02.2013 09:07

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

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

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

Auron 18.12.2010 22:23

8. порядок параметров

Eva 26.10.2013 08:00

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

Меньше - и вы теряете гибкость.

Другие вопросы по теме