---
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/` и наоборот.

### 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.
