🏠 /

Как писать код на Python

Структура папочек, код-стайл и как это автоматизировать

Дисклеймер

  • Все, что написано ниже, можно применять к любому бекенду, не только на 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 — для классов
    • Именовать что бы то ни было стоит максимально подробно, архитектура должна быть кричащей - чтобы сразу по названию можно было сказать что код делает

    Тесты

    • Зачем нужны? Чтобы быть уверенным в своем коде

    Автоматизируем

    • Black — форматирует все красиво
    • Ruff — супер быстрый линтер

    Почитать/посмотреть на тему