Почему бы не использовать контейнер IoC для разрешения зависимостей для сущностей / бизнес-объектов? - PullRequest
75 голосов
/ 29 января 2011

Я понимаю концепцию 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. Теперь пара вопросов.

  1. Считается ли плохой практикой, что ваши сущности зависят от внешних классов, таких как ShipQuoter? Устранение этих зависимостей, кажется, ведет меня к анемичной области, если я правильно понимаю определение.

  2. Является ли плохой практикой использование контейнера IoC для разрешения этих зависимостей и создания сущности при необходимости? Возможно ли это сделать?

Спасибо за понимание.

Ответы [ 2 ]

86 голосов
/ 29 января 2011

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

Если, например, вы внедряете репозиторий в свои сущности, у вас есть эффективная реализация шаблона Active Record .Некоторым людям этот шаблон нравится за удобство, которое он предоставляет, в то время как другие (например, я) считают его запахом кода или анти-шаблоном, поскольку он нарушает Принцип единой ответственности (SRP).

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

Я боролся со всем этим долгое время, пока янатолкнулся на статью Грега Янга (заброшенную) о DDDD , где он объясняет, почему стереотипная архитектура n-уровня / n-слоя всегда будет CRUDy (и, следовательно, довольно анемичной).

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

На второй вопрос легче ответить,Вы всегда можете использовать Abstract Factory для создания экземпляров во время выполнения .С Castle Windsor вы даже можете использовать Typed Factory Facility, освобождая вас от бремени внедрения фабрик вручную.

1 голос
/ 22 сентября 2017

Я знаю, что это старый пост, но хотел добавить.Сущность домена не должна сохраняться сама по себе, даже если вы передаете абстрагированный репозиторий в ctor.Причина, по которой я высказываю предположение, заключается не только в том, что она нарушает SRP, но и противоречит агрегации DDD.Позвольте мне объяснить, DDD подходит для сложных приложений с глубокими графами, поэтому мы используем агрегированные или составные корни для сохранения изменений в базовых «потомках», поэтому, когда мы внедряем постоянство в отдельных детей, мы нарушаем отношения, которые дети имеют ксоставной или совокупный корень, который должен «отвечать» за жизненный цикл или агрегацию.Конечно, составной корень или агрегат также не сохраняют свой собственный граф.Еще одна проблема с внедрением зависимостей объектов DDD заключается в том, что внедренный объект домена фактически не имеет состояния, пока не произойдет какое-либо другое событие для увлажнения его состояния.Любой потребитель кода будет вынужден сначала инициировать или настроить объект домена, прежде чем он сможет вызвать деловое поведение, которое нарушает инкапсуляцию.

...