Перейти к основному содержимому

Контроль качества

Философия: Архитектурные правила не должны существовать только в документации. Нарушения должны автоматически блокироваться на этапе разработки, коммита и CI/CD.

Цель: Предотвратить деградацию архитектуры через автоматизированный контроль.

Временные упрощения (MVP)

Схема принятия решения об упрощениях

MAY

  • Допускается для простых проектов (MVP, Landing, прототипов):
    • Упрощенная feature-based структура без всех слоев FSD
    • Отсутствие слоя widgets/ при небольших композициях UI
    • Размещение простой логики страниц непосредственно в pages/
    • Отсутствие явного файла index.ts при сохранении логического контракта модуля
    • Менее строгая декомпозиция модулей при малом объёме кода

MUST

  • Обязательные ограничения сохраняются даже в MVP:
    • Нет циклических зависимостей
    • Нет смешивания доменной логики и инфраструктуры
    • shared/ не используется как свалка доменного кода
    • Импорты между слайсами одного уровня запрещены

Сигналы перехода на полную FSD

MUST: Мигрировать на полную Feature-Sliced Design при появлении:

СигналОписаниеПример
Повторно используемые бизнес-сущностиОдни и те же сущности используются в нескольких фичахUser, Article, Order переиспользуются
Рост числа фич с общими даннымиУвеличилось количество features, работающих с одними entities5+ фич работают с Article
Появление доменных инвариантов и правилПоявились бизнес-правила сущностейВалидация email для корпоративных пользователей
Рост командыНачалась параллельная разработка3+ разработчика работают одновременно
Усложнение пользовательских сценариевПоявились сложные многошаговые процессыОнбординг, чекаут, многошаговые формы
MVP превращается в продуктПроект переходит из прототипа в productionПланируется долгосрочная поддержка

FORBIDDEN: Временное упрощение не должно закрепляться. Если появились сигналы — мигрируйте на полную FSD.


Контроль и автоматизация

MUST

  • Обязательно контролировать следующие правила:

1. Направление зависимостей между слоями

// ❌ FORBIDDEN - нарушение иерархии
// features/article-list/model/use-articles.ts
import { ArticleListPage } from '@/pages/articles'; // features → pages БЛОКИРУЕТСЯ

// entities/article/lib/format-date.ts
import { useArticleFilter } from '@/features/article-filter'; // entities → features БЛОКИРУЕТСЯ

// shared/lib/helpers.ts
import { Article } from '@/entities/article'; // shared → entities БЛОКИРУЕТСЯ

// ✅ CORRECT - правильное направление
// pages/articles/ui/articles-page.tsx
import { ArticleList } from '@/features/article-list'; // pages → features OK

// features/article-filter/model/use-filter.ts
import { Article } from '@/entities/article'; // features → entities OK

// entities/article/lib/format-date.ts
import { formatDate } from '@/shared/lib/formatters/date'; // entities → shared OK

2. Кросс-импорты между модулями одного слоя

// ❌ FORBIDDEN - импорты между features
// features/article-create/model/use-article-form.ts
import { uploadImage } from '@/features/image-upload'; // БЛОКИРУЕТСЯ

// features/auth/model/use-auth.ts
import { showNotification } from '@/features/notifications'; // БЛОКИРУЕТСЯ

// ❌ FORBIDDEN - импорты между entities
// entities/user/lib/get-full-name.ts
import { Article } from '@/entities/article'; // БЛОКИРУЕТСЯ

// ✅ CORRECT - композиция на уровне pages/widgets
// widgets/article-form/ui/article-form-widget.tsx
import { ArticleForm } from '@/features/article-create';
import { ImageUploader } from '@/features/image-upload';

3. Соблюдение Public API

// ❌ FORBIDDEN - глубокие импорты
import { ArticleCard } from '@/entities/article/ui/article-card'; // БЛОКИРУЕТСЯ
import { useArticle } from '@/entities/article/model/use-article'; // БЛОКИРУЕТСЯ
import { articleApi } from '@/entities/article/api/article-api'; // БЛОКИРУЕТСЯ

// ✅ CORRECT - импорт через Public API
import { ArticleCard, useArticle } from '@/entities/article'; // OK
  • Обязательно использовать инструменты:

  • eslint-plugin-boundaries — контроль зависимостей между слоями

  • TypeScript paths — настройка алиасов импортов (@/entities/*, @/features/*)

SHOULD

  • Рекомендуется настроить дополнительный контроль:
    • Pre-commit hooks (lint-staged + husky) для проверки перед коммитом
    • CI/CD pipeline с обязательными проверками ESLint
    • TypeScript strict mode для строгой типизации
    • Conventional Commits для стандартизации сообщений коммитов

Пример конфигурации pre-commit:

// package.json
{
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write"]
}
}
# .husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

npx lint-staged

FORBIDDEN

  • Следующие практики запрещены:

1. Игнорирование архитектурных ошибок

// ❌ FORBIDDEN - игнорирование через eslint-disable
// features/article-create/model/use-article-form.ts
// eslint-disable-next-line boundaries/element-types
import { uploadImage } from '@/features/image-upload'; // ЗАПРЕЩЕНО!

// ❌ FORBIDDEN - обход через @ts-ignore
// @ts-ignore
import { ArticleCard } from '@/entities/article/ui/article-card'; // ЗАПРЕЩЕНО!

// ❌ FORBIDDEN - обход через any
const ArticleCard: any = require('@/entities/article/ui/article-card'); // ЗАПРЕЩЕНО!

2. Откладывание исправлений "на потом"

// ❌ FORBIDDEN - TODO для архитектурных нарушений
// TODO: Рефакторить позже, сейчас некогда
// eslint-disable-next-line boundaries/element-types
import { showNotification } from '@/features/notifications';

3. Warnings вместо Errors

// ❌ FORBIDDEN - архитектурные правила как warnings
{
rules: {
'boundaries/element-types': ['warn', { /* ... */ }] // Должно быть 'error'!
}
}

// ✅ CORRECT
{
rules: {
'boundaries/element-types': ['error', { /* ... */ }]
}
}

Обработка нарушений

MUST

  • Нарушения архитектурных правил должны:
ЭтапДействиеРезультат
РазработкаESLint в редакторе❌ Красное подчеркивание, ошибка в консоли
КоммитPre-commit hook❌ Блокировка коммита
CI/CDПроверка в pipeline❌ Блокировка сборки
Pull RequestАвтоматическая проверка❌ Блокировка merge
Code ReviewПроверка ревьюером❌ Request changes
  • Требования к обработке:
    • Нарушения блокируют процесс разработки на всех этапах
    • Архитектурные нарушения — это ошибки, а не предупреждения
    • Нарушения исправляются немедленно, не откладываются

FORBIDDEN

  • При обнаружении нарушений запрещено:
    • ⛔ Игнорировать через // eslint-disable
    • ⛔ Обходить через @ts-ignore или any
    • ⛔ Откладывать исправление "на потом"
    • ⛔ Понижать ошибки до warnings
    • ⛔ Коммитить код с архитектурными нарушениями

Контрольный список для проектов

При старте проекта

  • Определен масштаб: MVP или продукт
  • Выбрана структура: упрощенная или полная FSD
  • Настроен ESLint с eslint-plugin-boundaries
  • Настроены TypeScript paths для алиасов
  • Настроены pre-commit hooks (lint-staged + husky)
  • Настроен CI/CD pipeline с проверками

При разработке

  • Код размещен в правильном слое
  • Нет кросс-импортов между модулями одного слоя
  • Импорты идут только "вниз" по иерархии
  • Используется Public API (нет глубоких импортов)
  • ESLint не показывает ошибок
  • TypeScript компилируется без ошибок
  • Тесты проходят (если используются)

При Code Review

  • Архитектурные правила соблюдены
  • Нет eslint-disable для архитектурных правил
  • Нет @ts-ignore для обхода типизации
  • Код находится в правильном слое/модуле
  • Public API соблюден
  • Композиция используется правильно