6.2 KiB
Архитектура проекта
Слоистая архитектура
Проект построен по принципу строгой слоистости. Зависимости могут идти только внутрь — от API к Core.
┌─────────────────────────────────────────────────────┐
│ API │
│ HTTP роуты, Pydantic валидация, OpenAPI │
│ Зависимости: Services │
├─────────────────────────────────────────────────────┤
│ Services │
│ Бизнес-логика, оркестрация │
│ Зависимости: Integrations, Data │
├─────────────────────────────────────────────────────┤
│ Integrations │
│ Внешние API, AI провайдеры, fallback chain │
│ Зависимости: Data │
├─────────────────────────────────────────────────────┤
│ Tasks │
│ Фоновые задачи (Celery или прямой вызов) │
│ Зависимости: Services, Integrations │
├─────────────────────────────────────────────────────┤
│ Agents │
│ Системные агенты (саморазвитие проекта) │
│ Зависимости: Services, Integrations │
├─────────────────────────────────────────────────────┤
│ Data │
│ Модели БД, репозитории, миграции │
│ Зависимости: Core │
├─────────────────────────────────────────────────────┤
│ Core │
│ Config, base classes, security, dependencies │
│ Зависимости: нет (фундамент) │
└─────────────────────────────────────────────────────┘
Правила слоёв
-
API не знает про БД. Он получает
db: AsyncSessionчерезDepends(get_db), но не создаёт сессии сам. Он не импортирует модели. -
Services не знают про HTTP. Они не импортируют FastAPI, Request, Response, HTTPException. Работают с бизнес-данными через сессию БД.
-
Integrations не знают про бизнес-логику. Они оборачивают внешние API, управляют таймаутами и ретраями.
-
Data (models) — SQLAlchemy модели. Не содержат бизнес-логики. Только структура данных.
-
Core — фундамент. Config читает .env, base содержит абстракции, security управляет JWT, dependencies содержит FastAPI-зависимости.
SOLID в проекте
S — Single Responsibility
Каждый модуль делает одну вещь:
idea_service.py— только операции с идеямиyandex_gpt.py— только вызов Yandex GPTauth.py— только аутентификация
O — Open/Closed
Новые интеграции — новые классы, а не модификация старых:
AIProvider(ABC) →YandexGPTProvider,GigaChatProviderBaseAgent(ABC) →DocAgent,AuditAgent, ...
L — Liskov Substitution
Сервисы принимают AsyncSession — любую реализацию (SQLite, PostgreSQL):
- Код работает одинаково на обеих БД
I — Interface Segregation
Сервис принимает только то, что нужно:
IdeaService(db)— не принимает config, security, и т.д.AuthService(db, settings)— принимает то, что реально нужно
D — Dependency Inversion
API зависит от IdeaService, а не от IdeaServicePostgres:
- Сервисы — это абстракция над слоем данных
- Можно подменить реализацию не меняя API
Dependency Injection
Сессия БД создаётся FastAPI и передаётся через Depends:
async def get_db() -> AsyncSession:
async with async_session_maker() as session:
yield session
Сервисы получают сессию в конструкторе:
class IdeaService:
def __init__(self, db: AsyncSession):
self.db = db
API создаёт сервис на каждый запрос:
@router.get("/")
async def list_ideas(db: AsyncSession = Depends(get_db)):
service = IdeaService(db)
return await service.list_all()
[ASK] Вопросы по архитектуре
- Нужен ли Repository Pattern (отдельный слой между сервисами и моделями)?
- Использовать ли CQRS (разделение чтения и записи)?
- Нужен ли Event Bus для межсервисного взаимодействия?