Some checks failed
CI / bootstrap (push) Successful in 52s
CI / lint (push) Successful in 2m2s
CI / typecheck (push) Successful in 27s
CI / test (3.12) (push) Failing after 2m53s
CI / test (3.13) (push) Failing after 2m0s
CI / test (3.14) (push) Failing after 1m48s
CI / complexity (push) Successful in 23s
* feat(spec): mobile-first silent enforcement in STACK_REQUIRED + Template C * feat(ci): frontend-e2e job with Playwright in fullstack cookiecutter * docs(skills): mention mobile-first in audit, code-standards, project-status tool * fix(ci): use npm install instead of npm ci + add e2e regression test --------- Co-authored-by: opencode-agent <agent@opencode.local>
137 lines
8 KiB
Markdown
137 lines
8 KiB
Markdown
---
|
||
name: code-standards
|
||
description: Universal code standards for any language. Use when writing, refactoring, or reviewing code. Also when user says "стандарты кода", "code review", "правила разработки".
|
||
---
|
||
|
||
# Code Standards
|
||
|
||
## 1. Код как рассказ
|
||
- **KISS:** Пиши лаконично, без переусложнений. Код читается как последовательный рассказ
|
||
- **Функциональный стиль:** Классы — только когда нужно состояние или интерфейс библиотеки. В остальном — функции
|
||
- **Приватность:** Внутреннюю логику модуля скрывай. Префикс `_` в Python/JS, `private` в TS/Rust, internal методы по умолчанию
|
||
- **Разделение ответственности:** Бизнес-логика ≠ транспорт ≠ представление. Максимум 200-300 строк на файл. Одна ответственность на файл
|
||
|
||
## 2. Прагматизм
|
||
- **YAGNI:** Только то что нужно сейчас. Никаких заделов «на будущее», оверинжиниринга и самодеятельности
|
||
- **Правило 80/20:** Если задача ведёт к неоправданному усложнению — предупреди и предложи альтернативу до написания кода
|
||
|
||
## 3. Принципы модульности
|
||
- Функция/метод — не длиннее 30-50 строк. Если больше — разбивай на мелкие тестируемые функции
|
||
- Файл — до 200-300 строк. Больше → декомпозиция
|
||
- Конфиги/константы — в отдельный файл, не в логику
|
||
- Приватные функции/методы для внутренних деталей (с префиксом `_` или аналогом языка)
|
||
|
||
## 4. Документирование
|
||
- AGENTS.md правило «No comments unless requested» — это **default**: код без комментариев
|
||
- Этот skill описывает **исключение**: Google-style docstrings на английском для публичных API — когда контракт warrants (библиотечный API, public surface)
|
||
- Описывай **зачем**, а не **что** — код и так говорит что делает
|
||
|
||
## 5. Architecture: good vs bad
|
||
|
||
Слои для **backend**: `routes → schemas → services → db/models` (4-tier, однонаправленный). Роуты тонкие (импортируют только `services` + `schemas`), сервисы работают с `db/models`, бизнес-логика здесь. `project-status.py` enforces subset (thin routes, centralized models); этот раздел объясняет «почему».
|
||
|
||
### Backend (подробно)
|
||
|
||
**GOOD tree (синтетический):**
|
||
```
|
||
src/<package>/
|
||
├── api/
|
||
│ ├── v1/
|
||
│ │ ├── routes/users.py ← тонкие роуты, импортируют только services + schemas
|
||
│ │ ├── dependencies.py ← Depends(), get_current_user
|
||
│ │ └── router.py
|
||
│ └── router.py
|
||
├── config/
|
||
│ ├── settings.py ← pydantic-settings
|
||
│ └── logger.py ← loguru setup
|
||
├── db/
|
||
│ ├── connection.py ← Tortoise.init
|
||
│ └── models/ ← ВСЕ ORM-модели здесь (centralized)
|
||
│ ├── user.py
|
||
│ ├── post.py
|
||
│ └── comment.py
|
||
├── schemas/ ← Pydantic DTO (НЕ Tortoise models)
|
||
│ ├── base.py
|
||
│ ├── user.py
|
||
│ └── post.py
|
||
├── services/ ← бизнес-логика (работает с db/models)
|
||
│ ├── user_service.py
|
||
│ └── post_service.py
|
||
└── utils/
|
||
└── metadata.py
|
||
```
|
||
|
||
**Правила GOOD:**
|
||
1. Все ORM-модели в `db/models/` (centralized)
|
||
2. Schemas (Pydantic) отдельно от models (Tortoise) — НЕ смешивать
|
||
3. Роуты тонкие — импортируют только `services` и `schemas`
|
||
4. Сервисы работают с `db/models` — бизнес-логика здесь
|
||
5. Слои: routes → schemas → services → db/models (4-tier, однонаправленный)
|
||
|
||
**BAD tree 1 — feature-scatter:**
|
||
```
|
||
src/<package>/
|
||
├── channels/
|
||
│ ├── models.py ← ❌ модель здесь (scatter)
|
||
│ ├── routes.py
|
||
│ └── service.py
|
||
├── monitor/
|
||
│ ├── models.py ← ❌ ещё модель здесь
|
||
│ └── routes.py
|
||
├── logs/
|
||
│ └── models.py ← ❌ и здесь
|
||
├── models.py ← ❌ root-level модель
|
||
├── db.py ← ❌ connection flat (не db/connection.py)
|
||
└── main.py
|
||
```
|
||
|
||
Проблемы BAD 1: модели раскиданы по feature-папкам; `models.py` в root; `db.py` flat; не publishable; Tortoise `modules` должен перечислять 4+ файла вручную.
|
||
|
||
**BAD tree 2 — mixed-layers:**
|
||
```
|
||
src/<package>/
|
||
├── api/
|
||
│ ├── v1/
|
||
│ │ └── users.py ← ❌ роут содержит бизнес-логику + Tortoise queries
|
||
│ └── models.py ← ❌ модели в api/ (не в db/models/)
|
||
├── services/
|
||
│ └── user_service.py
|
||
│ └── schemas.py ← ❌ schemas в services/ (не в schemas/)
|
||
└── main.py
|
||
```
|
||
|
||
Проблемы BAD 2: роут делает Tortoise queries напрямую (не тонкий); модели в `api/models.py` (не `db/models/`); schemas внутри services (не отдельный слой).
|
||
|
||
### Fullstack (кратко)
|
||
|
||
Backend as above (in `backend/` + `frontend/` separation). Frontend: SvelteKit co-located `*.test.ts` в `src/lib/`, `e2e/*.spec.ts` для Playwright. НЕ смешивать backend код в `frontend/` и наоборот. + mobile-first (PWA + Playwright mobile + axe a11y) — silent enforcement через `STACK_REQUIRED["fullstack"]`.
|
||
|
||
### CLI (кратко)
|
||
|
||
`cli.py` (Typer commands) + `core.py` (business logic). Нет api/db/schemas layers. `tests/test_cli.py` + `tests/test_core.py`.
|
||
|
||
## 6. Tests
|
||
|
||
Что писать (как запускать — в `run-tests` skill). `project-status.py` enforces subset (conftest required, anti-stub, mirror structure); этот раздел объясняет «почему».
|
||
|
||
### Типы тестов
|
||
|
||
- **Regression** — воспроизводит конкретный баг, который был исправлен. Ссылается на issue/PR (`test_parser_handles_crlf_regression_#227`).
|
||
- **Integration** — пересекает слои (DB+API, scheduler+DB). Имеет `pytest.mark.integration` + `skipif` opt-in. В `tests/integration/`.
|
||
- **Unit** — чистая функция/сервис, без DB/сети. В `tests/unit/`.
|
||
|
||
### Антипаттерны
|
||
|
||
- **Stub files** — `test_*.py` без `def test_*`/`async def test_*` (digital_factory 50/62 файлов). `project-status` WARNs.
|
||
- **Тесты без assertions** — только `print`/`logger.info`. Каждый тест должен иметь минимум 1 `assert`.
|
||
- **Тесты ради тестов** — coverage ради coverage, без реальной проверки поведения.
|
||
|
||
### Mirror structure (backend)
|
||
|
||
- `tests/unit/` ↔ `src/<pkg>/services/` (unit-тесты сервисов)
|
||
- `tests/api/` ↔ `src/<pkg>/api/v1/routes/` (route-тесты через TestClient)
|
||
- `tests/integration/` ↔ cross-cutting flows (opt-in)
|
||
|
||
### conftest.py
|
||
|
||
Обязателен (backend). Shared fixtures: `mock_settings`, `client`, `auth_client`, `create_<entity>` factories.
|