Когда я впервые столкнулся с Domain-Driven Design (DDD), у меня возникло ощущение, будто я Алиса, которая преследует Белого Кролика в кроличьей норе. «Нацеливайтесь на ядро бизнеса! Убиквитарный язык! Стратегические слои проектирования!» — кричали книги. Но как эти концепции воплощаются в реальный код? Вы здесь, потому что пролистали бесчисленные учебники и всё ещё задаётесь вопросом, с чего начать. Давайте разберёмся с этой терминологией, используя практичный подход, ориентированный на код.
Трёхногий стул реализации DDD
Прежде чем мы погрузимся в код, давайте визуализируем основу. Думайте о DDD как о трёх взаимозависимых столпах, поддерживающих архитектуру вашего приложения:
Шаг 1: Определите свою основную доменную область
Ваша доменная модель — это не просто «бизнес-логика»; это сердце вашего приложения. Допустим, вы создаёте платформу электронной коммерции. Основная доменная область — это не обработка платежей или управление учётными записями пользователей; это оптимизация оборота запасов и стратегии ценообразования, адаптирующиеся к требованиям рынка.
Чтобы найти свою основную доменную область:
- Проведите «охоту на влияние»: спросите заинтересованные стороны: «Какая функция напрямую влияет на доход?»
- Определите ограничения: какие процессы имеют жёсткие бизнес-правила? (например, «Количество товаров на складе не должно быть отрицательным»)
- Нарисуйте конкурирующие давления: используйте техники Event Storming для визуализации событий предметной области
Шаг 2: Постройте ограниченные контексты
Не все функции заслуживают первого класса в вашей доменной модели. Ограниченные контексты разбивают сложные системы на управляемые части.
Шаг 3: Реализуйте тактические шаблоны
Теперь мы переходим к коду. Тактические шаблоны DDD предоставляют конкретные стратегии реализации.
1. Сущности против объектов-значений
Сущности:
public class Product {
private final String sku;
private Version version; // Сущность отслеживает жизненный цикл
public Product(String sku) {
this.sku = sku;
this.version = new Version();
}
public void updatePrice(BigDecimal newPrice) {
version.increment();
this.price = newPrice;
}
}
Объекты-значения:
public class Money {
private final BigDecimal amount;
private final Currency currency;
public Money(BigDecimal amount, Currency currency) {
this.amount = amount.abs(); // Обеспечиваем бизнес-инварианты
this.currency = currency;
}
public boolean isHigherThan(Money other) {
return this.amount.compareTo(other.amount) > 0;
}
}
Шаг 4: Создайте настройку реализации
Шаблон многоуровневой архитектуры
Шаг 5: Добавьте службы сопоставления контекстов
Реализация границ между контекстами — это не только вопрос сети; это вопрос ответственности за данные.
// Антикоррупционный слой: преобразование данных внешней системы в модель предметной области
public class ThirdPartyPriceServiceProvider {
public ProductPrice getExternalPrice(String sku) {
ExternalPriceResponse response = restTemplate...
return new ProductPrice(
response.getCurrency(),
response.getAmount(),
response.isPromotional()
);
}
}
Шаг 6: Установите цикл разработки
Когда прекратить усложнять
Не каждому проекту нужен DDD. Если вы создаёте:
- Прототип концепции
- Простое CRUD-приложение
- Управленческую систему устаревшего наследия (с осторожностью) … Не поддавайтесь желанию навязывать шаблоны DDD.
Типичные ошибки при реализации
- Ловушка анемичной модели: Доменные объекты, которые являются просто контейнерами данных
- Чрезмерная инженерия: Создание агрегатов для простых структур данных
- Перекрытие контекстов: Тесная связь ограниченных контекстов
- Утомление от шторма событий: Слишком церемониальные сессии моделирования событий
Пример из реальной жизни: Ошибка «Стейк-хауса»
Предположим, вы создаёте систему управления рестораном. Команда с лучшими намерениями может создать:
// Плохой пример
public class Steak {
public CookingMethod cook(CookingMethod method) {
// DTO с некоторыми расчётами
}
}
Но на самом деле основная доменная область, скорее всего, связана с оптимизацией цен на основе затрат на ингредиенты и предпочтений клиентов, а не с самим процессом приготовления.
Финальная проверка: Готовы ли вы к DDD?
- Участвуют ли эксперты предметной области в сеансах моделирования?
- Есть ли чёткое различие между основными и вспомогательными поддоменами?
- Можете ли вы сформулировать ценность, приносимую каждой службой предметной области?
- Ведёт ли ваша команда глоссарий ключевых бизнес-терминов?
Теперь вперёд и моделируйте предметные области с определённой целью. Помните: DDD — это о целенаправленных компромиссах, а не о создании архитектурных музеев. Как сказал великий философ программного обеспечения: «Лучшая модель предметной области — та, которая упрощает создание следующей функции» (возможно, я это выдумал, но звучит круто).