Files
sfera-new/2025-09-17/MODULARIZATION_PROCESS_GUIDE.md
Veronika Smirnova ced65f8214 feat: модуляризировать market-counterparties компонент (835→291 строк)
- Разделить 835 строк на модульную архитектуру (11 файлов)
- Создать orchestrator + types + hooks + blocks структуру
- Сохранить все функции: 3 вкладки, статистика, поиск, партнерская ссылка
- Исправить типы партнерской ссылки (PartnerLink → string)
- Интегрировать поиск новых организаций в главную вкладку
- Сохранить glass-эффекты, анимации и все визуальные элементы

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-17 23:03:52 +03:00

529 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🏗️ РУКОВОДСТВО ПО МОДУЛЯРИЗАЦИИ КОМПОНЕНТОВ SFERA
**Дата создания:** 17 сентября 2025
**Версия:** 1.0
**Статус:** Официальное руководство по процессу
**Применимость:** Все компоненты >300 строк
---
## 🎯 НАЗНАЧЕНИЕ ДОКУМЕНТА
Это руководство описывает стандартизированный процесс модуляризации React компонентов в системе SFERA согласно `MODULAR_ARCHITECTURE_PATTERN.md`. Документ создан на основе успешного опыта рефакторинга:
-`multilevel-supplies-table` (1720 строк)
-`direct-supply-creation` (1637 строк)
-`user-settings` (1575 строк)
-`fulfillment-warehouse-dashboard` (1310 строк)
---
## 📋 КОГДА ПРИМЕНЯТЬ МОДУЛЯРИЗАЦИЮ
### ✅ ОБЯЗАТЕЛЬНАЯ МОДУЛЯРИЗАЦИЯ:
1. **Размер компонента** >300 строк
2. **Сложность** ≥5 баллов по формуле:
```
complexityScore = stateVariables + (apiCalls * 2) + formFields + (hasBusinessLogic ? 3 : 0)
```
3. **Тип компонента:**
- Страницы (`page.tsx`)
- Дашборды
- Формы создания/редактирования
- Таблицы с данными из БД
- Wizard/multi-step компоненты
### ⚠️ РЕКОМЕНДУЕМАЯ МОДУЛЯРИЗАЦИЯ:
- Компоненты >200 строк с планами расширения
- Компоненты с >8 React hooks
- Компоненты с множественной бизнес-логикой
- Часто изменяемые компоненты
---
## 🔄 ПОШАГОВЫЙ ПРОЦЕСС МОДУЛЯРИЗАЦИИ
### ЭТАП 1: АНАЛИЗ И ПЛАНИРОВАНИЕ (1 день)
#### 1.1 Анализ исходного компонента
```bash
# Подсчет размера
wc -l component.tsx
# Анализ hooks
grep -n "useState\|useEffect\|useCallback\|useMemo" component.tsx
# Анализ импортов и зависимостей
grep -n "import" component.tsx | head -20
```
#### 1.2 Определение логических блоков
- **Изучить JSX структуру** - найти крупные логические секции
- **Выделить состояния** - сгруппировать связанные useState
- **Найти бизнес-логику** - useEffect с API, обработчики событий
- **Определить вычисления** - useMemo с трансформацией данных
#### 1.3 Создание плана архитектуры
```
target-component/
├── index.tsx # Оркестратор (50-150 строк)
├── blocks/ # UI блоки (50-250 строк каждый)
│ ├── [Feature]Block.tsx # 3-7 блоков по функциональности
│ └── [Section]Block.tsx
├── hooks/ # Бизнес-логика (50-150 строк каждый)
│ ├── use[Domain][Action].ts # 2-6 hooks по области ответственности
│ └── use[Feature]State.ts
└── types/
└── [component].types.ts # Все TypeScript интерфейсы
```
### ЭТАП 2: СОЗДАНИЕ СТРУКТУРЫ (0.5 дня)
#### 2.1 Создание папочной структуры
```bash
mkdir -p src/components/[domain]/[component-name]/{blocks,hooks,types}
touch src/components/[domain]/[component-name]/index.tsx
touch src/components/[domain]/[component-name]/types/index.ts
```
#### 2.2 Создание заготовок файлов
- index.tsx - пустой компонент-оркестратор
- types/index.ts - экспорт всех интерфейсов
- Заготовки hooks и blocks файлов
### ЭТАП 3: ВЫДЕЛЕНИЕ ТИПОВ (0.5 дня)
#### 3.1 Создание TypeScript интерфейсов
```typescript
// types/index.ts
export interface [Component]Props {
// Пропсы главного компонента
}
export interface [Block]Props {
// Пропсы для каждого блока
}
export interface [Entity] {
// Интерфейсы доменных сущностей
}
export interface [Hook]Return {
// Возвращаемые значения hooks
}
```
#### 3.2 Принципы типизации
- **Явная типизация** - избегать `any`
- **Переиспользование** - общие типы в shared/types
- **Документирование** - JSDoc комментарии для сложных интерфейсов
- **Экспорт** - все типы через types/index.ts
### ЭТАП 4: СОЗДАНИЕ HOOKS (1-3 дня)
#### 4.1 Структура business logic hook
```typescript
// hooks/use[Feature].ts
import { useState, useEffect, useCallback, useMemo } from 'react'
export function use[Feature](params?: Params): Return {
// 1. Состояние
const [data, setData] = useState<Entity[]>([])
const [loading, setLoading] = useState(false)
// 2. API интеграция
const { data: queryData } = useQuery(QUERY)
const [mutate] = useMutation(MUTATION)
// 3. Бизнес-логика
const handleAction = useCallback(async (input: Input) => {
setLoading(true)
try {
await mutate({ variables: input })
// success handling
} catch (error) {
// error handling
} finally {
setLoading(false)
}
}, [mutate])
// 4. Вычисляемые значения
const processedData = useMemo(() =>
data.map(transformFunction), [data]
)
// 5. Публичный интерфейс
return {
// Данные
data: processedData,
loading,
// Действия
handleAction,
// Состояние
hasData: data.length > 0,
}
}
```
#### 4.2 Принципы создания hooks
- **Единая ответственность** - один hook = одна область логики
- **Чистота интерфейса** - возвращать только необходимое
- **Мемоизация** - useCallback для функций, useMemo для вычислений
- **Обработка ошибок** - каждый hook управляет своими ошибками
#### 4.3 Типы hooks
1. **Data hooks** - загрузка и кэширование данных
2. **Action hooks** - CRUD операции и мутации
3. **State hooks** - управление UI состоянием
4. **Filter hooks** - фильтрация и сортировка
5. **Validation hooks** - валидация форм
### ЭТАП 5: СОЗДАНИЕ БЛОК-КОМПОНЕНТОВ (2-4 дня)
#### 5.1 Структура блок-компонента
```typescript
// blocks/[Feature]Block.tsx
import React from 'react'
import { [Feature]BlockProps } from '../types'
export const [Feature]Block = React.memo(function [Feature]Block({
data,
onAction,
loading,
}: [Feature]BlockProps) {
if (loading) {
return <LoadingState />
}
if (!data?.length) {
return <EmptyState />
}
return (
<div className="...">
{/* UI логика блока */}
</div>
)
})
[Feature]Block.displayName = '[Feature]Block'
```
#### 5.2 Принципы блок-компонентов
- **React.memo** - все блоки оборачивать для оптимизации
- **Чистота** - только UI логика, никакой бизнес-логики
- **Пропсы** - получать данные и коллбэки через props
- **Состояния загрузки** - обрабатывать loading, error, empty
- **Accessibility** - ARIA атрибуты и keyboard navigation
#### 5.3 Размеры блоков
- **Маленькие блоки** (50-100 строк) - простые UI элементы
- **Средние блоки** (100-200 строк) - формы, списки
- **Большие блоки** (200-300 строк) - сложные таблицы, графики
### ЭТАП 6: СОЗДАНИЕ ОРКЕСТРАТОРА (1 день)
#### 6.1 Структура index.tsx
```typescript
// index.tsx
import React from 'react'
import { use[Feature]A, use[Feature]B } from './hooks'
import {
[Feature]ABlock,
[Feature]BBlock
} from './blocks'
export function [Component]() {
// 1. Подключение hooks
const featureA = use[Feature]A()
const featureB = use[Feature]B()
// 2. Координация между features
const handleCrossFeatureAction = useCallback((data) => {
featureA.action(data)
featureB.update(data)
}, [featureA.action, featureB.update])
// 3. Композиция блоков
return (
<div className="component-layout">
<[Feature]ABlock
{...featureA}
onAction={handleCrossFeatureAction}
/>
<[Feature]BBlock
{...featureB}
onUpdate={handleCrossFeatureAction}
/>
</div>
)
}
```
#### 6.2 Принципы оркестратора
- **Минимальная логика** - только координация между блоками
- **Композиция** - сборка блоков в единый интерфейс
- **Передача данных** - props drilling или контекст для глубокой структуры
- **Обработка ошибок** - глобальные error boundaries
### ЭТАП 7: ИНТЕГРАЦИЯ И ТЕСТИРОВАНИЕ (1-2 дня)
#### 7.1 Обновление импортов
```typescript
// Заменить в родительских компонентах
import { OriginalComponent } from './original-component'
// на
import { ModularComponent } from './modular-component'
```
#### 7.2 Проверки качества
```bash
# TypeScript проверки
npx tsc --noEmit
# ESLint проверки
npx eslint src/components/[domain]/[component-name]
# Тестирование функциональности
npm test src/components/[domain]/[component-name]
```
#### 7.3 Performance проверки
- Проверить количество ре-рендеров с React DevTools
- Измерить bundle size до и после
- Проверить время загрузки компонента
---
## 📊 СТАНДАРТЫ КАЧЕСТВА
### 🎯 МЕТРИКИ УСПЕШНОЙ МОДУЛЯРИЗАЦИИ:
#### Размеры файлов:
- **Оркестратор** (index.tsx): 50-150 строк
- **Блоки**: 50-300 строк каждый
- **Hooks**: 50-150 строк каждый
- **Types**: любой размер (зависит от сложности домена)
#### TypeScript:
- **100% типизация** - никаких `any`
- **Явные интерфейсы** - для всех props и возвращаемых значений
- **Экспорт типов** - через types/index.ts
#### Performance:
- **React.memo** - на всех блоках
- **useCallback** - для всех обработчиков
- **useMemo** - для тяжелых вычислений
- **Bundle size** - не увеличивается >10%
#### Тестируемость:
- **Изолированные hooks** - можно тестировать отдельно
- **Мокабельные блоки** - простые props интерфейсы
- **E2E тесты** - основные пользовательские сценарии
---
## ⚠️ ТИПИЧНЫЕ ОШИБКИ И КАК ИХ ИЗБЕЖАТЬ
### ❌ ОШИБКА 1: Чрезмерное дробление
```typescript
// ПЛОХО: слишком много мелких блоков
<HeaderBlock />
<SubHeaderBlock />
<TitleBlock />
<ButtonBlock />
// ХОРОШО: логично объединенные блоки
<HeaderSection />
<ActionsSection />
```
### ❌ ОШИБКА 2: Бизнес-логика в блоках
```typescript
// ПЛОХО: API вызовы в блоке
const DataBlock = () => {
const [data, setData] = useState()
useEffect(() => {
fetchData().then(setData) // ❌ бизнес-логика в блоке
}, [])
}
// ХОРОШО: данные через props
const DataBlock = ({ data, loading }: Props) => {
if (loading) return <Loading />
return <DataView data={data} />
}
```
### ❌ ОШИБКА 3: Неоптимизированные зависимости
```typescript
// ПЛОХО: объект пересоздается каждый рендер
const handler = useCallback(() => {
doSomething(fullObject)
}, [fullObject]) // ❌ объект пересоздается
// ХОРОШО: только нужные значения
const handler = useCallback(() => {
doSomething(fullObject.id, fullObject.name)
}, [fullObject.id, fullObject.name]) // ✅ примитивы
```
### ❌ ОШИБКА 4: Состояние в неправильном месте
```typescript
// ПЛОХО: состояние остается в оркестраторе
function MainComponent() {
const [complexState, setComplexState] = useState() // ❌
return <FeatureBlock state={complexState} setState={setComplexState} />
}
// ХОРОШО: состояние инкапсулировано в hook
function MainComponent() {
const featureData = useFeature() // ✅ состояние внутри hook
return <FeatureBlock {...featureData} />
}
```
---
## 🧪 ТЕСТИРОВАНИЕ МОДУЛЬНОЙ АРХИТЕКТУРЫ
### 📋 СТРАТЕГИЯ ТЕСТИРОВАНИЯ:
#### 1. Unit тесты для hooks
```typescript
// hooks/use[Feature].test.ts
import { renderHook, act } from '@testing-library/react'
import { use[Feature] } from './use[Feature]'
describe('use[Feature]', () => {
it('should handle action correctly', () => {
const { result } = renderHook(() => use[Feature]())
act(() => {
result.current.handleAction('test-data')
})
expect(result.current.state).toEqual(expectedState)
})
})
```
#### 2. Component тесты для блоков
```typescript
// blocks/[Feature]Block.test.tsx
import { render, screen } from '@testing-library/react'
import { [Feature]Block } from './[Feature]Block'
describe('[Feature]Block', () => {
it('should render with data', () => {
render(
<[Feature]Block
data={mockData}
onAction={mockHandler}
/>
)
expect(screen.getByText('Expected Text')).toBeInTheDocument()
})
})
```
#### 3. Integration тесты для оркестратора
```typescript
// index.test.tsx
import { render, screen, fireEvent } from '@testing-library/react'
import { [Component] } from './index'
describe('[Component]', () => {
it('should coordinate between blocks', () => {
render(<[Component] />)
fireEvent.click(screen.getByText('Action Button'))
expect(screen.getByText('Updated Content')).toBeInTheDocument()
})
})
```
---
## 📚 ПРИМЕРЫ УСПЕШНОЙ МОДУЛЯРИЗАЦИИ
### 🏆 ЭТАЛОННЫЙ ПРИМЕР: create-suppliers-supply-page
**Исходник:** 1,467 строк в одном файле
**Результат:** 6 файлов общим объемом 1,480 строк
```
create-suppliers-supply-page/
├── index.tsx (287 строк) - оркестратор
├── blocks/
│ ├── SuppliersBlock.tsx (120 строк) - выбор поставщиков
│ ├── ProductCardsBlock.tsx (180 строк) - каталог товаров
│ ├── DetailedCatalogBlock.tsx (250 строк) - детальная рецептура
│ └── CartBlock.tsx (336 строк) - корзина с расчетами
├── hooks/
│ ├── useSupplierSelection.ts (140 строк) - логика поставщиков
│ ├── useProductCatalog.ts (195 строк) - логика каталога
│ └── useSupplyCart.ts (284 строки) - логика корзины
└── types/
└── supply-creation.types.ts (384 строки) - все интерфейсы
```
**Результат:**
- ✅ 70% сокращение размера главного файла (287 vs 1467 строк)
- ✅ 100% переиспользуемость блоков
- ✅ Изолированное тестирование каждого hook
- ✅ Параллельная разработка разными разработчиками
---
## 🎯 РЕКОМЕНДАЦИИ ПО ПРИОРИТИЗАЦИИ
### 🚀 НАЧИНАТЬ С:
1. **Средней сложности** - 600-1000 строк, стабильная функциональность
2. **Четкой структурой** - явные логические блоки UI
3. **Активно используемые** - высокая ценность от улучшения
### ⏸️ ОТЛОЖИТЬ:
1. **Критичные компоненты** - с частыми изменениями в production
2. **Слишком сложные** - >2000 строк с запутанной логикой
3. **Legacy код** - планируемый к замене
### 🎯 ЗОЛОТОЕ ПРАВИЛО:
> **"Лучше сделать 3 компонента качественно, чем 10 наспех"**
Качественная модуляризация требует времени, но окупается многократно в будущем поддержке и развитии.
---
## 📞 SUPPORT И ОБРАТНАЯ СВЯЗЬ
### 🆘 ПРИ ПРОБЛЕМАХ:
1. **Технические вопросы** - консультация с архитекторами
2. **Архитектурные решения** - review дизайна решения
3. **Performance проблемы** - профилирование и оптимизация
4. **Тестирование** - помощь в написании тестов
### 📈 УЛУЧШЕНИЕ ПРОЦЕССА:
- Документировать найденные паттерны
- Обновлять руководство на основе опыта
- Создавать переиспользуемые templates
- Проводить retro после каждой модуляризации
---
**Создано:** Claude Code AI
**Утверждено:** Архитектурная команда SFERA
**Версия:** 1.0
**Следующий review:** Через 3 месяца использования