Clean Architecture: обзор
Clean Architecture — архитектурная концепция Роберта Мартина, разделяющая систему на концентрические слои с правилом зависимости: внутренние слои не зависят от внешних.
Зачем нужно
Clean Architecture решает главную проблему долгосрочных проектов — «прилипание» бизнес-логики к фреймворку, БД или UI. Когда логика независима, её можно тестировать в изоляции, менять React на Vue или PostgreSQL на MongoDB без переписывания ядра. Архитектура описывает не конкретный фреймворк, а принципы организации зависимостей.
Где используется
- Крупные SPA-приложения, где бизнес-логика сложная и критичная
- Серверные Node.js-приложения с NestJS или чистым Express
- Проекты с высокими требованиями к тестируемости (unit тесты без браузера/БД)
- Команды, где несколько разработчиков параллельно работают над разными слоями
- Долгосрочные продукты, где предполагается смена технологий
Основной контент
Слои Clean Architecture (снаружи → внутрь)
┌─────────────────────────────────────┐
│ Frameworks & Drivers │ ← React, Express, Prisma
│ ┌─────────────────────────────┐ │
│ │ Interface Adapters │ │ ← Controllers, Presenters, Gateways
│ │ ┌───────────────────────┐ │ │
│ │ │ Use Cases │ │ │ ← Бизнес-правила приложения
│ │ │ ┌─────────────────┐ │ │ │
│ │ │ │ Entities │ │ │ │ ← Бизнес-правила предметной области
│ │ │ └─────────────────┘ │ │ │
│ │ └───────────────────────┘ │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
Правило зависимости: зависимости направлены только внутрь. Entities ничего не знают об Use Cases, Use Cases — о Controllers, Controllers — о React.
Пример структуры проекта
src/
domain/ ← Entities
entities/
User.ts
Order.ts
repositories/ ← интерфейсы (abstractions)
IUserRepository.ts
application/ ← Use Cases
use-cases/
CreateUser.ts
GetUserById.ts
infrastructure/ ← конкретные реализации
repositories/
PrismaUserRepository.ts
http/
express/
UserController.ts
presentation/ ← UI
components/
UserCard.tsx
Пример Use Case (без зависимости от фреймворка)
// domain/repositories/IUserRepository.js — интерфейс (контракт)
// { findById(id), save(user), findByEmail(email) }
// application/use-cases/CreateUser.js
class CreateUserUseCase {
constructor(userRepository, emailService) {
this.userRepository = userRepository;
this.emailService = emailService;
}
async execute({ name, email, password }) {
// Проверка дубликата — бизнес-правило
const existing = await this.userRepository.findByEmail(email);
if (existing) {
throw new Error('Пользователь с таким email уже существует');
}
const user = { id: crypto.randomUUID, name, email, createdAt: new Date };
await this.userRepository.save(user);
await this.emailService.sendWelcome(email, name);
return user;
}
}
// Use Case не знает про Express, React, Prisma, Postgres
// Тест: передать mock-репозиторий и mock-emailService
// infrastructure/repositories/PrismaUserRepository.js
class PrismaUserRepository {
constructor(prisma) { this.prisma = prisma; }
async findByEmail(email) { return this.prisma.user.findUnique({ where: { email } }); }
async save(user) { return this.prisma.user.create({ data: user }); }
}
// infrastructure/http/UserController.js (Express)
class UserController {
constructor(createUserUseCase) { this.createUser = createUserUseCase; }
async post(req, res) {
try {
const user = await this.createUser.execute(req.body);
res.status(201).json(user);
} catch (err) {
res.status(400).json({ error: err.message });
}
}
}
Частые ошибки
- Правило зависимости нарушено внутрь: Use Case импортирует Prisma-модель напрямую — теперь смена ORM требует переписывания Use Cases.
- Слои смешаны: бизнес-логика в Controller или SQL в Entity — самая частая проблема на практике.
- Overkill для малых проектов: для CRUD-приложения с 5 сущностями Clean Architecture добавляет лишний boilerplate без реальной пользы. Применяйте YAGNI.
🎓 Источники
- 🎓 [Public Interview #7 — Hexagonal/Clean] · 2022-05-13 · YouTube
- «Гексагональная — реинкарнация слоёной/чистой архитектуры с чёткими портами и адаптерами».
- Характерна Inversion of Control, не наследование.
- 🎓 [Дядя Боб и розовые пони] и автор · 2025-02-18 · YouTube
- Критика догматичного следования Clean Architecture/Clean Code.
- 🎓 [Архитектурные принципы Metarhia] · 2023-12-06 · YouTube
- Альтернативная позиция: «В архитектуре нет единственно правильного решения. Структура приложения важнее архитектуры».