Подтвердить что ты не робот

Сколько переменных должно иметь конструктор?

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

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

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

Вот пример:

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
}

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

Что-нибудь еще, что является "опцией", я предпочитаю оставить как свойства, особенно теперь, когда С# предоставляет инициализаторы объектов.

Ответ 3

Сложно поставить тяжелое, быстрое число в то, что "слишком много". Реальный вопрос: что делает ваш класс? Является ли класс слишком много? Если это так, пришло время разбить класс на более мелкие и более сжатые классы.

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

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

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

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

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

Ответ 7

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

Например, если у вас был класс Rectangle, может возникнуть смысл сделать конструктор Rectangle (двойная ширина, двойная высота) и сделать конструктор Rectangle() закрытым.

Ответ 8

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

Ответ 9

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

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

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

Ответ 10

IMHO, используя TDD, является полезной перспективой для оценки этой проблемы. Когда ваш ctor трудно применить к unit test ctor или SetUp(), аргументы инициализации /factory слишком велики и относительно жестко связаны.

Ответ 11

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

Ответ 12

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

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

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

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

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

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

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

Здесь "здравый смысл" не применяется, так как можно вводить столько услуг, сколько необходимо. Например:.

Если сохранение данных выполняется с использованием шаблона Unit of Work, который агрегирует изменения из любого количества репозиториев, чем Unit of work class будет вводиться всеми используемыми репозиториями. Более подробную информацию можно найти в этом ответе от CodeReview.

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