Не обязательно плохо смешивать внедрение конструктора и внедрение свойств, но это может быть не так часто. В качестве общей стратегии избегайте внедрения свойств, так как его гораздо сложнее реализовать правильно (это может показаться нелогичным, но это правда).
Важно понимать, когда использовать каждый шаблон.
- Внедрение конструктора должно быть шаблоном внедрения по умолчанию. Его очень легко реализовать, и он может гарантировать инварианты: назначьте его в поле только для чтения, чтобы обеспечить инварианты потребителя.
- Внедрение свойств можно использовать, если у вас есть хорошая реализация Local Default, но вы хотите следовать Принцип Открытости/Закрытости и позволить опытным пользователям расширить класс, предоставив альтернативную реализацию.
Вы никогда не должны применять внедрение свойств из-за косметики конструктора.
Если вам требуется слишком много зависимостей, это может означать, что вы нарушаете принцип единой ответственности – class просто пытается сделать слишком много одновременно.
Вместо того, чтобы вводить Parameter Object (в противном случае это хорошее предложение), лучшим вариантом будет инкапсулировать две или более зависимостей в агрегирующую службу, которая управляет взаимодействием этих зависимостей.
Представьте, что ваш исходный конструктор выглядит так:
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, чем когда вы начинали.
person
Mark Seemann
schedule
31.12.2009