TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2786 2.34K
День 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
  • 👍 4
  • 👎 2
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 →