Поскольку «модель анемичной области» является анти-шаблонной, почему существует так много систем, которые реализуют это?
Я думаю, что есть несколько причин
1. Сложность системы
В простой системе (которая содержит почти все примеры и примеры кода, которые вы можете найти в Интернете), если я хочу реализовать:
Добавление товара в заказ
Я поставил эту функцию на Заказ
public void Order.AddOrderLine(Product product)
{
OrderLines.Add(new OrderLine(product));
}
Хороший и супер ориентированный на объект.
Теперь давайте скажем, что мне нужно убедиться, что мне нужно проверить, что товар существует в инвентаре, и выбросить исключение, если его нет.
Я больше не могу ставить его на заказ, так как не хочу, чтобы мой заказ зависел от инвентаря, поэтому теперь он должен перейти на службу
public void OrderService.AddOrderLine(Order order, Product product)
{
if (!InventoryService.Has(product)
throw new AddProductException
order.AddOrderLine(product);
}
Я также мог бы передать IInventoryService в Order.AddOrderLine, что является еще одним вариантом, но все равно делает Order зависимым от InventoryService.
В Order.AddOrderLine все еще есть некоторая функциональность, но обычно она ограничена областью заказа, хотя, по моему опыту, бизнес-логика выходит за рамки объема заказа.
Когда система представляет собой нечто большее, чем просто CRUD, в итоге вы получите большую часть своей логики в OrderService и очень мало в Order.
2. Взгляд разработчика на ООП
В интернете много горячих дискуссий о том, какая логика должна применяться к сущностям.
что-то вроде
Order.Save
Должен ли Порядок знать, как себя спасти или нет? Допустим, у нас есть хранилища для этого.
Теперь можно заказать добавить строки заказа? Если я попытаюсь разобраться в этом, используя простой английский, это тоже не имеет смысла. Пользователь добавляет продукт в заказ, поэтому мы должны сделать User.AddOrderLineToOrder ()? Это похоже на излишество.
Как насчет OrderService.AddOrderLine (). Теперь это имеет смысл!
Мое понимание ООП состоит в том, что для инкапсуляции вы помещаете функции в классы, где функция должна будет получить доступ к внутреннему состоянию класса. Если мне нужен доступ к коллекции Order.OrderLines, я помещаю Order.AddOrderLine () в Order. Таким образом, внутреннее состояние класса не раскрывается.
3. Контейнеры IoC
Системы, в которых используются контейнеры IoC, обычно полностью анемичны.
Это потому, что вы можете тестировать свои сервисы / репозитории, которые имеют интерфейсы, но не могут тестировать доменные объекты (легко), если вы не установите интерфейсы на всех из них.
Поскольку «IoC» в настоящее время хвалят как решение всех ваших проблем с программированием, многие люди слепо следуют ему, и в результате получаются модели Anemic Domain Models.
4. ООП сложно, процедурно легко
У меня есть немного " Проклятие знания " на этом, но я обнаружил, что
для новых разработчиков, имеющих DTO и Сервисы, намного проще, чем Rich Domain.
Возможно, это связано с тем, что с Rich Domain труднее узнать, на какие классы поместить логику. Когда создавать новые классы? Какие шаблоны использовать? и т.д ..
С сервисами без сохранения состояния вы просто добавляете их в службу с ближайшим именем.