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

Зависимости направлены внутрь.

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


📌 Что значит «внутрь»?

Вспомним картинку с изображением основных слоёв в чистой архитектуре:

  • Presentation (HTTP, контроллеры)
  • Application (use cases)
  • Domain (бизнес-логика)
  • Infrastructure (БД, ORM, внешние API)

Если зависимости направлены внутрь, то верное направление будет таким:

Presentation → Application → Domain
Infrastructure → Domain

То есть:

  • Контроллер знает про use case
  • Use case знает про домен
  • Инфраструктура знает про домен
  • Домен не знает ни про кого

❗ Domain — самый внутренний слой. И он не должен ничего импортировать из внешнего мира.


Почему это так важно?

Как только домен узнаёт про ORM, HTTP или какую-то библиотеку, происходит следующее:

  • Бизнес-логика начинает зависеть от конкретной библиотеки
  • Замена ORM или любой другой зависимости превращается в миграцию всей системы
  • Тестирование без базы становится невозможным

Проще говоря: библиотека начинает управлять вами, а не вы ею.

В своей практике я это прочувствовал несколько раз: когда переезжали с sequelize, избавлялись от request и moment. И это только часть примеров, с которыми я столкнулся, присоединившись к проекту.


Простые примеры для иллюстрации проблемы

😭 Плохо:

import { PrismaClient } from '@prisma/client'

export class UserService {
  async register(...) {
    const prisma = new PrismaClient()
    ...
  }
}

Здесь доменный сервис стал зависеть от Prisma.
Теперь мы с библиотекой «навечно».


👍 Лучше:

export interface UserRepository {
  save(user: User): Promise<void>
}

Домен определяет контракт, а реализация происходит на уровне инфраструктуры.

Домену всё равно, SQLite там, PostgreSQL или вообще in-memory реализация для тестов. В репозитории я как раз привёл пример реализации in-memory варианта.


🧠 Ментальная модель

Представь, что Domain — это отдельная библиотека с бизнес-логикой.

Можно ли её вынести в отдельный npm-пакет без Prisma (или любого другого ORM), без Express, Fastify или axios?

Если да — ты на верном пути к чистой архитектуре.
Если нет — значит что-то не так с зависимостями и стоит ещё раз проверить соблюдение правила.


🎯 Файловая структура вторична

Часто чистую архитектуру демонстрируют, отталкиваясь от файловой структуры. Мол, есть директории domain / application / infrastructure, значит точно в проекте clean architecture.

Но это не показатель.

Если где-то в Domain есть что-то вроде:

import { PrismaClient } from '@prisma/client'

— архитектура уже нарушена.

Запоминаем: Clean Architecture — это не про структуру директорий.
Это про направление зависимостей.


В следующей серии посмотрим, как это выглядит в коде 🧑‍💻