TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2785 2.45K
День 2310. #ЗаметкиНаПолях
Уходим от Анемичных Моделей. Пример DDD-Рефакторинга. Продолжение

Начало

Пошаговый рефакторинг
Цель здесь не в погоне за чистотой или академическим DDD. Она в постепенном улучшении связности и создании пространства для самовыражения домена. На каждом шаге мы спрашиваем: должно ли это поведение принадлежать домену? Если да, мы добавляем его внутрь домена.

Внедрение логики создания и проверки
Первый шаг — сделать агрегат ответственным за самосборку. Статический метод Create даёт нам единую точку входа, где все инварианты могут работать по принципу «fail fast».

Хотя добавление проверки остатков в Order улучшает тестируемость, оно связывает поток заказов с доступностью товаров на складе. В некоторых доменах лучше смоделировать это как событие домена и проверять асинхронно.
// Order.cs (Фабричный метод)
public static Order Create(
Customer customer,
IEnumerable<(Guid productId, int quantity)> lines,
IPricingService pricingService,
IInventoryService invService)
{
var order = new Order(customer.Id);

foreach (var (id, quantity) in lines)
{
if (invService.GetStock(id) < quantity)
throw new InvalidOperationException("Товара недостаточно");

var price = pricingService.GetPrice(id);
order.AddItem(id, quantity,
price, customer.IsVip);
}

order.EnsureCreditWithinLimit(customer);

return order;
}


Зачем мы это сделали?
Создание заказа теперь быстро завершается неудачей, если какой-либо инвариант нарушен. Сервис больше не занимается микроуправлением запасами или скидками.

Обратите внимание, как мы теперь следуем принципу «Скажи, не спрашивай». Вместо того, чтобы сервис проверял условия и затем манипулировал заказом, мы говорим заказу создать себя с необходимыми встроенными проверками. Это фундаментальный сдвиг в сторону инкапсуляции.

Замечание: О внедрении сервисов в методы домена
Передача сервисов, таких как IPricingService или IInventoryService, в метод домена, такой как Order.Create, на первый взгляд может показаться нетрадиционной и спорной. Но это осознанный выбор дизайна: он сохраняет оркестрацию внутри модели домена, где естественным образом находится бизнес-логика вместо того, чтобы раздувать сервис приложения процедурными рабочими процессами.

Такой подход сохраняет автономность сущности, при этом по-прежнему согласуясь с принципами внедрения зависимостей: зависимости передаются явно, а не разрешаются изнутри. Это мощный метод, но его следует использовать избирательно — только тогда, когда операция явно вписывается в сферу ответственности домена и выигрывает от прямого доступа к внешним сервисам.

Окончание следует…

Источник:
https://www.milanjovanovic.tech/blog/from-anemic-models-to-behavior-driven-models-a-practical-ddd-refactor-in-csharp
  • 👍 8
More from @netdeveloperdiary
  1. Oct 2, 2026День 2802. #Карьера #Юмор Секреты Программирования, Известные Только Легендам Ещё один пос…
  2. Oct 1, 2026Post #3357
  3. Sep 30, 2026Post #3356
  4. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  5. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  6. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →