У подпрограмм могут быть параметры, это не новость. Вы можете определить столько параметров, сколько вам нужно, но слишком большое их количество затруднит понимание и поддержку вашей процедуры.
Конечно, вы можете использовать структурированную переменную в качестве обходного пути: поместить все эти переменные в единую структуру и передать ее подпрограмме. Фактически, использование структур для упрощения списков параметров - один из методов, описанных Стивом МакКоннеллом в Код завершен. Но как он говорит:
Careful programmers avoid bundling data any more than is logically necessary.
Поэтому, если ваша процедура имеет слишком много параметров или вы используете структуру, чтобы замаскировать большой список параметров, вы, вероятно, делаете что-то не так. То есть вы не ослабляете связь.
Мой вопрос: когда я могу считать список параметров слишком большим? Я считаю, что более пяти параметров - это слишком много. Что вы думаете?
В JavaScript 65537 параметров слишком много: jsfiddle.net/vhmgLkdm
просто посмотрите на компоненты apache http, практически невозможно создать из них что-то динамическое





Для меня, когда список пересекает одну строку в моей среде IDE, это на один параметр слишком много. Я хочу видеть все параметры в одной строке, не прерывая зрительного контакта. Но это только мои личные предпочтения.
Это хорошо, пока вы с некоторыми разработчиками не попробуете foo (int a, float b, string c, double d). Думаю, лучше избегать работы с ними. : D
Если бы кто-то другой дал классам смехотворно длинные имена, я бы не позволил этому влиять на то, как я определяю или называю свои подпрограммы.
Могу я познакомить вас с «возвратом каретки»?
Когда список пересекает одну строку в вашей среде IDE, ваш монитор слишком мал, чтобы использовать его с этим кодом, и вам явно следует купить монитор с более высоким разрешением по горизонтали. Разрыв строки или уменьшение количества параметров - это просто обходные пути, которые не решают основную проблему, заключающуюся в том, что ваш монитор слишком мал для этой кодовой базы!
Я в целом согласен с 5, однако, если есть ситуация, когда мне нужно больше, и это самый ясный способ решить проблему, я бы использовал больше.
Согласно Лучшие практики Perl, 3 - это нормально, 4 - слишком много. Это всего лишь ориентир, но в нашем магазине мы стараемся его придерживаться.
Если вы начинаете мысленно считать параметры в сигнатуре и сопоставлять их с вызовом, то пора провести рефакторинг!
Это очень хороший ответ. Если параметры организованы логически (x, y, w, h), легко запомнить их все в правильном порядке. Намного труднее вспомнить, где поместить указатель FILE в putc (который имеет только два параметра), тем более, что fprintf - противоположность.
Самый приятный ответ. Очень хорошо сказано
Похоже, есть и другие соображения, кроме простого числа, вот некоторые, которые приходят на ум:
логическая связь с основной целью функции по сравнению с одноразовыми настройками
Если это просто флаги среды, объединение может быть очень удобным.
Это сильно зависит от среды, в которой вы работаете. Возьмем, к примеру, javascript. В javascript лучший способ передать параметры - это использовать объекты с парами ключ / значение, что на практике означает, что у вас есть только один параметр. В других системах золотая середина будет на трех или четырех точках.
В конце концов, все сводится к личному вкусу.
Как правило, я останавливаюсь на трех параметрах. Еще больше, и пора вместо этого передать массив параметров или объект конфигурации, что также позволяет добавлять параметры в будущем без изменения API.
Если API изменяется, тогда API должен действительно измениться, а не просто иметь скрытое изменение, при котором несовместимость все еще может произойти, но быть менее очевидным.
однако, если вам нужен еще один параметр для настройки пограничного случая, он не должен распространяться на несвязанные компоненты с помощью API.
Я бы сам нарисовал ограничение для публичных функций по 5 параметрам.
IMHO, длинные списки параметров приемлемы только в частных / локальных вспомогательных функциях, которые предназначены только для вызова из нескольких конкретных мест в коде. В этих случаях вам может потребоваться передать много информации о состоянии, но удобочитаемость не такая большая проблема, поскольку только вы (или кто-то, кто будет поддерживать ваш код и должен понимать основы вашего модуля) должны заботиться о вызов этой функции.
Именно поэтому многие люди на данном этапе сделали бы все, что не является фактическим аргументом, а передаваемое состояние, просто состоянием объекта в форме полей (переменных-членов). Этот объект будет представлен как класс. Он будет создаваться либо один раз, либо для каждого использования. Иногда у такого объекта будет только один частный или общедоступный метод пакета, который затем делегирует работу частным методам с несколькими аргументами каждый. Теперь возможно несколько аргументов, потому что конфигурация и состояние теперь имеют правильное место :)
Я бы сказал, что пока у вас есть перегрузки, которые имеют 2-4, вы можете подняться выше, если вам это нужно.
Я согласен с тем, что 3 - это нормально, 4 - это слишком много для ориентира. Имея более трех параметров, вы неизбежно выполняете более одной задачи. Более одной задачи следует разбивать на отдельные методы.
Однако, если бы я посмотрел на последний проект, над которым я работал, было бы множество исключений, и в большинстве случаев было бы трудно перейти к 3 параметрам.
Я думаю, что фактическое число действительно зависит от того, что имеет логический смысл в контексте функции. Я согласен, что вокруг 4-5 параметров начинает скучать.
В случае установки флагов отличный способ справиться с этой ситуацией - перечислить значения и объединить их с помощью ИЛИ.
Когда что-то считается настолько непристойным, что может регулироваться, несмотря на гарантию свободы слова Первой поправкой? По словам судьи Поттера Стюарта: «Я знаю это, когда вижу». То же самое и здесь.
Я ненавижу устанавливать такие жесткие и быстрые правила, потому что ответ меняется не только в зависимости от размера и объема вашего проекта, но я думаю, что он меняется даже на уровне модуля. В зависимости от того, что делает ваш метод или что должен представлять класс, вполне возможно, что 2 аргумента - это слишком много и это признак слишком сильной связи.
Я бы посоветовал, задав вопрос в первую очередь и уточняя свой вопрос, как вы это сделали, чтобы вы действительно все это знали. Лучшее решение здесь - не полагаться на точные и быстрые цифры, а вместо этого смотреть на обзоры дизайна и проверки кода среди ваших коллег, чтобы определить области, в которых у вас низкая сплоченность и тесная связь.
Никогда не бойтесь показывать коллегам свою работу. Если вы боитесь этого, это, вероятно, более серьезный признак того, что с вашим кодом что-то не так, и что вы уже знаю это.
Хороший практическое правило - это количество регистров ЦП, потому что больше и компилятор будет вынужден размещать их в стеке.
@ Michaelangel007 относительно ответа, который вы комментируете, вы не должны так говорить, потому что он говорит об отсутствии правила. Кроме того, количество параметров зависит от удобочитаемости, а не производительности.
@ clemp6r Неправильно - это и то и другое. Ребятам, занимающимся компиляцией, постоянно приходится иметь дело с "утечкой регистров". Авторитетный ответ Только - проверить сборку того, что генерирует ваш компилятор. Количество регистров не меняется волшебным образом на платформе такой же. en.wikipedia.org/wiki/Register_allocation
В Чистый код Роберт К. Мартин посвятил этой теме четыре страницы. Вот суть:
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» в объектно-ориентированных языках или исключает его?
Я сомневаюсь, что он включает «это», потому что это контекст исполнения. В функциональном программировании контекст является глобальным, а в oop контекст - это объект, к которому вы применяете метод. Кроме того, если бы вы включили "this" в список параметров, было бы невозможно иметь 0 параметров (идеальный вариант).
Нет, это не включает "это".
Кроме того, Мартин должен поговорить с комитетом по стандартизации C++. Половина <algorithm> принимает более 3 параметров, потому что диапазон одного итератора уже равен 2. Это просто природа программирования с итераторами (то есть общее программирование с коллекциями STL).
@SteveJessop: ошибка <algorithm> в том, что он всегда работает на срезе. Если бы алгоритм и коллекцию были переработаны, я бы сделал так, чтобы алгоритмы всегда занимали всю коллекцию, и у вас был бы способ разрезать представление коллекции, чтобы алгоритмы работали по частям; в качестве альтернативы я бы также определил сокращенное переопределение, чтобы упростить работу с общим регистром.
@LieRyan: тогда как если бы я перепроектировал <algorithm>, я бы заставил его воздействовать на объект диапазона. Коллекции будут диапазонами, но не все диапазоны будут коллекциями. И действительно, Boost уже сделал это. В любом случае, я хочу сказать, что широко используемая библиотека игнорирует этот совет, поэтому худшее, что гарантированный может случиться с вами, если вы это сделаете, - это то, что многие из ваших миллионов пользователей будут возиться с небольшими упрощениями вашего интерфейса ;-)
Это правило имеет смысл, поскольку все методы объекта имеют доступ ко всем частным переменным. А как насчет конструктора? Если это правило применимо и к конструкторам, то как мы должны внедрять в конструктор более 2-3 зависимостей? Есть мысли по этому поводу?
@MilosMrdovic Может быть, объект слишком много делает сам по себе? Можете ли вы взять 2-3 параметра, использовать их для создания более специализированного объекта и передать этот объект конструктору?
Это просто ориентир. Иногда вы смотрите на код и думаете: «Я знаю, что это могло бы быть лучше, но я не знаю, как это сделать прямо сейчас». Так что оставьте это и идите дальше. Всегда будут возможности для улучшения. Вы никогда не добьетесь совершенства.
В некоторых языках люди просто передают массив, чтобы избежать слишком большого количества параметров. Я думаю, что это намного хуже при любых обстоятельствах, чем слишком много аргументов.
@alvinc Вы имеете в виду, что они передают массив в качестве первого (и единственного) аргумента? Или что-то вроде оператора распространения в JavaScript?
@PatrickMcElhaney Да, я имел в виду передачу массива в качестве единственного аргумента, а не оператора распространения JavaScript. Вы в конечном итоге просматриваете документацию и / или сам код, чтобы попытаться выяснить, каковы аргументы. Я сам предпочитаю строительный шаблон.
@alvinc Да, всегда будет не пытаться понять причины, лежащие в основе рекомендаций, воспринимать их буквально и в конечном итоге создать еще больший беспорядок. Недавно я наткнулся на код, который представлял собой серию непонятных вложенных блоков switch / case, потому что, очевидно, это сделало цикломатическую сложность меньше, чем если бы они использовали операторы if.
Передача массива - ужасная вещь. Лучше передать объект, который, очевидно, упаковывает необходимую информацию (а если объект достаточно большой, то ничем не отличается от передачи непристойного количества параметров). Большое количество аргументов? Массивы? Жирные предметы? Все это запахи кода, намекающие на плохую связь или отсутствие достаточной абстракции IMO. Не всегда, но в большинстве случаев.
Этот ответ предполагает объектно-ориентированный язык. Если вы его не используете - пропустите этот ответ (другими словами, это не совсем языковой ответ.
Если вы передаете более 3 или около того параметров (особенно внутренние типы / объекты), это не значит, что это «слишком много», а то, что вы можете упустить шанс создать новый объект.
Ищите группы параметров, которые передаются более чем в один метод - даже группа, переданная в два метода, почти гарантирует, что у вас там должен быть новый объект.
Затем вы реорганизуете функциональность в свой новый объект и не поверите, насколько это помогает как вашему коду, так и вашему пониманию объектно-ориентированного программирования.
Пожалуйста, назовите язык, на котором не используются процедуры и параметры. Я не могу придумать ни одного, даже сборка может рассматриваться как имеющая подпрограммы (метки).
Сборка x86 определенно имеет подпрограммы (вызов / возврат). Другие могут потребовать комбинации cmp / jmp.
Извините, "ret", а не "return". Вздыхает. Это был уже долгий день.
Извините за двусмысленную формулировку Аурона, я думаю, что исправил. Это был мой ответ, специфичный для языка, а не вопрос.
Использование объектно-ориентированного языка не имеет значения. Объект может быть структурой, точно так же параметры функции могут быть параметрами конструктора ...
Не все языки позволяют передавать структуры. Кроме того, передача структуры означает, что принимающий метод должен иметь код для обработки структуры и, следовательно, может потребоваться больше параметров. Кроме того, на языке, отличном от oo, вам обычно нужен дополнительный параметр - все языки OO имеют параметр «Hidden» для «this», который в противном случае должен быть передан (или, в более ужасном языке / дизайне, может быть глобально доступный)
В некотором коде, с которым я работал в прошлом, использовались глобальные переменные, чтобы не передавать слишком много параметров.
Пожалуйста, не делай этого!
(Как правило.)
В некотором коде, над которым я работал, использовались члены класса для достижения того же самого. В то время я был программистом на C и спросил, почему существует так много глобальных переменных, почему ввод / вывод не могут быть явно параметрами?
Ограничение длины в списке параметров - это еще одно ограничение. А ограничение означает примененное насилие. Звучит забавно, но вы можете быть ненасильственным даже при программировании. Просто позвольте коду диктовать правила. Очевидно, что если у вас много параметров, тело метода функции / класса будет достаточно большим, чтобы их можно было использовать. И большие фрагменты кода обычно можно реорганизовать и разбить на более мелкие части. Таким образом, вы получаете решение против использования большого количества параметров в качестве бесплатного бонуса, поскольку они разделены между более мелкими реорганизованными частями кода.
Еще один, чем нужно. Я не хочу показаться бойким, но для некоторых функций обязательно нужно несколько опций. Например:
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, но если нет, то это не является строго необходимым.
... поэтому я думаю, что mmap является хорошей иллюстрацией того факта, что некоторые дизайнеры и пользователи предпочитают большой длинный список параметров, в то время как другие предпочитают пройти несколько шагов, подготовив меньшее количество параметров, прежде чем делать вызов.
@Steve: Предварительная установка позиции поиска отдельным вызовом привела бы к беспричинной гонке. Для некоторых API (OpenGL) существует так много параметров, которые влияют на вызов, что вам действительно нужно использовать состояние, но обычно каждый вызов должен быть автономным, насколько это возможно. Действие на расстоянии - это путь к темной стороне.
Функция может иметь слишком много параметров только в том случае, если некоторые из параметров являются избыточными. Если используются все параметры, функция должна иметь правильное количество параметров. Возьмем эту часто используемую функцию:
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» и «4»! Правильный ответ: минимум необходимого, которого иногда может быть довольно много.
@Auron - Я видел систему, о которой вы говорите. Они были ужасны, потому что люди, устанавливающие эти параметры позже в коде, требовали уничтожения и воссоздания окна. Это было очень медленно.
@Auron - эта функция из Win32 API. Окно можно нарисовать до возврата из функции, поэтому все параметры необходимы.
Хорошо, я считаю, что в очень конкретных случаях, например при вызове API ОС, длинный список параметров приемлем.
Если бы эта функция была разработана сегодня, она, вероятно, выглядела бы немного иначе. x, y, nWidth и nHeight могут быть объединены в объект Rectangle. style и xStyle могут быть объединены в набор перечислений или строк. Теперь у вас всего 8 параметров.
«Теперь у вас всего 8 параметров». Точно! Удвойте максимум, заявленный другими. @Skizz - в этом я согласен с вами.
@finnw Если бы эта функция была разработана сегодня? Он уже был переработан. Форма f = новая форма (); имеет 0 параметров.
@Nick Угадайте, что вызывается внутри f.show ()? :) Легко завернуть эту вещь и сделать ее теплой и приятной.
Это C и winapi. Я не могу придумать худшего примера.
Нет нет. Это процедурный стиль. Окна - это объекты, поэтому сейчас они устарели. Сегодня это можно решить с помощью агрегированных классов, а не набора параметров. Интуитивное правило хорошего дизайна - если вы не можете описать функцию (включая параметры) одним простым предложением, она плохо спроектирована. Я считаю, что это так.
Этот код появился в древние времена от ботаников, гордо создававших запутанный код. Даже название функции плохое: что означает Бывший? Исключить, выполнить, исключить, исключение? Если бы это был хороший дизайн, не создавались бы MFC или .NET.
Я считаю своим долгом указать, что все стили окон в этом вызове уже объединены в аккуратный DWORD; иначе у него было бы намного больше параметров. О, и @ JanTuroň, вы намеренно упустили правильное значение Ex, не так ли?
+1 @ JanTuroň, если вы передаете такое количество аргументов, вам следует подумать, связаны ли некоторые из них концептуально вместе и подходят ли они для совокупного класса (например, Rect, как указано finnw)
Ребята, не забывайте: этот код, вероятно, был написан примерно в 1987 году, до того, как такие вещи, как объектно-ориентированное программирование, стали обычным явлением для пользовательского интерфейса. Хотя ООП не тянет вниз систему, подобную Core i5, мы говорим о системах вроде 286.
если я напишу код, подобный этому стилю, проблема, которую я вижу, в том, что функции становятся очень длинными по высоте, но мало что делают. Например, у меня около 15 параметров, и если я захочу добавить в форму больше фильтров, количество параметров станет еще больше.
эта старая вещь была такой по нескольким причинам: тогда программы, написанные на 100% ассемблере, были довольно распространены, и многие функции api были сделаны либо для большей совместимости, либо были написаны на ассемблере сами. Многие из этих вызовов были написаны действительно (действительно) очень давно, когда использовались классы, и (то, что мы называем сегодня) «минимальный C++» считался раздутым кодом. Как вы думаете, в наши дни, сколько людей пишут на 100% ассемблере ...? (вы слышите звук сверчков)
Я не могу придумать худшего примера. Просто потому, что он существует, это не делает его великим. Раньше мне приходилось иметь дело с этим API. Мы застряли на нем по историческим причинам и из-за широкого распространения. Но ни в коем случае нельзя рассматривать это как пример того, что «правильное» количество параметров каким-то образом «контекстно-зависимо» (это не так). Это похоже на естественный язык, в котором нет ничего, кроме простых предложений и никаких союзов любых типа вообще. Этот фрагмент API наиболее близок к этому.
@ luis.espinal: Я думаю, вы неверно истолковали то, что я пытался сказать, не существует "правильного" количества параметров или диапазона параметров. Если функции требуются параметры X для выполнения своей работы, тогда ей нужны параметры X независимо от значения X, нет правильного или неправильного количества параметров, и большую часть времени не о чем беспокоиться. Этому ответу уже более 9 лет, и пример из API еще старше, языки программирования появились в то время, но основная идея та же, идея «слишком много» бесполезна.
Понимаю, возможно, я слишком поспешил судить о твоем ответе. Я понимаю вашу точку зрения.
ИМО, оправдание длинного списка параметров заключается в том, что данные или контекст являются динамическими по своей природе, подумайте о printf (); хороший пример использования varargs. Лучший способ справиться с такими случаями - передать поток или структуру xml, что снова минимизирует количество параметров.
Машина, конечно же, не возражала бы против большого количества аргументов, но разработчики думают также о накладных расходах на обслуживание, количестве модульных тестов и проверок достоверности. Дизайнеры также ненавидят длинный список аргументов, большее количество аргументов означает больше изменений в определениях интерфейсов, когда изменение должно быть сделано. Вопросы о сцеплении / когезии исходят из вышеупомянутых аспектов.
Ты сумасшедший, мужик? XML-структура? Для передачи параметров? Что у вас так много против использования массивов, что вы должны пройти через все накладные расходы на написание xml, а затем проанализировать его через 5 циклов процессора?
Если у меня есть 7-10 параметров в одной подпрограмме, я смотрю на объединение их в новый класс но, не если бы этот класс был не чем иным, как кучей полей с геттерами и сеттерами - новый класс должен делать что-то другое, кроме перемешивания значений и из. В противном случае я бы предпочел смириться с длинным списком параметров.
Я свяжу его с классом только для данных, если он используется более чем в одном месте, но даже тогда я обычно создаю оба конструктора.
Это известный факт, что в среднем люди могут держать в голове 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 или какое-то фиксированное число. Вещи, на которые стоит обратить внимание, могут быть
С точки зрения простоты использования или легкости чтения кода, я думаю, что когда вам нужно как бы "перенести по словам" подпись вашего метода, это должно заставить вас остановиться и подумать: если вы не чувствуете себя беспомощным, и все усилия по уменьшению подписи приводят к безрезультатно. Некоторые очень хорошие библиотеки в прошлом и в настоящее время используют более 4-5 детских колясок.
По словам Стива МакКоннелла в Код завершен, вам следует
Limit the number of a routine's parameters to about seven
/: Число, указывающее, что фактоид составлен: xkcd.com/899
Мое практическое правило состоит в том, что мне нужно иметь возможность запоминать параметры достаточно долго, чтобы посмотреть на вызов и сказать, что он делает. Итак, если я не могу посмотреть на метод, а затем перейти к вызову метода и вспомнить, какой параметр что делает, то их слишком много.
Для меня это примерно 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).
Это так грустно ... Незнание о «записях», «структурах» или «объектах значений», которые объединяют несколько значений вместе и дают им общее имя, чтобы вы могли иерархически представлять множество из них в удобочитаемой форме, - все равно что ходить с туфлями, расстегнутыми годами, потому что никто никогда не говорил вам, что вы даже можете это сделать ?
С точки зрения производительности я хотел бы отметить одну вещь: в зависимости от того, как вы передаете параметры методу, передача большого количества параметров по значению замедлит работу программы, потому что каждый параметр должен быть скопирован, а затем помещен в стек.
Использование одного класса для охвата всех параметров будет работать лучше, потому что один параметр, переданный по ссылке, будет элегантнее, чище и быстрее!
Я даю этому ответу +1, потому что это единственный ответ, который обсуждает что-либо, кроме чистоты кода или произвольных ограничений, которые являются субъективными. Некоторые люди могут не думать о том, что вы делаете со стеком, когда вы находитесь в цикле и отправляете десятки аргументов в стек и из него. Если это цикл, вам следует подумать об использовании количества аргументов, передаваемых REGISTERS в ABI, для которого вы компилируете. Например, в MS x64 ABI максимальное количество аргументов, передаваемых через регистры, равно 4. ABI "System V" (используемый в ОС, отличных от Windows) использует больше регистров, поэтому использование 4 аргументов довольно переносимо.
Семь вещей в краткосрочной памяти?
Что ж. Это практическое правило. Когда вы кодируете тело функции, вас не волнует ее имя, а возвращаемое значение и его назначение тесно связаны.
8. порядок параметров
Меньше - и вы теряете гибкость.
Просто ссылка здесь этот вопрос, который является практическим примером, сколько параметров слишком много ...