Смешивает основанные на конструкторе и основанные на методе set инжекции плохая вещь?

У меня есть класс для импорта продуктов от операции файла CSV, которая требует приблизительно 7 параметров. Это - информация, которая определенно необходима для средства импорта.

Все это параметры имеет то же время жизни. В конце у нас должен быть Неизменный Объект.

Я также боялся перечислять всех их в конструкторе из-за его влияния к удобочитаемости и решил переместить 3 из них к инжекции методов set. Но очевидно это не изящное решение.

Вопросы:

1) Смешивает основанные на конструкторе и основанные на методе set инжекции плохая практика?

2) Как эта конкретная проблема может быть решена?

Я думал о применении, "Представляют Объект параметра" рефакторинг Martin Fowler, но существует проблема с этим.

4 Параметра могут быть перемещены в Объект параметра довольно легко (customerId, спроектированы, languageId и т.д.) - все целые числа.

Другие 3 параметра являются объектом, который я ввожу (он требуется для Ложных модульных тестов).

13
задан finnw 31 December 2009 в 15:40
поделиться

1 ответ

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

Важно понимать, когда использовать каждый шаблон.

  • Инъекция конструктора должна быть шаблоном по умолчанию. Он очень прост в реализации и может гарантировать инварианты: назначьте его в поле только для чтения, чтобы обеспечить инварианты потребителя.
  • Инъекция свойств может быть использована, когда у вас есть хорошая Local Default реализация, но вы хотите следовать Open/Closed Principle и позволить продвинутым пользователям расширить класс, предоставив альтернативную реализацию.

Вы никогда не должны применять Property Injection из-за косметики конструктора.

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

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

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

public MyClass(IDep1 dep1, IDep2 dep2, IDep3 dep3, IDep4 dep4, IDep5 dep5)

После применения некоторого анализа, вы выясняете, что в данном случае IDep1, IDep3 и IDep4 будут использоваться вместе определенным образом. Это позволит вам ввести сервис агрегации, который инкапсулирует их следующим образом:

public class AggService : IAggService
{
    public AggService(IDep1 dep1, IDep3 dep3, IDep4 dep4)
    {
        // ...
    }

    // ...
}

Теперь вы можете переписать исходный конструктор на:

public MyClass(IAggService aggSrvc, IDep2 dep2, IDep5 dep5)

и так далее....

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

26
ответ дан 1 December 2019 в 21:24
поделиться