Ответ
Domain-Driven Design (DDD) — это подход к разработке программного обеспечения, который фокусируется на предметной области (домене) и бизнес-логике. Главная цель — смоделировать сложный домен в коде, используя терминологию и концепции, понятные как разработчикам, так и экспертам в предметной области.
DDD особенно полезен в больших и сложных проектах, где простая CRUD-архитектура не справляется.
Ключевые концепции DDD
-
Ubiquitous Language (Единый язык): Создание общего языка, который используется всеми участниками проекта (разработчиками, менеджерами, экспертами). Этот язык отражается в коде: в названиях классов, методов, модулей.
-
Bounded Context (Ограниченный контекст): Четкое определение границ, в рамках которых модель и Единый язык имеют смысл. Например, в контексте "Продажи"
Товар
может иметь цену и скидку, а в контексте "Склад" — вес и местоположение. -
Layers (Слои): Классическая слоистая архитектура в DDD:
- Domain Layer: Сердце приложения. Содержит бизнес-логику, сущности, агрегаты. Не зависит от других слоев.
- Application Layer: Оркестрирует выполнение бизнес-сценариев (use cases), делегируя работу объектам домена.
- Infrastructure Layer: Технические детали: работа с базами данных, файловой системой, внешними API. Реализует интерфейсы, определенные в доменном и прикладном слоях.
- Presentation/UI Layer: Взаимодействие с пользователем (API-эндпоинты, веб-интерфейс).
Применение в Go (Тактические паттерны)
Поскольку в Go нет классов, паттерны DDD реализуются с помощью структур и интерфейсов.
-
Entity (Сущность): Объект с уникальным идентификатором и жизненным циклом. В Go это структура с полем ID.
type User struct { ID uuid.UUID Email string // ... другие поля }
-
Value Object (Объект-значение): Неизменяемый объект без идентификатора, характеризуемый своими атрибутами (например,
Money
,DateRange
).type Money struct { Amount decimal.Decimal Currency string }
-
Aggregate (Агрегат): Кластер из связанных сущностей и объектов-значений, который рассматривается как единое целое. У агрегата есть корень (Aggregate Root), который является единственной точкой входа для изменения агрегата.
-
Repository (Репозиторий): Интерфейс для доступа к агрегатам, имитирующий коллекцию объектов в памяти. Он скрывает детали хранения (SQL, NoSQL).
// В доменном слое (domain/user.go) package domain type UserRepository interface { FindByID(ctx context.Context, id uuid.UUID) (*User, error) Save(ctx context.Context, user *User) error } // В инфраструктурном слое (infrastructure/postgres_user_repo.go) package infrastructure type PostgresUserRepo struct { db *sql.DB } func (r *PostgresUserRepo) FindByID(ctx context.Context, id uuid.UUID) (*domain.User, error) { // ... логика запроса к PostgreSQL }
Преимущества и недостатки в Go
- Преимущества: Четкая структура, тестируемость, масштабируемость, бизнес-логика изолирована от технических деталей.
- Недостатки: Может быть избыточным для простых CRUD-приложений. Требует дисциплины и глубокого понимания предметной области.