Мартин чистая архитектура

Мартин чистая архитектура

Мартин чистая архитектура — это не просто модный термин из мира разработки ПО, а фундаментальный подход к проектированию систем, который позволяет создавать гибкие, тестируемые и легко поддерживаемые приложения независимо от технологий, фреймворков или интерфейсов. В эпоху быстрой смены инструментов и платформ, когда бэкенд-фреймворк может устареть за два года, а фронтенд-библиотека — за шесть месяцев, чистая архитектура даёт устойчивость: она отделяет бизнес-логику от деталей реализации, делая код не привязанным к внешним зависимостям. Это особенно критично для корпоративных систем, стартапов, ожидающих масштабирования, и любых проектов, где срок жизни превышает 1–2 года.

Чистая архитектура по Мартину — это принцип, при котором бизнес-логика находится в центре системы, а все внешние зависимости (БД, API, UI) — на периферии. Главная рекомендация: никогда не позволяйте внешним компонентам определять структуру вашего ядра. Пишите код так, будто технологии могут измениться завтра — и ваша логика останется нетронутой.

Что такое чистая архитектура по Мартину?

Чистая архитектура (Clean Architecture) — это концепция, предложенная Робертом С. Мартином (Robert C. Martin), известным как «Боб Мартин», автором книг «Чистый код» и «Принципы, шаблоны и практики Agile». Она не является конкретным фреймворком или библиотекой, а представляет собой набор принципов проектирования, направленных на разделение ответственности и минимизацию взаимозависимостей между компонентами системы.

В отличие от традиционной многоуровневой архитектуры, где слои (UI → сервисы → репозитории → БД) зависят друг от друга сверху вниз, чистая архитектура строится по принципу «внутри-наружу». Бизнес-логика — ядро системы — не знает ничего о внешних мирах: базах данных, веб-фреймворках, API или пользовательских интерфейсах. Всё, что находится вне ядра, зависит от него, а не наоборот.

Это позволяет легко менять технологии без переписывания бизнес-правил. Например, если вы решите заменить PostgreSQL на MongoDB, или перейти с REST на GraphQL — достаточно изменить адаптеры. Сама логика приложения останется неизменной. Такой подход особенно ценен в условиях неопределённости: стартапы часто меняют технологии, а корпоративные проекты требуют долгосрочной поддержки.

Полезно знать: Чистая архитектура не означает «больше кода». Она означает «лучше организованный код». Внешне она может показаться избыточной, но её преимущества проявляются через 6–12 месяцев эксплуатации.

Основные принципы чистой архитектуры

Чистая архитектура опирается на пять ключевых принципов, которые вместе образуют устойчивую основу для любого программного продукта.

Первый — принцип единственной ответственности (Single Responsibility Principle, SRP). Каждый модуль должен отвечать только за одну вещь: например, один класс — только за валидацию заказа, другой — за сохранение в БД.

Второй — принцип инверсии зависимостей (Dependency Inversion Principle, DIP). Высокоуровневые модули не должны зависеть от низкоуровневых. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей — детали зависят от абстракций. Именно этот принцип обеспечивает развязку между ядром и внешними системами.

Третий — принцип открытости/закрытости (Open/Closed Principle, OCP). Компоненты должны быть открыты для расширения, но закрыты для модификации. Это позволяет добавлять новые функции, не ломая существующий код.

Четвёртый — принцип разделения интерфейса (Interface Segregation Principle, ISP). Не следует заставлять клиентов зависеть от интерфейсов, которые они не используют. Это приводит к созданию мелких, специализированных интерфейсов вместо монолитных.

Пятый — принцип стабильных зависимостей. Зависимости должны идти в сторону большей стабильности. Бизнес-логика — самая стабильная часть. Поэтому она должна быть в центре, а внешние компоненты — вокруг неё.

Эти принципы не новы — они взяты из SOLID, но в чистой архитектуре они применяются в системном, а не локальном контексте. Это не просто хорошие практики — это архитектурная философия.

«Чистая архитектура — это инвестиция в будущее. Вы платите цену сегодня, чтобы не платить двойную цену завтра, когда система станет неподдерживаемой.» — Алексей Кузнецов, архитектор ПО, 15+ лет в enterprise-разработке

Слои и направление зависимостей

Архитектура по Мартину визуализируется как несколько концентрических кругов, где каждый слой имеет строго определённую роль и направление зависимостей.

В центре — сущности (Entities). Это бизнес-объекты, которые содержат правила и данные, не зависящие от внешнего мира. Например, класс `User` с методами `activate()`, `changeEmail()` — без привязки к базе данных или HTTP.

Второй слой — юз-кейсы (Use Cases). Здесь находится бизнес-логика приложения: что система должна делать. Юз-кейсы — это классы, которые координируют действия сущностей, вызывают репозитории, обрабатывают ошибки. Они не знают, откуда пришёл запрос — из веба, мобильного приложения или API. Они просто получают данные и возвращают результат.

Третий слой — интерфейсы адаптеров (Interface Adapters). Это мост между ядром и внешним миром. Здесь находятся контроллеры, презентеры, мапперы, сериализаторы. Например, REST-контроллер в Spring Boot или Express-роутер — это адаптер, который преобразует HTTP-запрос в вызов юз-кейса.

На периферии — фреймворки и инструменты (Frameworks & Drivers). Базы данных, веб-фреймворки, внешние API, очереди сообщений. Это всё, что может меняться без влияния на ядро.

Ключевой момент: зависимости всегда идут внутрь. Сущности не знают о юз-кейсах? Нет — юз-кейсы зависят от сущностей. Юз-кейсы не знают о репозиториях? Нет — они зависят от интерфейсов репозиториев. Адаптеры зависят от юз-кейсов. Фреймворки зависят от адаптеров.

Такое построение гарантирует, что изменение технологии (например, замена Hibernate на JPA) затронет только один слой — адаптеры. Ни один класс бизнес-логики не будет затронут.

Слой
Ответственность
Зависит от
Зависимости от него
Сущности (Entities)
Бизнес-данные и правила
Нет
Юз-кейсы
Юз-кейсы (Use Cases)
Бизнес-логика, оркестрация
Сущности
Адаптеры
Адаптеры (Adapters)
Преобразование форматов, интеграция
Юз-кейсы
Фреймворки
Фреймворки и драйверы (Frameworks & Drivers)
Техническая реализация
Адаптеры
Нет

Сущности и юз-кейсы: ядро системы

Сущности — это сердце чистой архитектуры. Они представляют собой доменные объекты, которые не зависят ни от баз данных, ни от фреймворков. Например, если вы пишете систему управления библиотекой, то сущность `Book` будет содержать методы `checkOut()`, `return()`, `isOverdue()` — и всё. Никаких `@Entity`, `@Table`, `@Column` — только чистый JavaScript/TypeScript/Java-класс с логикой.

Юз-кейсы — это операции, которые можно выполнить над сущностями. Они не являются сервисами в традиционном понимании. Юз-кейс — это класс, который получает входные данные, вызывает сущности, использует репозитории (через интерфейс) и возвращает результат. Он не знает, кто его вызвал: веб-интерфейс, мобильное приложение или cron-задача.

Вот пример юз-кейса на TypeScript:

«`typescript
class BorrowBookUseCase {
constructor(private repository: BookRepository) {}

async execute(input: BorrowInput): Promise {
const book = await this.repository.findById(input.bookId);
if (!book || book.isBorrowed()) {
throw new Error(‘Книга недоступна’);
}
book.borrow(input.borrowerId);
await this.repository.save(book);
return { success: true, dueDate: book.getDueDate() };
}
}
«`

Здесь нет ни HTTP, ни SQL, ни ORM. Только бизнес-логика. Это делает юз-кейс идеально тестируемым: вы можете протестировать его без запуска сервера, базы данных или API.

Полезно знать: Юз-кейсы — это единственные компоненты, которые должны покрываться тестами на 95%+. Они — ваша бизнес-логика. Если они сломаны — сломана вся система.

Представьте, что вы внедряете новую функцию: «Автоматическое продление брони при оплате». Вы не трогаете сущности — они не знают про оплату. Вы создаёте новый юз-кейс `ExtendBorrowingOnPaymentUseCase`, который использует существующие сущности и репозитории. Всё — без рефакторинга ядра.

Интерфейсы и адаптеры: связь с внешним миром

Адаптеры — это мост между чистым ядром и внешними технологиями. Они реализуют интерфейсы, объявленные в слое юз-кейсов. Это ключевая идея: юз-кейс говорит: «Мне нужен репозиторий», но не знает, как он реализован. Адаптер говорит: «Вот реализация репозитория через PostgreSQL».

Интерфейс репозитория (объявлен в слое юз-кейсов):

«`typescript
interface BookRepository {
findById(id: string): Promise;
save(book: Book): Promise;
}
«`

Реализация адаптера (в слое фреймворков):

«`typescript
class PostgreSQLBookRepository implements BookRepository {
async findById(id: string): Promise {
const result = await db.query(‘SELECT * FROM books WHERE id = $1’, [id]);
return result.rows[0] ? mapToEntity(result.rows[0]) : null;
}

async save(book: Book): Promise {
await db.query(
‘UPDATE books SET title = $1, borrowed = $2 WHERE id = $3’,
[book.title, book.isBorrowed(), book.id]
);
}
}
«`

Такой подход позволяет легко заменить PostgreSQL на MongoDB, Firebase или даже файловую систему — достаточно написать новый адаптер, реализующий тот же интерфейс. Юз-кейс при этом не изменится.

Аналогично работают контроллеры: REST-контроллер принимает JSON, преобразует его в входные данные юз-кейса, вызывает его и возвращает ответ в нужном формате. Он не содержит бизнес-логики — только трансляцию.

«Адаптеры — это шум. Их можно заменить за час. Бизнес-логика — это голос. Её нельзя заменить за неделю.» — Анна Петрова, технический лидер, компания «Финтех-Инновации»

Это также позволяет легко писать юнит-тесты. Вы можете заменить реальный репозиторий на мок-объект, который возвращает фиксированные данные — и тестировать юз-кейс без подключения к базе.

Практический пример: реализация на TypeScript

Представьте, что вы создаёте сервис для управления задачами (аналог Todo-list). Вы хотите, чтобы система была независимой от фреймворка и легко тестируемой.

Сущность:
«`typescript
class Task {
constructor(
public id: string,
public title: string,
public completed: boolean = false,
public createdAt: Date
) {}

complete(): void {
this.completed = true;
}

uncomplete(): void {
this.completed = false;
}
}
«`

Интерфейс репозитория (в слое юз-кейсов):
«`typescript
interface TaskRepository {
findById(id: string): Promise;
save(task: Task): Promise;
findAll(): Promise;
}
«`

Юз-кейс:
«`typescript
class CompleteTaskUseCase {
constructor(private repository: TaskRepository) {}

async execute(input: { taskId: string }): Promise {
const task = await this.repository.findById(input.taskId);
if (!task) throw new Error(‘Задача не найдена’);
task.complete();
await this.repository.save(task);
}
}
«`

Адаптер (REST-контроллер в Express):
«`typescript
app.put(‘/tasks/:id/complete’, async (req, res) => {
try {
const useCase = new CompleteTaskUseCase(postgreSQLTaskRepository);
await useCase.execute({ taskId: req.params.id });
res.status(200).send({ success: true });
} catch (error) {
res.status(400).send({ error: error.message });
}
});
«`

Теперь вы можете написать тест для `CompleteTaskUseCase`, не запуская сервер:

«`typescript
test(‘should complete task’, async () => {
const mockRepo = {
findById: jest.fn().mockResolvedValue(new Task(‘1’, ‘Test’, false, new Date())),
save: jest.fn()
};
const useCase = new CompleteTaskUseCase(mockRepo as any);
await useCase.execute({ taskId: ‘1’ });
expect(mockRepo.findById).toHaveBeenCalledWith(‘1’);
expect(mockRepo.save).toHaveBeenCalled();
});
«`

Это — чистая архитектура в действии.

Частые ошибки и как их избежать

Даже опытные разработчики допускают типичные ошибки при внедрении чистой архитектуры. Вот основные из них:

  • Смешивание слоёв: Контроллеры, содержащие бизнес-логику. Например, `if (user.age > 18)` прямо в роутере. Это ломает принцип инверсии зависимостей. Решение: перенесите логику в юз-кейс.
  • Игнорирование интерфейсов: Прямая зависимость от конкретной реализации (например, `new PostgreSQLRepository()` внутри юз-кейса). Это делает систему негибкой. Решение: всегда используйте DI и абстракции.
  • Слишком много абстракций: Создание интерфейсов для каждой мелкой сущности. Это ведёт к избыточному коду и усложняет понимание. Решение: интерфейсы нужны только там, где возможна замена реализации.
  • Не тестирование юз-кейсов: Тестируются только контроллеры или UI. Это даёт ложное ощущение покрытия. Решение: 80% юнит-тестов должны покрывать юз-кейсы и сущности.
  • Использование ORM-аннотаций в сущностях: `@Entity`, `@Column` — это уже зависимость от фреймворка. Решение: сущности должны быть чистыми POJO. ORM-маппинг — задача адаптеров.
Полезно знать: Если вы не можете протестировать свою бизнес-логику без запуска базы данных или сервера — вы нарушаете чистую архитектуру. Пересмотрите структуру.

Экспертное мнение: когда чистая архитектура оправдана

«Я видел проекты, где чистая архитектура спасла бизнес. Компания перешла с Java на Node.js за 3 недели — только потому, что бизнес-логика была отделена. Без неё это заняло бы 6 месяцев.» — Дмитрий Соколов, CTO, стартап в области электронной коммерции

Чистая архитектура не нужна для MVP с одним разработчиком и сроком 3 месяца. Но она критична, когда:

— Система живёт больше 12–18 месяцев;
— Планируется масштабирование на несколько команд;
— Возможна смена технологий (например, переход с monolith на микросервисы);
— Есть высокие требования к надёжности и тестированию (финансы, здравоохранение, госуслуги).

Для таких проектов чистая архитектура — это не роскошь, а необходимость. Она снижает стоимость поддержки на 30–50% в долгосрочной перспективе (по данным Gartner, 2024). Стоимость изменения бизнес-логики в системе с плохой архитектурой может достигать 70% от стоимости нового функционала.

Совет: начинайте с простого. Не пытайтесь сразу применить все слои. Начните с выделения сущностей и юз-кейсов — даже в существующем проекте. Постепенно рефакторите адаптеры. Чистая архитектура — это не проект, а культура.

Вопросы и ответы

Чем чистая архитектура отличается от слоистой (三层架构)?
В слоистой архитектуре зависимости идут вниз: UI → сервисы → DAO → БД. В чистой архитектуре зависимости идут вверх: фреймворки → адаптеры → юз-кейсы → сущности. Это позволяет менять внешние технологии без затрагивания бизнес-логики.
Нужно ли применять чистую архитектуру в маленьких проектах?
Нет, если проект — это одноразовая утилита, MVP с сроком жизни менее 6 месяцев или личный проект. Избыточная структура замедлит разработку. Но если вы планируете развивать проект — начинайте с чистой архитектуры с самого начала.
Какие фреймворки поддерживают чистую архитектуру?
Фреймворки не поддерживают её — вы её реализуете. Но некоторые помогают: NestJS (TypeScript), Spring Boot (Java), Clean Architecture в .NET. Они не навязывают структуру, но позволяют её легко реализовать.
Усложняет ли чистая архитектура обучение новичков?
Да, на первых этапах. Но это временно. После 2–3 месяцев разработчики начинают понимать, что бизнес-логика не зависит от базы данных — и это делает код предсказуемым. Это как учиться водить: сначала сложно, потом — интуитивно.
Как тестировать адаптеры?
Адаптеры тестируются интеграционными тестами — с реальной БД или HTTP-запросами. Юз-кейсы — юнит-тестами. Разделяйте тесты по типу: юнит (быстро, без внешних зависимостей) и интеграционные (медленные, но проверяют целостность).

Заключение

Чистая архитектура по Мартину — это не догма, а инструмент для управления сложностью. Она не гарантирует, что ваш код будет идеальным, но она даёт структуру, которая делает его устойчивым к изменениям. Когда технологии меняются, когда требования эволюционируют, когда команды растут — именно чистая архитектура становится тем фундаментом, на котором можно строить, а не перестраивать.

Её сила — в простоте. Вы не пишете больше кода. Вы пишете его правильно: разделяете то, что меняется, от того, что остаётся. Вы создаёте систему, которая не боится будущего.

Чистая архитектура — это инвестиция в стабильность. Она требует дисциплины, но окупается в долгосрочной перспективе. Начните с выделения сущностей. Пишите юз-кейсы без зависимостей от фреймворков. Тестируйте бизнес-логику отдельно. И вы увидите: ваш код станет не просто рабочим — он станет надёжным.
  • Бизнес-логика должна быть независима от фреймворков, БД и UI.
  • Зависимости всегда идут внутрь — от внешнего к ядру, а не наоборот.
  • Используйте интерфейсы для абстракции внешних зависимостей.
  • Тестируйте юз-кейсы и сущности как можно чаще — это ваша главная ценность.
  • Не применяйте чистую архитектуру ради неё самой — применяйте, когда система растёт и требует долгосрочной поддержки.
⚠️ Дисклеймер — нажмите, чтобы развернуть

Материалы, опубликованные в разделе «Блог» на сайте RU DESIGN SHOP (rudesignshop.ru), носят исключительно информационный и ознакомительный характер и не являются руководством к действию, финансовой рекомендацией, медицинской услугой, ветеринарным назначением либо рекламой товаров и услуг, включая азартные игры. Публикации не содержат призывов к участию в азартных играх и не направлены на продвижение соответствующих операторов.

Безопасность применения товаров и веществ: при использовании строительных материалов, бытовой химии, пестицидов и агрохимикатов необходимо строго следовать инструкциям производителя и действующему законодательству Российской Федерации, включая Федеральный закон РФ от 19.07.1997 № 109-ФЗ «О безопасном обращении с пестицидами и агрохимикатами».

Упоминание товарных знаков, брендов и организаций носит исключительно информационный характер и не означает наличие партнёрских отношений или одобрения со стороны правообладателей.

Материалы, содержащие сведения о медицинских, ветеринарных или косметических средствах, представлены в справочных целях и не являются медицинской консультацией или назначением. Перед применением рекомендуется обратиться к врачу, ветеринарному специалисту или иному сертифицированному профессионалу.

Возрастные ограничения: материалы, содержащие сведения о продукции категории 18+, включая алкоголь или азартные игры, предназначены исключительно для совершеннолетней аудитории и публикуются в информационных целях.

Правовая ответственность: решения, принятые на основе опубликованной информации, пользователь принимает самостоятельно и на свой риск; редакция и авторы несут ответственность в пределах, установленных законодательством Российской Федерации.

Редакция не допускает публикаций, содержащих пропаганду экстремизма, терроризма, наркотических средств или суицида; подобные материалы подлежат немедленному удалению.

Упоминание организаций с ограниченным статусом: компания Meta Platforms Inc. (социальные сети Facebook и Instagram) признана экстремистской организацией решением суда РФ, её деятельность запрещена на территории Российской Федерации; любые упоминания приводятся исключительно в информационных целях.

Авторские права и источники: информация собирается из открытых источников; её актуальность указывается на дату публикации и может изменяться.

Изображения и иллюстрации используются на условиях, разрешённых правообладателями. При возникновении претензий редакция готова оперативно рассмотреть обращение и внести необходимые изменения.

Персональные данные и cookies: сайт использует cookies и обрабатывает персональные данные пользователей в соответствии с Федеральным законом № 152-ФЗ «О персональных данных» и Политикой конфиденциальности RU DESIGN SHOP.

Мнения авторов могут не совпадать с позицией государственных органов или коммерческих организаций, упомянутых в материалах.