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

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

Ответы

Ответ 1

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

Передача множества параметров может быть хорошим признаком плохого разделения проблем (т.е. ваш метод делает слишком много), но похоже, что в этом случае вы проходите в четко определенном наборе элементов для их итерации каким-то образом. Учитывая синтаксис инициализатора коллекции в С# 3, я бы порекомендовал IEnumerable почти в каждом случае по списку параметров, которые были бы чем-то вроде Type a, Type b, Type c....

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

Node BuildTree( Node parent, Node child1, Node child2...)

Я бы, вероятно, преследовал нечто большее:

void ConstructChildren( this Node parent, IEnumerable<Node> children)

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

Ответ 2

Стив Макконнелл обращается к этому в Code Complete, цитируя исследование, в котором говорится, что люди не могут обрабатывать более семи фрагментов информации за раз, делая семь пределов здравого смысла, где бы они ни практиковались.

В заключительном абзаце этого раздела (стр. 178 во втором издании) он пишет:

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

Ответ 3

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

Альтернативой тоннам параметров было бы создать класс операций, то есть заменить:

func(boo, far, lint, pizza, flags);

с

var action = new DoSomethingObject(boo, far, lint);
action.Food = pizza;
action.Go(flags);

Это имеет несколько преимуществ перед функцией:

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

Ответ 4

Если вы пройдете неизвестное количество аргументов, вы должны использовать varargs или передать IEnumerable. Конечно, иногда вы передаете фиксированное количество элементов одного типа. В последнем случае фиксированное число должно следовать из цели метода.

Ответ 5

Кроме того, для большей читаемости сайта вы можете использовать список параметров params (ранее упомянутые varargs), поэтому вместо

void ConstructChildren( Node parent, IEnumerable<Node> children)
....
List<Node> children = new List<Node> {child1, child2, child3};
ConstructChildren(parent, children);

Я бы использовал

void ConstructChildren( Node parent, params Node[] children)
...
ConstructChildren( parent, child1, child2, child3);

Однако синтаксис params становится уродливым, если вы используете более 5-6-7 элементов в коллекции для детей.