Какие бывают структуры Python-проектов: не только слои
Плоская, слоистая, по фичам, гексагональная, чистая архитектура и модульный монолит. Что за каждой стоит, где она ломается и как выбрать под свой проект, а не под моду.
miki/kakie-byvayut-struktury-python-proektov-ne-tolko-sloi · v1
Плоская, слоистая, по фичам, гексагональная, чистая архитектура и модульный монолит. Что за каждой стоит, где она ломается и как выбрать под свой проект, а не под моду.
Мы взяли слоистую структуру. Это осознанный выбор, а не единственный правильный вариант.
Знать остальные надо по трём причинам. Первая: ты придёшь в чужой проект, где всё устроено иначе, и надо будет понять логику, а не решить, что там бардак. Вторая: у каждой структуры есть цена, и лучше знать её заранее. Третья: вопрос про архитектуру задают на каждом собеседовании.
Этот список непоследовательный — можно читать в любом порядке.
Всё в корне, один файл на тип сущности. Именно так выглядит большинство примеров в туториалах.
Когда годится: скрипт, прототип, учебный пример, сервис на три эндпоинта.
Где ломается: примерно на тридцатом файле. models.py на две тысячи строк не читается, а двое людей правят его одновременно и постоянно конфликтуют.
- Ты можешь назвать размер проекта, на котором плоская структура перестаёт работать
Папка — это роль файла. Все модели вместе, все роутеры вместе.
Плюсы: очевидно, куда класть новый файл. Правило зависимостей проверяется глазами. Новичок разбирается за десять минут.
Цена: чтобы добавить одну функцию, надо открыть пять папок и править пять файлов. Всё, что относится к заказам, размазано по всему проекту.
- Ты можешь назвать главный минус слоистой структуры
Папка — это часть предметной области. Слои никуда не делись — они внутри каждой папки.
Плюсы: вся функциональность в одном месте. Удалить фичу — удалить папку. Двое людей работают над разными фичами и не пересекаются.
Цена: границы слоёв больше не видны в дереве — их приходится держать договорённостью. Новичок легко напишет SQL в router.py — он же рядом.
Так устроен Netflix Dispatch и этот подход советует известный сборник FastAPI Best Practices.
- Ты можешь объяснить, что теряется при переходе от слоёв к фичам
Идея: логика в центре и не знает ничего о базе, HTTP и фреймворке. Она объявляет порты — что ей нужно, а адаптеры это предоставляют.
Плюсы: логика тестируется без базы вообще. Смена PostgreSQL на что угодно — новый адаптер, логика не меняется.
Цена: много интерфейсов и перекладывания данных из одних объектов в другие. На маленьком проекте это чистые накладные расходы.
Первоисточник: Алистер Кокберн о гексагональной архитектуре
- Ты можешь объяснить своими словами, что такое порт и что такое адаптер
Правило одно: зависимости всегда указывают внутрь, к сущностям. Внешнее кольцо знает про внутреннее, никогда наоборот.
Плюсы: логика переживёт смену фреймворка и базы. Сценарии читаются как описание бизнеса.
Цена: самая высокая из всех. Много слоёв преобразования, больше кода ради того же результата. Оправдана там, где логика сложнее техники — банки, страхование, биллинг.
Первоисточник: Роберт Мартин о чистой архитектуре
- Ты можешь назвать тип проекта, где такая цена оправдана
То же, что группировка по фичам, но с явным правилом: модули общаются только через объявленный интерфейс. Заказы не лезут во внутренности каталога, даже если технически могут.
Плюсы: готовность разрезать на микросервисы, если потребуется. Границы видны.
Цена: дисциплина. Python не мешает импортировать что угодно откуда угодно, и правило держится только на договорённости и ревью.
- Ты понимаешь, почему граница здесь держится не на Python, а на людях
Это не архитектура, а вопрос упаковки. Путают постоянно.
Зачем src: пакет нельзя случайно импортировать из корня проекта. Значит, тесты гоняются против установленного пакета, а не против файлов рядом. Если ты забыл добавить файл в сборку, тесты сразу покраснеют — а не у пользователя после релиза.
Зачем без src: короче пути, меньше вложенности. Для приложения, которое не публикуется как библиотека, разница невелика.
Мы выбрали flat с пакетом app/ — потому что строим приложение, а не библиотеку на PyPI.
Подробно с аргументами с обеих сторон: src-layout vs flat-layout
Официальная документация в разделе Bigger Applications показывает вариант ближе к слоистому: пакет app/ с routers/, общими зависимостями и внутренними подпакетами.
Важное: у FastAPI нет обязательной структуры. В отличие от Django, который генерирует проект по шаблону и ждёт приложений с models.py и views.py, FastAPI не навязывает ничего. Отсюда и свобода, и разнобой между проектами.
Поэтому вопрос «как правильно» не имеет ответа в документации — только в контексте твоего проекта.
| Ситуация | Что брать |
|---|---|
| Скрипт, прототип, до 10 файлов | Плоская |
| Учёба, небольшой сервис, до 10 сущностей | Слоистая |
| Много сущностей, команда от трёх человек | По фичам |
| Готовимся разрезать на сервисы | Модульный монолит |
| Логика сложнее техники, долгая жизнь | Гексагон или чистая |
Три правила, которые важнее выбора:
- Любая структура лучше, чем две сразу. Половина по фичам, половина по слоям — хуже любого из вариантов по отдельности.
- Структура под размер сейчас, а не на вырост. Перейти от слоёв к фичам потом проще, чем год тащить чистую архитектуру в сервисе из трёх эндпоинтов.
- Записанное решение важнее самого решения. Абзац в README «мы выбрали так-то, потому что...» спасает следующего человека от переписывания всего по своему вкусу.
Нет «правильной» структуры — есть подходящая под размер проекта, размер команды и срок жизни.
Мы взяли слоистую, потому что на ней видно границы ответственности. Когда поймёшь, почему они важны, сможешь держать их в любой раскладке — именно поэтому мы и начинаем с неё.
И главное: в реальном проекте качество чаще определяется не выбором структуры, а тем, насколько последовательно её держат. Самая продуманная архитектура развалится за полгода, если каждый будет класть файлы туда, куда удобнее в момент.

