Почему бы не использовать контейнер IoC для разрешения зависимостей для объектов/бизнес-объектов?
Я понимаю концепцию DI, но я просто изучаю, что могут сделать различные контейнеры IoC. Похоже, что большинство людей выступают за использование контейнеров IoC для подключения служб без учета состояния, но как их использовать для объектов с сохранением состояния, таких как объекты?
Правильно или неправильно, я обычно накладываю свои сущности на поведение, даже если для этого поведения требуется внешний класс. Пример:
public class Order : IOrder
{
private string _ShipAddress;
private IShipQuoter _ShipQuoter;
public Order(IOrderData OrderData, IShipQuoter ShipQuoter)
{
// OrderData comes from a repository and has the data needed
// to construct order
_ShipAddress = OrderData.ShipAddress; // etc.
_ShipQuoter = ShipQuoter;
}
private decimal GetShippingRate()
{
return _ShipQuoter.GetRate(this);
}
}
Как вы можете видеть, зависимыми являются Constructor Injected. Теперь на пару вопросов.
-
Является ли плохая практика, чтобы ваши объекты зависели от внешних классов, таких как ShipQuoter? Устранение этих зависимостей, по-видимому, приводит меня к анемическому домену, если я правильно понимаю определение.
-
Неправильно ли использовать контейнер IoC для разрешения этих зависимостей и при необходимости создавать объект? Возможно ли это сделать?
Спасибо за понимание.
Ответы
Ответ 1
Первый вопрос - самый трудный ответ. Неужели плохая практика заключается в том, что сущности зависят от внешних классов? Это, конечно, не самая распространенная вещь.
Если вы, например, вводите репозиторий в свои объекты, у вас есть реализация Active Record pattern. Некоторым людям нравится этот шаблон для удобства, который он предоставляет, в то время как другие (например, я) считают его запахом кода или анти-шаблоном, поскольку он нарушает принцип единой ответственности (SRP).
Вы можете утверждать, что вложение других зависимостей в Entities приведет вас в том же направлении (в сторону от SRP). С другой стороны, вы, безусловно, правы, что если вы этого не сделаете, то тяга идет к Anemic Domain Model.
Я долгое время боролся со всем этим, пока не наткнулся на Грега Янга (отброшенного) [на DDDD] [4], где он объясняет, почему стереотипная архитектура n-уровня/n-уровня всегда будет CRUDy (и, следовательно, довольно анемичный).
Перемещение нашей фокусировки на моделирование Объекты домена как Команды и события вместо существительных, похоже, позволяют нам создать подходящую объектно-ориентированную модель домена.
Второй вопрос легче ответить. Вы всегда можете использовать Аннотация Factory для создания экземпляров во время выполнения. С Castle Windsor вы даже можете использовать Типированный механизм Factory, освободив вас от бремени внедрения фабрик вручную.
Ответ 2
Я знаю, что это старый пост, но хотелось добавить. Сущность домена не должна сохраняться, даже если вы переходите в абстрактный репозиторий в ctor. Причина, по которой я предлагаю, заключается не только в том, что она нарушает SRP, но и вопреки агрегации DDD. Позвольте мне объяснить, что DDD подходит для сложных приложений с глубокими графами, поэтому мы используем совокупные или составные корни для сохранения изменений в "детях", поэтому, когда мы добавляем постоянство в отдельные дети, мы нарушаем отношения, которые дети имеют к составной или совокупный корень, который должен "отвечать" за жизненный цикл или агрегацию. Конечно, составной корень или совокупность не сохраняются и в собственном графике. Другим является использование зависимостей DDD от инъекций в том, что объект проинъективного домена фактически не имеет состояния, пока не произойдет какое-либо другое событие, чтобы увлажнить его состояние. Любому потребителю кода будет принудительно инициировать или настраивать объект домена прежде, чем они смогут вызвать бизнес-поведение, которое нарушает инкапсуляцию.