TG Telegram Group & Channel
.NET Разработчик | United States America (US)
Create: Update:

День 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

День 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<<

.NET Разработчик




Share with your best friend
VIEW MORE

United States America Popular Telegram Group (US)