Ответ
Чистая архитектура (Clean Architecture) — это предложенный Робертом Мартином (Uncle Bob) подход к проектированию программного обеспечения, цель которого — разделение ответственностей (Separation of Concerns) и создание системы, независимой от внешних факторов, таких как фреймворки, база данных или UI.
Архитектура строится на основе слоев, напоминающих луковицу, где внутренние слои ничего не знают о внешних.
Ключевой принцип — Правило зависимостей (The Dependency Rule)
Зависимости в исходном коде могут быть направлены только внутрь. Ничто во внутреннем круге не может знать что-либо о внешнем круге. В частности, код, реализующий бизнес-логику, не должен зависеть от деталей реализации (например, от конкретной СУБД).
Основные слои (от центра к периферии):
- Entities (Сущности): Объекты доменной логики, содержащие ключевые бизнес-правила. Они не зависят ни от чего.
- Use Cases (Сценарии использования): Реализуют специфичные для приложения бизнес-правила. Они оркестрируют поток данных к сущностям и от них.
- Interface Adapters (Адаптеры интерфейсов): Слой, который преобразует данные из формата, удобного для Use Cases и Entities, в формат, удобный для внешних систем (например, веб-фреймворка или базы данных). Сюда входят Presenters, Controllers, Gateways.
- Frameworks & Drivers (Фреймворки и драйверы): Самый внешний слой, содержащий конкретные реализации: веб-фреймворк (Django, FastAPI), СУБД (PostgreSQL), UI и т.д.
Пример на Python (упрощенно):
# 1. Entities (не зависит ни от чего)
class User:
def __init__(self, name: str):
if not name:
raise ValueError("Name cannot be empty")
self.name = name
# 2. Use Cases (зависит от абстракции репозитория)
from abc import ABC, abstractmethod
class UserRepository(ABC):
@abstractmethod
def save(self, user: User):
pass
class CreateUserUseCase:
def __init__(self, user_repo: UserRepository):
self.user_repo = user_repo
def execute(self, name: str):
user = User(name)
self.user_repo.save(user)
return user
# 4. Frameworks & Drivers (реализация для внешнего слоя)
class InMemoryUserRepository(UserRepository):
def save(self, user: User):
print(f"User '{user.name}' saved in memory.")
# Использование
repo = InMemoryUserRepository()
use_case = CreateUserUseCase(repo)
new_user = use_case.execute("Alice")
Преимущества:
- Независимость от фреймворков: Легко заменить веб-сервер или СУБД.
- Тестируемость: Бизнес-логику можно тестировать в изоляции, без UI и базы данных.
- Гибкость: Система легко адаптируется к изменениям требований.