> Насколько жестко проект был разделен на ограниченные контексты и агрегаты в DDD (JavaScript)
Уровень: senior · Роль: frontend · Язык: JavaScript · Категория: Технические вопросы
Компании: Mosline
Стек: Node.js, JavaScript
> Пример ответа
Короткий ответ
Проект был разделён на ограниченные контексты по бизнес-доменам: каталог, корзина, заказы, платежи, пользователи. Каждый контекст имел чёткие границы через API и изолированное хранилище. Агрегаты внутри контекстов были минимальными - например, Order как корень с OrderItem как value object. Жёсткость проявлялась в запрете прямого доступа к данным соседнего контекста и строгой валидации инвариантов внутри агрегата.
Подробное объяснение
Ограниченные контексты (bounded contexts) в этом проекте определялись на основе границ бизнес-логики, а не технических слоёв. Каждый контекст имел:
- собственное хранилище (отдельная таблица или коллекция в БД)
- явный API для взаимодействия (REST или events)
- изолированную модель данных, не зависящую от других контекстов
Агрегаты проектировались с учётом консистентности: один агрегат - одна транзакция. Например, Cart содержал только CartItem как value objects, без ссылок на Product напрямую - только productId. Order включал OrderItem и ShippingAddress как value objects, а статус заказа менялся через методы агрегата с проверкой инвариантов (нельзя перейти из "delivered" в "pending").
Границы контекстов были жёсткими: cross-context запросы шли только через API или event bus, никогда через прямые SQL-запросы. Это давало слабую связанность, но требовало больше boilerplate для интеграции.
На практике
В реальной работе это выглядело так:
- каждый контекст - отдельный модуль с чётким public API (например,
CatalogService,OrderService) - внутри модуля - агрегаты с приватными полями и методами для изменения состояния
- для cross-context данных использовались проекции (read models) - например,
OrderSummaryViewсобиралась из событийOrderPlacedиProductUpdated - транзакции не выходили за границы одного агрегата: если нужно обновить и заказ, и склад - использовалась сага (Saga pattern) через event bus
Типичный пример: при оформлении заказа агрегат Order проверял только свои инварианты (корректность суммы, статус). Проверка наличия товара делегировалась внешнему сервису через API, а результат приходил как событие.
Пример кода
JAVASCRIPT// Агрегат Order в контексте заказовclass Order {constructor(id, items, customerId) {this.id = id;this.items = items.map(item => new OrderItem(item.productId, item.quantity, item.price));this.customerId = customerId;this.status = 'pending';this.total = this.calculateTotal();}calculateTotal() {return this.items.reduce((sum, item) => sum + item.price * item.quantity, 0);}confirm() {if (this.status !== 'pending') {throw new Error('Order can only be confirmed from pending status');}this.status = 'confirmed';// событие для внешнего мираthis.events.push(new OrderConfirmedEvent(this.id, this.total));}addItem(productId, quantity, price) {if (this.status !== 'pending') {throw new Error('Cannot modify confirmed order');}this.items.push(new OrderItem(productId, quantity, price));this.total = this.calculateTotal();}}// Value objectclass OrderItem {constructor(productId, quantity, price) {this.productId = productId;this.quantity = quantity;this.price = price;}}
Как отвечать на собеседовании
Начни с чёткого разделения контекстов и объясни, почему выбраны именно такие границы. Упомяни, что агрегаты проектировались с учётом консистентности и инвариантов. Приведи конкретный пример из практики, где жёсткое разделение помогло избежать проблем (например, race condition при параллельных заказах). Покажи понимание trade-off: жёсткие границы усложняют интеграцию, но дают изоляцию и масштабируемость. Не углубляйся в детали реализации БД или фреймворков - фокус на бизнес-логике.
Что проверяет интервьюер
- понимание DDD-терминологии (bounded context, aggregate, value object, invariant)
- умение применять DDD на практике, а не только в теории
- способность объяснить, как жёсткость границ влияет на архитектуру и разработку
- знание trade-off между изоляцией и сложностью интеграции
- опыт работы с event-driven подходами (саги, проекции)
Типичные ошибки
- путать агрегат с простой сущностью (например, делать
Productагрегатом без чётких границ) - нарушать границы контекста: прямой вызов методов другого контекста или общая БД
- игнорировать инварианты агрегата: позволять менять состояние извне без проверок
- делать агрегаты слишком большими (god aggregate), что ломает консистентность
- забывать про eventual consistency между контекстами и пытаться делать distributed transactions
> Похожие задачи по JavaScript
Приходилось ли писать Docker файлы и работать с контейнерами
Какая библиотека для IoC контейнера использовалась
Что такое саги в микросервисах
Что такое двухфазная фиксация в микросервисах
> Похожие задачи по frontend
Была ли архитектура проекта разбита на сервисные слои и ограниченные контексты
Какая библиотека для IoC контейнера использовалась
Что такое DDD
Какие приоритеты при выборе вакансии
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью