Выносишь ли 5 DTO с одинаковыми полями в одно?

«Выносишь ли 5 DTO с одинаковыми полями в одно?» — вопрос из категории Архитектура, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Да, если DTO (Data Transfer Object) имеют полностью идентичную структуру и семантику, я выношу их в общий базовый класс или интерфейс. Это следует принципу DRY (Don't Repeat Yourself) и упрощает поддержку.

Пример на TypeScript для Node.js/Express:

// 1. Общий базовый интерфейс
interface BaseUserDto {
    email: string;
    firstName: string;
    lastName: string;
}

// 2. Специфичные DTO наследуют или расширяют базовый
interface UserCreateDto extends BaseUserDto {
    password: string; // Дополнительное поле только для создания
}

interface UserUpdateDto extends BaseUserDto {
    // Пока полей нет, но структура общая
}

interface UserResponseDto extends BaseUserDto {
    id: string;
    createdAt: Date;
}

// 3. Использование в контроллере Express
app.post('/users', (req: Request<{}, {}, UserCreateDto>, res: Response) => {
    // Валидация и обработка req.body
});

app.patch('/users/:id', (req: Request<{ id: string }, {}, UserUpdateDto>, res: Response) => {
    // Обновление пользователя
});

Когда НЕ стоит объединять:

  • Если DTO могут эволюционировать по-разному (например, в UserUpdateDto поле email станет опциональным, а в UserCreateDto — обязательным).
  • Если они используются в разных bounded context'ах (доменная модель разная). В таких случаях дублирование может быть менее вредным, чем неправильная абстракция.