Дисклеймер
- Все, что написано ниже, можно применять к любому бекенду, не только на Python
- Все, что написано ниже, необязательно соблюдать строго, главное чтобы с кодом было удобно работать
Структура папочек
src/
├─ core/
│ ├─ str_utils.py
│ ├─ sql_repo.py
│ ├─ api_client.py
├─ entities/
│ ├─ order/
│ │ ├─ order.py
├─ features/
│ ├─ order/
│ │ ├─ create_order/
│ │ │ ├─ create_order.py
│ │ ├─ ports/
│ │ │ ├─ order_repo.py
├─ infra/
│ ├─ order/
│ │ ├─ sql_order_repo.py
│ ├─ ext_api/
│ │ ├─ ext_api_client.py
│ │ ├─ ext_api_repo.py
├─ views/
│ ├─ order/
│ │ ├─ api.py
│ │ ├─ admin.py
├─ root/
│ ├─ server.py
│ ├─ ioc.py
main.py
- Делаем в стиле DDD / Clean Architecture / Hexagonal
core
/shared
— всякий переиспользуемый код: утилитки, базовые классы для работы с бд, http-запросамиentities
/models
/domain
— доменные сущности и логика внутри них - все с чем работает бизнес: заказы, клиенты, точкиfeatures
/use_cases
/services
— юзкейсы, сервисы, бизнес-логика - все что приносит ценность бизнесу: создание заказа, регистрация клиентаports
— в юзкейсе, обычно, надо ходить в бд, делать запросы к другим сервисам, но это должно быть абстрактно, на этом слое мы не должны зависеть от конкретных технологий, типа SQL, Google API - так что тут делаем интерфейсы (абстрактные классы) для работы с бд, сторонними сервисами
infra
— здесь реализуем те самые интерфейсы изports
: классы, которые отправляют sql-запросы, http-запросыviews
/handlers
/endpoints
/api
— апи-ендпоинты: парсят данные из http-запросов, дергают бизнес логику и сериализуют результатroott
/config
/composition_root
— здесь все склеивается вместе: регистрация роутов, создание классов-сервисов с конкретными зависимостями (ака IoC-Container)
⚠️
Каждый слой может использовать код только из своего слоя или слоев ниже, но не слоев выше
Так
features
может использовать код из shared
, entities
,
features
,
но не может использовать код из infra
Что дает такая структура
- Устранение циклических зависимостей — циклические зависимости возникают если нижний слой использует верхний слой, а у нас это запрещено
- Тестируемость — так как все разделено, можно легко мокать зависимости
Код-стайл
Именование
- 🐍
snake_case
— для пакетов, модулей, методов, переменных;PascalCase
— для классов - Именовать что бы то ни было стоит максимально подробно, архитектура должна быть кричащей - чтобы сразу по названию можно было сказать что код делает
Тесты
- Зачем нужны? Чтобы быть уверенным в своем коде
Почитать/посмотреть на тему
- 📝 A Beginner’s Guide to Domain-centric Architectures (clean, hexagonal, …) — супер статья про слоистую архитектуру
- 📹 Борис Цема, Wargaming.net «Как мы уменьшили сложность наших проектов» — видос про слоистую архитектуру
- 📖 Весь Роберт Мартин
- 📖 Весь Мартин Фаулер
(развелось Мартинов) - 📖 Весь Стив Макконнелл
- 📖 Троица про DDD: Domain-Driven Design, Implementing Domain-Driven Design, Distilled Domain-Driven Design