> Какие тактические шаблоны DDD вы знаете и применяли (JavaScript)

Уровень: senior · Роль: frontend · Язык: JavaScript · Категория: Технические вопросы

Компании: Mosline

Стек: Node.js, JavaScript

> Пример ответа

Короткий ответ

Из тактических шаблонов DDD я применял Entity, Value Object, Aggregate, Repository, Domain Service, Factory и Specification. На фронтенде чаще всего использовал Value Object для валидации и форматирования данных, Repository для абстракции доступа к API и Aggregate для управления сложными формами с инвариантами.

Подробное объяснение

Тактические шаблоны DDD помогают организовать бизнес-логику в коде. Основные из них:

  • Entity - объект с уникальным идентификатором и изменяемым состоянием (например, пользователь, заказ)
  • Value Object - неизменяемый объект, определяемый своими атрибутами (например, Email, Money, Coordinates)
  • Aggregate - группа связанных Entity и Value Object с единой точкой входа (корнем агрегата)
  • Repository - абстракция для доступа к хранилищу, скрывающая детали persistence
  • Domain Service - stateless сервис для операций, не вписывающихся в один Entity
  • Factory - отдельный объект или метод для создания сложных доменных объектов
  • Specification - объект, инкапсулирующий бизнес-правило для фильтрации или проверки

На фронтенде эти шаблоны адаптируются: Repository работает с API вместо БД, Value Object часто используются для валидации форм, а Aggregate - для управления состоянием сложных UI-компонентов.

На практике

В проекте с финансовым дашбордом я использовал Value Object для сумм и валют - это гарантировало корректное форматирование и предотвращало арифметические ошибки. Repository инкапсулировал вызовы к REST API с кэшированием и обработкой ошибок. Aggregate применял для управления корзиной заказов: корень агрегата (Cart) контролировал добавление/удаление товаров и проверял лимиты.

В Node.js бэкенде использовал Domain Service для расчета комиссий и налогов, а Specification - для фильтрации транзакций по сложным правилам (например, "транзакции за последний месяц с суммой > 1000 и статусом pending").

Пример кода

JAVASCRIPT
// Value Object для Email
class Email {
constructor(value) {
if (!Email.isValid(value)) {
throw new Error('Invalid email');
}
this.value = value;
Object.freeze(this);
}
static isValid(email) {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
equals(other) {
return other instanceof Email && this.value === other.value;
}
}
// Repository для пользователей
class UserRepository {
constructor(apiClient) {
this.apiClient = apiClient;
}
async findById(id) {
const data = await this.apiClient.get(`/users/${id}`);
return new User(data);
}
async save(user) {
const data = user.toJSON();
await this.apiClient.put(`/users/${user.id}`, data);
}
}
// Aggregate: корзина заказов
class Cart {
constructor(id) {
this.id = id;
this.items = [];
this.discount = 0;
}
addItem(product, quantity) {
if (quantity <= 0) throw new Error('Quantity must be positive');
if (this.items.length >= 50) throw new Error('Cart is full');
this.items.push({ product, quantity });
}
getTotal() {
const subtotal = this.items.reduce((sum, item) =>
sum + item.product.price * item.quantity, 0);
return subtotal - this.discount;
}
}

Как отвечать на собеседовании

Начни с перечисления шаблонов, которые реально применял. Приведи конкретный пример из своего опыта - это покажет глубину понимания. Объясни, почему выбрал именно этот шаблон и какие проблемы он решил. Упомяни адаптацию DDD для фронтенда - это демонстрирует гибкость мышления. Не углубляйся в теорию, если не спрашивают.

Что проверяет интервьюер

  • Понимание различий между Entity и Value Object
  • Умение выбирать подходящий шаблон под задачу
  • Практический опыт применения DDD в реальных проектах
  • Способность адаптировать паттерны под контекст (фронтенд vs бэкенд)
  • Знание границ применения: когда DDD избыточен

Типичные ошибки

  • Путать Entity и Value Object (например, делать Email изменяемым)
  • Использовать Repository напрямую из UI-компонентов, нарушая слои
  • Создавать гигантские Aggregate, нарушающие инварианты
  • Применять DDD везде без учета сложности проекта (overengineering)
  • Не учитывать, что на фронтенде DDD часто требует адаптации из-за асинхронности и UI-состояний

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью