Сколько переменных должен иметь конструктор? - PullRequest
31 голосов
/ 16 сентября 2009

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

Используя C # (или Java, или любой язык OO), существует ли общее правило, которое указывает, сколько переменных должно быть передано в конструктор? Число переменных, которые я передаю в конструктор расширенных классов, похоже, выходит из-под контроля.

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

Вот пример:

public class A
{
  private int var1;
  private int var2;
  private int var3;

  //3 variables passed in
  public A(int v1, int v2, int v3)
  {
    var1 = v1;
    var2 = v2;
    var3 = v3;
  }

  //Properties (accessors) here
}

public class B : A
{
  private int var4;
  private int var5;

  //5 variables passed in
  public B(int v1, int v2, int v3, int v4, int v5)
  : base(v1,v2,v3)
  {
    var4 = v4;
    var5 = v5;
  }

  //Properties (accessors) here
}

public class C : B
{
  private int var6;
  private int var7;

  //7 variables passed in !!!
  public C(int v1, int v2, int v3, int v4, int v5, int v6, int v7)
  : base(v1,v2,v3,v4,v5)
  {
    var6 = v6;
    var7 = v7;
  }

  //Properties (accessors) here
}

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

Это считается плохой практикой программирования? Есть ли общее ограничение на количество переменных, которые вы должны передать в конструктор?

Ответы [ 12 ]

38 голосов
/ 16 сентября 2009

Для меня правильный ответ:

Вы должны передать столько переменных, сколько требуется для установки объекта в недопустимое состояние.

Все остальное, что является «опцией», я предпочитаю оставлять в качестве свойств, особенно теперь, когда C # предоставляет инициализаторы объектов.

34 голосов
/ 16 сентября 2009

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

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

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

Если параметры не связаны - например, нет смысла группировать их в контейнерный класс - ваш класс, вероятно, делает слишком много вещей. Как правило, нет причин, по которым один класс должен знать о 7 совершенно разных элементах информации. Разбейте свой класс на отдельные классы. Возможно, имеет смысл делегировать параметры 3 и 4 подклассу, а 5, 6 и 7 - другому классу, например, и ваш родительский класс просто координирует операции между ними.

5 голосов
/ 16 сентября 2009

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

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

2 голосов
/ 16 сентября 2009

Как уже говорили другие, здесь нет строгих правил, это действительно зависит. Тем не менее, есть конкретные доказательства того, сколько вещей может уловить мозг человека: это правило 7 + или - 2.

На этот тип вопросов очень хорошо ответил Стив Макконнелл в Code Complete. Я рекомендую вам прочитать эту книгу, если вы еще этого не сделали.

1 голос
/ 16 сентября 2009

Мое эмпирическое правило: 5

Если вам нужно больше, оберните их в структуру или объект.

Это изменяется, когда вам не нужно инициализировать объект. Если я инициализирую объект с помощью контейнера IOC, количество параметров конструкции в основном не ограничено.

1 голос
/ 16 сентября 2009

Одна вещь, которую я люблю в 3,5 рамки ...

new Foo {
    Street = "909 Rose Ave",
    City = "San Diego",
    State = "CA",
    FName = "Joe",
    LName = "Wazowski",
    ID = "987665454"
};

Больше не нужно беспокоиться о слишком большом количестве конструкторов или о слишком большом количестве конструкторов со слишком большим количеством параметров.

0 голосов
/ 30 декабря 2016

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

1) Явно вызванные конструкторы

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

Кроме того, если вы знаете, что ваш класс, вероятно, сможет обрабатывать больше дел, для которых в будущем потребуется больше параметров, я бы обратился непосредственно к struct / class. Например:

скажем, класс должен обрабатывать фильтрацию некоторых объектов на основе некоторых критериев. В начале будет только 2-3 критерия. Зная, что в будущем у него будет гораздо больше критериев, я бы сразу отправил объект FilterValue с самого начала.

2) Неявно называемые конструкторы

В типичном случае используется Внедрение зависимостей . Почти во всех случаях вводятся все параметры конструктора, поэтому создание инфраструктуры для вас - задача создания объектов для вас.

Здесь «здравый смысл» не применяется, поскольку можно вводить столько служб, сколько необходимо. E.g.:

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

Кстати, максимальное теоретическое количество параметров для метода должно быть достаточно большим, чтобы его никогда не достигать: C # и Java .

0 голосов
/ 17 сентября 2009

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

0 голосов
/ 16 сентября 2009

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

0 голосов
/ 16 сентября 2009

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

Это запах в книге Рефакторинга Мартина Фаулера. Эта веб-страница содержит ссылки на стандартные рефакторинги, которые помогают.

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

...