type: standard
aspect: policy
title: "Политики кода"
version: 1.0.0
date: 2026-02-19
status: active
Обязательные правила написания, организации и проверки кода.
КОД = ЧИТАЕМЫЙ + БЕЗОПАСНЫЙ + ПЕРЕИСПОЛЬЗУЕМЫЙ
Код пишется один раз, читается много раз.
| Язык | Стандарт | Инструмент | Конфиг |
|---|---|---|---|
| Python | PEP 8 + Black | black, ruff |
pyproject.toml |
| JavaScript | Airbnb Style Guide | prettier, eslint |
.eslintrc.json |
| TypeScript | Google TypeScript Style | prettier, tslint |
tsconfig.json |
| Bash | Google Shell Style | shellcheck, shfmt |
.shellcheckrc |
Подробнее: format-code.md
ОБЯЗАТЕЛЬНО: Запускать форматтер перед каждым коммитом.
# Python
black .
ruff check --fix .
# JavaScript/TypeScript
prettier --write .
eslint --fix .
# Bash
shfmt -w *.sh
Pre-commit hook:
#!/bin/bash
# .git/hooks/pre-commit
black . || exit 1
ruff check . || exit 1
Python (PEP 8):
# 1. Стандартная библиотека
import os
import sys
from typing import List, Dict
# 2. Сторонние библиотеки
import requests
from fastapi import FastAPI
# 3. Локальные модули
from library.connectors import OzonClient
from .models import User
JavaScript/TypeScript:
// 1. Внешние библиотеки
import React from 'react';
import { useEffect } from 'react';
// 2. Внутренние модули
import { Button } from '@/components';
import { useAuth } from '@/hooks';
// 3. Локальные
import styles from './styles.module.css';
Правило:
- Абсолютные — для импорта из library/, system/
- Относительные — для импорта из той же папки
# ✅ Хорошо
from library.connectors.ozon import OzonClient # Абсолютный
from .models import User # Относительный (та же папка)
# ❌ Плохо
from ../../library/connectors/ozon import OzonClient # Слишком сложно
Подробнее: naming-code-imports.md
Правило: Один класс/функция = один файл (если > 200 строк).
library/connectors/ozon/
├── __init__.py ← Экспорты
├── client.py ← Главный класс OzonClient
├── models.py ← Data classes
├── operations.py ← Операции
└── exceptions.py ← Исключения
Подробнее: structure-component.md
| Размер | Действие |
|---|---|
| < 200 строк | ✅ OK |
| 200-500 строк | ⚠️ Рассмотреть разбиение |
| > 500 строк | ❌ Обязательно разбить |
| Размер | Действие |
|---|---|
| < 20 строк | ✅ OK |
| 20-50 строк | ⚠️ Желательно разбить |
| > 50 строк | ❌ Обязательно разбить |
Python (Google Style):
def sync_orders(api_key: str, date_from: str, limit: int = 100) -> Dict[str, int]:
"""Синхронизировать заказы из OZON API.
Args:
api_key: API ключ OZON
date_from: Дата начала в формате YYYY-MM-DD
limit: Максимальное количество заказов (default: 100)
Returns:
Dict с ключами:
- synced: количество синхронизированных заказов
- errors: количество ошибок
Raises:
ValueError: Если date_from в неверном формате
APIError: Если API вернул ошибку
"""
pass
JavaScript/TypeScript (JSDoc):
/**
* Синхронизировать заказы из OZON API.
*
* @param apiKey - API ключ OZON
* @param dateFrom - Дата начала в формате YYYY-MM-DD
* @param limit - Максимальное количество заказов (default: 100)
* @returns Объект с количеством синхронизированных заказов
* @throws {ValueError} Если dateFrom в неверном формате
*/
function syncOrders(apiKey: string, dateFrom: string, limit: number = 100): SyncResult {
// ...
}
Когда комментировать:
- ✅ Сложная логика (алгоритмы)
- ✅ Неочевидные решения
- ✅ Обходы багов/ограничений
- ✅ TODO/FIXME/HACK
Когда НЕ комментировать:
- ❌ Очевидный код
- ❌ Дублирование имени функции
- ❌ Устаревшие комментарии
# ❌ Плохо (очевидно)
# Увеличить счётчик на 1
count += 1
# ✅ Хорошо (объясняет почему)
# OZON API возвращает время в UTC+3, конвертируем в UTC
order_time = order_time - timedelta(hours=3)
from typing import List, Dict, Optional, Union
def get_user(user_id: int) -> Optional[User]:
"""Получить пользователя по ID."""
pass
def process_orders(orders: List[Order]) -> Dict[str, int]:
"""Обработать список заказов."""
pass
Проверка типов:
mypy .
interface User {
id: number;
name: string;
email: string;
}
function getUser(userId: number): User | null {
// ...
}
function processOrders(orders: Order[]): Record<string, number> {
// ...
}
# ✅ Хорошо
try:
risky_operation()
except SpecificError as e:
logger.error(f"Failed: {e}")
raise
```
# ✅ Хорошо
except (ValueError, KeyError) as e:
handle_error(e)
```
python
try:
result = api_call()
except APIError as e:
logger.error(f"API call failed: {e}", exc_info=True)
raise| Проблема | Пример | Правильно |
|---|---|---|
| SQL Injection | f"SELECT * FROM users WHERE id={user_id}" |
Параметризованные запросы |
| Command Injection | os.system(f"rm {filename}") |
subprocess.run(["rm", filename]) |
| Hardcoded credentials | API_KEY = "abc123" |
Переменные окружения |
| eval() | eval(user_input) |
Никогда не использовать |
| pickle | pickle.loads(data) |
Только для доверенных данных |
Подробнее: policy-security.md
ПЕРЕД написанием нового кода — проверить library/ и system/.
library/
├── connectors/ ← API клиенты (OZON, 1C, Telegram)
├── functions/ ← Утилиты (парсеры, валидаторы)
└── internal/ ← Хелперы
Если есть в library/ — использовать, не дублировать.
Подробнее: structure-library.md
# ❌ Плохо (дублирование)
def process_order_a(order):
validate(order)
save(order)
notify(order)
def process_order_b(order):
validate(order)
save(order)
notify(order)
# ✅ Хорошо (переиспользование)
def process_order(order):
validate(order)
save(order)
notify(order)
| Тип | Когда | Инструмент |
|---|---|---|
| Unit | Для каждой функции | pytest, jest |
| Integration | Для API, БД | pytest, supertest |
| E2E | Для критических flow | playwright, cypress |
Минимальное покрытие: 80%
# Python
pytest --cov=. --cov-report=term-missing
# JavaScript
npm test -- --coverage
project/
├── src/
│ └── module.py
└── tests/
├── unit/
│ └── test_module.py
└── integration/
└── test_api.py
Подробнее: process-testing.md
Формат:
type(scope): short description
Longer description if needed
Fixes #123
Типы:
- feat: Новая функция
- fix: Исправление бага
- refactor: Рефакторинг
- docs: Документация
- test: Тесты
- chore: Инфраструктура
Пример:
feat(ozon): add order sync method
Implemented sync_orders() method that fetches
orders from OZON API and saves to database.
Fixes #42
main ← Продакшн
dev ← Разработка
test ← Тестирование
feature/* ← Фичи
fix/* ← Багфиксы
black, prettier)ruff, eslint)mypy, tsc)pytest, npm test)#!/bin/bash
# .git/hooks/pre-commit
echo "Running pre-commit checks..."
# Форматирование
black . || exit 1
prettier --write . || exit 1
# Линтинг
ruff check . || exit 1
eslint . || exit 1
# Типы
mypy . || exit 1
# Тесты
pytest || exit 1
echo "✅ All checks passed"
| Политика | Связь |
|---|---|
| policy-security.md | Безопасность кода |
| policy-code-data-separation.md | Разделение код/данные |
| policy-docker.md | Docker контейнеры |
| format-code.md | Стиль кода |
| naming-variables.md | Именование переменных |
| structure-library.md | Организация библиотеки |
Версия: 1.0.0
Статус: active
Владелец: architect