113 lines
6.2 KiB
Markdown
113 lines
6.2 KiB
Markdown
# Архитектура проекта
|
||
|
||
## Слоистая архитектура
|
||
|
||
Проект построен по принципу строгой слоистости. Зависимости могут идти **только внутрь** — от 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 │
|
||
│ Зависимости: нет (фундамент) │
|
||
└─────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### Правила слоёв
|
||
|
||
1. **API** не знает про БД. Он получает `db: AsyncSession` через `Depends(get_db)`, но не создаёт сессии сам. Он не импортирует модели.
|
||
|
||
2. **Services** не знают про HTTP. Они не импортируют FastAPI, Request, Response, HTTPException. Работают с бизнес-данными через сессию БД.
|
||
|
||
3. **Integrations** не знают про бизнес-логику. Они оборачивают внешние API, управляют таймаутами и ретраями.
|
||
|
||
4. **Data** (models) — SQLAlchemy модели. Не содержат бизнес-логики. Только структура данных.
|
||
|
||
5. **Core** — фундамент. Config читает .env, base содержит абстракции, security управляет JWT, dependencies содержит FastAPI-зависимости.
|
||
|
||
---
|
||
|
||
## SOLID в проекте
|
||
|
||
### S — Single Responsibility
|
||
Каждый модуль делает одну вещь:
|
||
- `idea_service.py` — только операции с идеями
|
||
- `yandex_gpt.py` — только вызов Yandex GPT
|
||
- `auth.py` — только аутентификация
|
||
|
||
### O — Open/Closed
|
||
Новые интеграции — новые классы, а не модификация старых:
|
||
- `AIProvider` (ABC) → `YandexGPTProvider`, `GigaChatProvider`
|
||
- `BaseAgent` (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:
|
||
```python
|
||
async def get_db() -> AsyncSession:
|
||
async with async_session_maker() as session:
|
||
yield session
|
||
```
|
||
|
||
Сервисы получают сессию в конструкторе:
|
||
```python
|
||
class IdeaService:
|
||
def __init__(self, db: AsyncSession):
|
||
self.db = db
|
||
```
|
||
|
||
API создаёт сервис на каждый запрос:
|
||
```python
|
||
@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 для межсервисного взаимодействия?
|