Ответ
Domain-Driven Design (DDD) — это методология разработки сложного программного обеспечения, в центре которой находится предметная область (домен) и бизнес-логика. Главная цель — смоделировать бизнес-процессы в коде, используя общий язык (Ubiquitous Language) между разработчиками и экспертами домена.
Ключевые концепции:
- Домен (Domain): Предметная область, для которой создается приложение. Например, «логистика», «банкинг».
- Сущность (Entity): Объект, обладающий уникальным идентификатором и жизненным циклом. Например,
Пользователь
сUserID
. - Объект-значение (Value Object): Неизменяемый (immutable) объект без уникального идентификатора, характеризуемый своими атрибутами. Например,
Адрес
илиДенежнаяСумма
. - Агрегат (Aggregate): Кластер из связанных сущностей и объектов-значений, который рассматривается как единое целое. У агрегата есть корень (Aggregate Root) — единственная сущность, через которую происходит взаимодействие с другими частями агрегата. Это обеспечивает целостность данных и соблюдение бизнес-правил.
- Репозиторий (Repository): Абстракция, которая предоставляет интерфейс для доступа к агрегатам, имитируя коллекцию объектов в памяти. Скрывает детали хранения данных (БД, файлы и т.д.).
Пример на Go:
// Order является корнем агрегата (Aggregate Root).
// Весь агрегат включает Order и OrderItem. ype Order struct {
ID string
CustomerID string
Items []*OrderItem // Коллекция объектов-значений
totalPrice float64
}
// AddItem - метод, инкапсулирующий бизнес-логику.
// Изменения внутри агрегата проходят через его корень.
func (o *Order) AddItem(productID string, quantity int, price float64) {
item := &OrderItem{
ProductID: productID,
Quantity: quantity,
Price: price,
}
o.Items = append(o.Items, item)
o.totalPrice += price * float64(quantity)
}
// OrderItem - объект-значение (Value Object).
// У него нет своего ID, он определяется в контексте заказа.
type OrderItem struct {
ProductID string
Quantity int
Price float64
}
// OrderRepository определяет контракт для хранения и извлечения агрегатов Order.
type OrderRepository interface {
Save(order *Order) error
FindByID(id string) (*Order, error)
}
DDD наиболее эффективен в больших и сложных проектах, где бизнес-логика является основной сложностью.