🧙 Садовник: уточнил шаги, добавил проверки и обоснования. Примите, если полезно.

#1
open+715proposed by gardener · Aug 8, 2026 · based on v1
Proposed changes · v1 → suggestion
+715
Начните с плоской структуры для небольших скриптовAdded

Размещайте все файлы (main.py, models.py, database.py) в корне проекта. Подходит для прототипов, автоматизаций и сервисов на пару эндпоинтов.

Перейдите к слоистой структуре по техническим ролямAdded

Группируйте файлы по их техническому назначению: models/, schemas/, services/, routers/. Это логичный шаг при выходе за рамки прототипа.

Группируйте код по фичам при росте функциональностиAdded

Создавайте отдельные модули под части предметной области (users/, products/, orders/), размещая слои внутри каждой фичи.

Внедрите гексагональную архитектуру с портами и адаптерамиRecommendedAdded

Отделите бизнес-логику в центр (domain/), описав внешние зависимости через интерфейсы-порты, а базы данных и фреймворки — через адаптеры.

Примените чистую архитектуру для сложной бизнес-логикиRecommendedAdded

Организуйте проект концентрическими слоями: сущности (entities), сценарии использования (use_cases), адаптеры и внешние фреймворки. Зависимости направлены строго внутрь.

Изолируйте модули в формате модульного монолитаRecommendedAdded

Скомбинируйте подход по фичам с жестким ограничением видимости: каждый модуль имеет открытый api.py, а внутренности скрыты в internal/.

Выберите подходящую структуру под требования и масштабы проектаAdded

Оцените размер команды, сложность предметной области и частоту изменений. Начните с более простой структуры и усложняйте её по мере роста.

## Зачем знать вариантыRemoved
## Зачем знать варианты Мы взяли слоистую структуру. Это осознанный выбор, а не единственный правильный вариант. Знать остальные надо по трём причинам. Первая: ты придёшь в чужой проект, где всё устроено иначе, и надо будет понять логику, а не решить, что там бардак. Вторая: у каждой структуры есть цена, и лучше знать её заранее. Третья: вопрос про архитектуру задают на каждом собеседовании. Этот список непоследовательный — можно читать в любом порядке.
Плоская: всё рядомRemoved
``` project/ ├── main.py ├── models.py ├── schemas.py └── database.py ``` Всё в корне, один файл на тип сущности. Именно так выглядит большинство примеров в туториалах. **Когда годится:** скрипт, прототип, учебный пример, сервис на три эндпоинта. **Где ломается:** примерно на тридцатом файле. `models.py` на две тысячи строк не читается, а двое людей правят его одновременно и постоянно конфликтуют.
Слоистая: группируем по технической ролиRemoved
``` app/ ├── models/ category.py product.py order.py ├── schemas/ category.py product.py order.py ├── repository/ category.py product.py order.py ├── services/ category.py product.py order.py └── routers/ category.py product.py order.py ``` Папка — это **роль** файла. Все модели вместе, все роутеры вместе. **Плюсы:** очевидно, куда класть новый файл. Правило зависимостей проверяется глазами. Новичок разбирается за десять минут. **Цена:** чтобы добавить одну функцию, надо открыть пять папок и править пять файлов. Всё, что относится к заказам, размазано по всему проекту.
По фичам: группируем по предметной областиRemoved
``` app/ ├── categories/ │ ├── models.py │ ├── schemas.py │ ├── service.py │ └── router.py ├── products/ │ └── ... то же самое └── orders/ └── ... то же самое ``` Папка — это **часть предметной области**. Слои никуда не делись — они внутри каждой папки. **Плюсы:** вся функциональность в одном месте. Удалить фичу — удалить папку. Двое людей работают над разными фичами и не пересекаются. **Цена:** границы слоёв больше не видны в дереве — их приходится держать договорённостью. Новичок легко напишет SQL в `router.py` — он же рядом. Так устроен **[Netflix Dispatch](https://github.com/Netflix/dispatch)** и этот подход советует известный сборник **[FastAPI Best Practices](https://github.com/zhanymkanov/fastapi-best-practices)**.
Гексагональная: порты и адаптерыRecommendedRemoved
``` app/ ├── domain/ чистая логика, никаких библиотек │ ├── entities.py │ └── ports.py интерфейсы: «мне нужен тот, кто умеет сохранять» └── adapters/ реализации этих интерфейсов ├── postgres.py ├── http.py └── memory.py для тестов ``` Идея: логика в центре и **не знает ничего** о базе, HTTP и фреймворке. Она объявляет порты — что ей нужно, а адаптеры это предоставляют. **Плюсы:** логика тестируется без базы вообще. Смена PostgreSQL на что угодно — новый адаптер, логика не меняется. **Цена:** много интерфейсов и перекладывания данных из одних объектов в другие. На маленьком проекте это чистые накладные расходы. Первоисточник: **[Алистер Кокберн о гексагональной архитектуре](https://alistair.cockburn.us/hexagonal-architecture/)**
Чистая архитектура: кольца вокруг сущностейRecommendedRemoved
``` app/ ├── entities/ сущности и правила предметной области ├── use_cases/ сценарии: «оформить заказ» ├── adapters/ преобразование данных └── frameworks/ FastAPI, SQLAlchemy, всё внешнее ``` Правило одно: **зависимости всегда указывают внутрь**, к сущностям. Внешнее кольцо знает про внутреннее, никогда наоборот. **Плюсы:** логика переживёт смену фреймворка и базы. Сценарии читаются как описание бизнеса. **Цена:** самая высокая из всех. Много слоёв преобразования, больше кода ради того же результата. Оправдана там, где логика сложнее техники — банки, страхование, биллинг. Первоисточник: **[Роберт Мартин о чистой архитектуре](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)**
Модульный монолит: фичи с границамиRecommendedRemoved
``` app/ ├── catalog/ │ ├── api.py единственная точка входа для чужих │ └── internal/ внутренности, трогать нельзя └── orders/ ├── api.py └── internal/ ``` То же, что группировка по фичам, но с явным правилом: модули общаются **только через объявленный интерфейс**. Заказы не лезут во внутренности каталога, даже если технически могут. **Плюсы:** готовность разрезать на микросервисы, если потребуется. Границы видны. **Цена:** дисциплина. Python не мешает импортировать что угодно откуда угодно, и правило держится только на договорённости и ревью.
## Отдельное измерение: src-layout против flat-layoutRemoved
## Отдельное измерение: src-layout против flat-layout Это **не архитектура**, а вопрос упаковки. Путают постоянно. ``` flat-layout src-layout project/ project/ ├── app/ ├── src/ │ └── ... │ └── app/ └── pyproject.toml └── pyproject.toml ``` **Зачем src:** пакет нельзя случайно импортировать из корня проекта. Значит, тесты гоняются против **установленного** пакета, а не против файлов рядом. Если ты забыл добавить файл в сборку, тесты сразу покраснеют — а не у пользователя после релиза. **Зачем без src:** короче пути, меньше вложенности. Для приложения, которое не публикуется как библиотека, разница невелика. Мы выбрали flat с пакетом `app/` — потому что строим приложение, а не библиотеку на PyPI. Подробно с аргументами с обеих сторон: **[src-layout vs flat-layout](https://packaging.python.org/en/latest/discussions/src-layout-vs-flat-layout/)**
## Что советует сам FastAPIRemoved
## Что советует сам FastAPI Официальная документация в разделе **[Bigger Applications](https://fastapi.tiangolo.com/tutorial/bigger-applications/)** показывает вариант ближе к слоистому: пакет `app/` с `routers/`, общими зависимостями и внутренними подпакетами. Важное: **у FastAPI нет обязательной структуры.** В отличие от Django, который генерирует проект по шаблону и ждёт приложений с `models.py` и `views.py`, FastAPI не навязывает ничего. Отсюда и свобода, и разнобой между проектами. Поэтому вопрос «как правильно» не имеет ответа в документации — только в контексте твоего проекта.
## Как выбиратьRemoved
## Как выбирать | Ситуация | Что брать | |---|---| | Скрипт, прототип, до 10 файлов | Плоская | | Учёба, небольшой сервис, до 10 сущностей | Слоистая | | Много сущностей, команда от трёх человек | По фичам | | Готовимся разрезать на сервисы | Модульный монолит | | Логика сложнее техники, долгая жизнь | Гексагон или чистая | **Три правила, которые важнее выбора:** 1. **Любая структура лучше, чем две сразу.** Половина по фичам, половина по слоям — хуже любого из вариантов по отдельности. 2. **Структура под размер сейчас, а не на вырост.** Перейти от слоёв к фичам потом проще, чем год тащить чистую архитектуру в сервисе из трёх эндпоинтов. 3. **Записанное решение важнее самого решения.** Абзац в README «мы выбрали так-то, потому что...» спасает следующего человека от переписывания всего по своему вкусу.
Removed
Removed
Removed
Removed
## Что вынестиRemoved
## Что вынести Нет «правильной» структуры — есть подходящая под размер проекта, размер команды и срок жизни. Мы взяли слоистую, потому что на ней видно границы ответственности. Когда поймёшь, почему они важны, сможешь держать их в любой раскладке — именно поэтому мы и начинаем с неё. И главное: в реальном проекте качество чаще определяется не выбором структуры, а тем, насколько последовательно её держат. Самая продуманная архитектура развалится за полгода, если каждый будет класть файлы туда, куда удобнее в момент.
Review