Сколько аргументов конструктора слишком много? - PullRequest
121 голосов
/ 02 сентября 2008

Допустим, у вас есть класс с именем Customer, который содержит следующие поля:

  • UserName
  • E-mail
  • Имя
  • Фамилия

Скажем также, что в соответствии с вашей бизнес-логикой все объекты Customer должны иметь эти четыре свойства.

Теперь мы можем сделать это довольно легко, заставив конструктор указать каждое из этих свойств. Но довольно легко увидеть, как это может выйти из-под контроля, когда вы вынуждены добавить дополнительные обязательные поля в объект Customer.

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

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

Ответы [ 14 ]

1 голос
/ 02 сентября 2008

Я бы инкапсулировал подобные поля в собственный объект со своей собственной логикой построения / проверки.

Скажем, например, если у вас есть

  • BusinessPhone
  • BusinessAddress
  • HomePhone
  • HomeAddress

Я бы создал класс, который хранит телефон и адрес вместе с тегом, указывающим, является ли он «домашним» или «служебным» телефоном / адресом. А затем уменьшите 4 поля до простого массива.

ContactInfo cinfos = new ContactInfo[] {
    new ContactInfo("home", "+123456789", "123 ABC Avenue"),
    new ContactInfo("biz", "+987654321", "789 ZYX Avenue")
};

Customer c = new Customer("john", "doe", cinfos);

Это должно сделать его менее похожим на спагетти.

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

И следующие также возможные решения:

  • Разложите логику проверки вместо хранения в одном классе. Проверять, когда пользователь вводит их, а затем снова проверять на уровне базы данных и т. Д. *
  • Создайте CustomerFactory класс, который помог бы мне построить Customer s
  • @ Марсио тоже интересно ...
1 голос
/ 02 сентября 2008

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

0 голосов
/ 02 сентября 2008

Просто используйте аргументы по умолчанию. На языке, который поддерживает аргументы метода по умолчанию (например, PHP), вы можете сделать это в сигнатуре метода:

public function doSomethingWith($this = val1, $this = val2, $this = val3)

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

Конечно, вы также можете установить значения по умолчанию при объявлении полей, если сочтете это уместным.

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

0 голосов
/ 02 сентября 2008

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

...