День 2311. #ЗаметкиНаПолях
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Окончание
Начало
Продолжение
Защищаем Внутреннее Состояние Агрегата
// Order.cs (вырезка)
private readonly List<OrderItem> _items = new();
public IReadOnlyCollection<OrderItem> Items
=> _items.AsReadOnly(); // C# 12 -> [.._items]
private void AddItem(Guid id, int quantity,
decimal price, bool isVip)
{
if (quantity <= 0)
throw new ArgumentException("Количество должно быть положительным");
var finalPrice = isVip
? price * 0.95m
: price;
_items.Add(
new OrderItem(id, quantity, finalPrice)
);
RecalculateTotal();
}
private void EnsureCreditWithinLimit(Customer customer)
{
if (customer.CreditUsed + Total > customer.CreditLimit)
throw new InvalidOperationException("Кредитный лимит превышен");
}
Зачем?
1. Инкапсуляция
Потребители не могут напрямую изменять _items, гарантируя сохранение инвариантов.
2. Самозащита
Модель домена защищает свою собственную согласованность, а не полагается на проверки на уровне сервисов.
3. Истинный ООП
Объекты теперь объединяют данные и поведение, как и задумано объектно-ориентированным программированием.
4. Более простые сервисы
Сервисы приложений могут сосредоточиться на координации, а не на бизнес-правилах.
Сокращаем слой приложения до чистой оркестрации
public void PlaceOrder(
Guid customerId,
IEnumerable<OrderLineDto> lines)
{
var customer = _db.Customers.Find(customerId);
if (customer is null)
throw new ArgumentException("Клиент не найден");
var input = lines.Select(l => (l.ProductId, l.Quantity));
var order = Order.Create(
customer, input,
_pricingService, _inventoryService);
_db.Orders.Add(order);
_db.SaveChanges();
}
Метод PlaceOrder сокращается в 3 раза, при этом бизнес-логика отсутствует.
Что мы получили
- Агрегат владеет всеми бизнес-правилами; сервис только оркеструет.
- Чистые тесты предметной области — контейнер базы данных не требуется.
- Большинство изменений изолированы в агрегате Order.
Итого
Настоящая ценность рефакторинга анемичных моделей не техническая, а стратегическая. Переместив бизнес-логику ближе к данным, мы:
- Уменьшили площадь распространения изменений;
- Сделали бизнес-правила явными и проверяемыми.
Именно так устаревшие системы превращаются в удобные в обслуживании архитектуры.
Источник: https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
>>Click here to continue<<