architect/standards/1-structure/structure-hierarchy.md

type: standard
aspect: structure
title: "СТАНДАРТ: Иерархия сущностей и классов"
version: 1.0.0
date: 2026-02-19
status: active


СТАНДАРТ: Иерархия сущностей и классов

Версия: 1.0.0
Дата: 2025-12-26
Статус: СТАНДАРТ
Уровень: У2 (Обязательно)


НАЗНАЧЕНИЕ

Единая система классификации всех сущностей (классов, модулей, функций) в платформе и проектах.

Решает:
- Где размещать код (library/ vs projects/)
- Как называть классы
- Как структурировать приложения
- Какие зависимости допустимы


СОДЕРЖАНИЕ

  1. Три измерения классификации
  2. Уровни платформы L0-L6
  3. Типы сущностей
  4. Слои внутри приложения
  5. Правила размещения
  6. Именование
  7. Матрица принятия решений
  8. Примеры

1. ТРИ ИЗМЕРЕНИЯ КЛАССИФИКАЦИИ

Любая сущность классифицируется по трём независимым измерениям:

┌─────────────────────────────────────────────────────────────┐
                                                             
  ИЗМЕРЕНИЕ 1: УРОВЕНЬ ПЛАТФОРМЫ (L0-L6)                     
  ────────────────────────────────────                        
  Где живёт код в экосистеме                                 
                                                             
  L0-L2  architect/       Методология                       
  L3     system/          Движок платформы                  
  L4     library/         Универсальные компоненты          
  L5     components/      Готовые решения (БУДЕТ)           
  L6     projects/        Конкретные проекты                
                                                             
├─────────────────────────────────────────────────────────────┤
                                                             
  ИЗМЕРЕНИЕ 2: ТИП СУЩНОСТИ (роль в системе)                
  ─────────────────────────────────────────                  
  Что делает класс/модуль                                    
                                                             
  Primitive  Function  Connector  Adapter  Service       
  (данные)   (атом)      (транспорт) (маппинг)  (логика)    
                                                             
  + Model, Repository, Parser, Factory, Config...            
                                                             
├─────────────────────────────────────────────────────────────┤
                                                             
  ИЗМЕРЕНИЕ 3: СЛОЙ TOGAF (внутри приложения)               
  ──────────────────────────────────────────                 
  Архитектурный слой                                         
                                                             
  MOTIVATION  BUSINESS  DATA  APPLICATION  TECHNOLOGY    
     (зачем)     (как)    (что)     (код)        (где)      
                                                             
└─────────────────────────────────────────────────────────────┘

Пример классификации:

class ProductService:
    """
    УРОВЕНЬ: L6 (projects/pirotehnika/app/pim/)
    ТИП: Service
    СЛОЙ: APPLICATION
    """

2. УРОВНИ ПЛАТФОРМЫ L0-L6

2.1. Определение уровней

Уровень Название Папка Назначение Переиспользование
L0 Философия architect/theory/ Принципы, ценности 100% (универсально)
L1 Методология architect/concept/ Концепции, подходы 100% (универсально)
L2 Стандарты architect/standards/ Правила, паттерны 100% (универсально)
L3 Движок system/core/ Executor, Scheduler 90% (платформа)
L4 Компоненты library/ Коннекторы, функции 70% (переиспользуемо)
L5 Решения components/ (БУДЕТ) Готовые наборы 30% (шаблоны)
L6 Проекты projects/ Бизнес-приложения 0% (уникально)

2.2. Зависимости между уровнями

L6  projects/pirotehnika/app/pim/
      использует
L4  library/connectors/api/ozon/
      использует
L3  system/core/executor/
      использует
L2  architect/standards/
      основаны на
L1  architect/concept/
      основаны на
L0  architect/theory/

ПРАВИЛО ЗАВИСИМОСТЕЙ: Уровень N может импортировать только N-1 и ниже.

# ✅ ПРАВИЛЬНО
# L6 → L4
from library.connectors.api.ozon import OzonConnector

# ❌ НЕПРАВИЛЬНО
# L4 → L6 (обратная зависимость!)
from projects.pirotehnika.app.pim import ProductService

2.3. Критерии размещения

Где размещать код:

Вопрос Ответ ДА → Ответ НЕТ →
Это универсальный принцип? L0-L2 architect/
Это часть платформы? L3 system/
Можно использовать в других проектах? L4 library/
Это специфика конкретного проекта? L6 projects/ ?

Примеры:

Сущность Уровень Путь
OzonConnector L4 library/connectors/api/ozon/
1C OData клиент L4 library/connectors/data/1c/
ProductService (PIM) L6 projects/pirotehnika/app/pim/core/
Маппинг 1С → PIM L6 projects/pirotehnika/data/connectors/1c/
Excel парсер L4 library/parsers/xlsx/

3. ТИПЫ СУЩНОСТЕЙ

3.1. Полная классификация

┌──────────────────────────────────────────────────────────────┐
  L2: PRIMITIVES (атомы данных)                               
├──────────────────────────────────────────────────────────────┤
  Type           Dataclass, Pydantic модель, TypedDict       
  Enum           Перечисление (IntEnum, StrEnum)             
  Constant       CONST = value                                
  Exception      class MyError(Exception)                     
└──────────────────────────────────────────────────────────────┘
          используются в
┌──────────────────────────────────────────────────────────────┐
  L3: FUNCTIONS (атомы логики)                                
├──────────────────────────────────────────────────────────────┤
  Validator      def validate_inn(inn: str) -> bool          
  Formatter      def format_money(amount: int) -> str        
  Normalizer     def normalize_phone(phone: str) -> str      
  Calculator     def calculate_price(base, margin) -> Decimal
  Generator      def generate_uuid() -> str                  
  Transformer    def transform_to_dict(obj) -> dict          
└──────────────────────────────────────────────────────────────┘
          используются в
┌──────────────────────────────────────────────────────────────┐
  L4: COMPONENTS (молекулы)                                   
├──────────────────────────────────────────────────────────────┤
  Connector      Связь с внешним API/системой                
  Parser         Чтение структурированных данных             
  Adapter        Преобразование формата A  B                
  Mapper         Маппинг полей между сущностями              
  Repository     Доступ к хранилищу данных                   
  Cache          Кеширование                                 
  Queue          Очереди задач                               
  Factory        Создание объектов                           
└──────────────────────────────────────────────────────────────┘
          используются в
┌──────────────────────────────────────────────────────────────┐
  L5: SERVICES (оркестрация)                                  
├──────────────────────────────────────────────────────────────┤
  Service        Бизнес-логика (ProductService)              
  SyncService    Синхронизация данных между системами        
  Worker         Фоновые задачи (Celery task)                
  Handler        Обработчик событий                          
  UseCase        Сценарий использования (CQRS)               
└──────────────────────────────────────────────────────────────┘
          используются в
┌──────────────────────────────────────────────────────────────┐
  L6: INTEGRATIONS (экосистемы)                               
├──────────────────────────────────────────────────────────────┤
  Integration    Связка систем (OZON  1C)                   
  Pipeline       Конвейер обработки данных                   
  Workflow       Многоэтапный процесс                        
└──────────────────────────────────────────────────────────────┘

3.2. Детальное описание типов

Connector (Коннектор)

Назначение: Связь с внешней системой (API, БД, файл).

Характеристики:
- Инкапсулирует транспортный протокол (HTTP, SQL, gRPC)
- Знает о QUIRKS (особенностях) внешней системы
- Предоставляет domain-agnostic интерфейс

Структура:

class OzonConnector:
    """OZON Seller API Connector"""

    async def _request(self, method: str, endpoint: str, **kwargs) -> Dict:
        """Базовый HTTP запрос"""

    async def get_orders(self, status: str) -> List[Dict]:
        """Получить заказы"""

Размещение:

library/connectors/api/ozon/
├── client.py           OzonConnector
├── SPEC.md             Спецификация API
├── QUIRKS.md           Особенности (!!)
└── STATUS.md           Статус тестирования

Parser (Парсер)

Назначение: Чтение структурированных данных (Excel, CSV, XML, JSON, HTML).

Характеристики:
- Знает формат данных
- Возвращает list[dict] или dataclass
- НЕ знает о бизнес-логике

Структура:

class ExcelParser:
    """Generic Excel parser"""

    def parse(self, file_path: str, config: ParserConfig) -> List[Dict]:
        """Parse Excel file"""

Размещение:

library/parsers/xlsx/
├── parser.py           ExcelParser
├── auto_mapper.py      Автоопределение колонок
└── SPEC.md

Adapter / Mapper (Адаптер / Маппер)

Назначение: Преобразование данных из формата A в формат B.

Различие:
- Mapper — маппинг полей (field-level)
- Adapter — преобразование сущности (entity-level)

Структура:

class OzonAdapter:
    """Адаптирует данные OZON к унифицированной модели Order"""

    def adapt(self, ozon_data: Dict) -> Order:
        """OZON dict → Order dataclass"""

class FieldMapper:
    """Маппинг полей 1С → PIM"""

    GUID_TO_FIELD = {
        'b86639de-...': 'brand',
        '0699197f-...': 'category'
    }

    def map_field(self, guid: str, value: Any) -> Tuple[str, Any]:
        """GUID → (field_name, normalized_value)"""

Размещение:

library/adapters/ozon/            Универсальный адаптер
projects/.../data/connectors/     Специфичный маппер

Repository (Репозиторий)

Назначение: Доступ к хранилищу данных (БД, кеш, файлы).

Характеристики:
- Инкапсулирует работу с БД
- Предоставляет CRUD операции
- Может содержать специфичные запросы

Структура:

class ProductRepository:
    """Репозиторий товаров"""

    async def get_by_article(self, article: str) -> Optional[Product]:
        """Получить товар по артикулу"""

    async def save(self, product: Product) -> None:
        """Сохранить товар"""

    async def find_by_brand(self, brand: str) -> List[Product]:
        """Найти товары бренда"""

Размещение:

# Универсальный
library/storages/postgres/repository.py

# Специфичный
projects/.../app/pim/repositories/product_repo.py

Service (Сервис)

Назначение: Бизнес-логика, оркестрация операций.

Характеристики:
- Координирует работу компонентов L4
- Содержит бизнес-правила
- Транзакционность

Структура:

class ProductService:
    """Управление товарами"""

    def __init__(
        self,
        repository: ProductRepository,
        pricing: PricingService
    ):
        self.repo = repository
        self.pricing = pricing

    async def create_product(self, data: ProductCreate) -> Product:
        """
        Создать товар:
        1. Валидация
        2. Расчёт цены
        3. Сохранение
        """
        # Validate
        if not self._validate(data):
            raise ValidationError()

        # Calculate price
        cost = await self.pricing.calculate_cost(data.base_price, data.brand)

        # Save
        product = Product(**data.dict(), cost_price=cost)
        await self.repo.save(product)

        return product

Размещение:

projects/.../app/pim/core/services/

Factory (Фабрика)

Назначение: Создание объектов по конфигурации.

Характеристики:
- Создаёт экземпляры других классов
- Использует конфигурацию
- Может генерировать код

Структура:

class ParserFactory:
    """Фабрика парсеров"""

    def create_parser(self, supplier: str, config: Dict) -> BaseParser:
        """Создать парсер для поставщика"""

        if supplier == "jf":
            return JFPyroParser(config)
        elif supplier == "maxsem":
            return MaxsemParser(config)

3.3. Модели данных (Models)

Два типа моделей:

ORM Models (Persistence)

Таблицы БД через SQLAlchemy/Django ORM.

from sqlalchemy import Column, String, Numeric
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class PimProduct(Base):
    __tablename__ = 'pim_products'

    article = Column(String(50), primary_key=True)
    name = Column(String(500), nullable=False)
    base_price = Column(Numeric(10, 2), nullable=False)

Размещение:

projects/.../app/pim/models/product.py

Domain Models (Business Logic)

Pydantic, dataclass — бизнес-сущности.

from pydantic import BaseModel, Field
from decimal import Decimal

class Product(BaseModel):
    article: str
    name: str
    base_price: Decimal = Field(gt=0)

    def calculate_retail(self, margin: Decimal) -> Decimal:
        """Бизнес-логика расчёта цены"""
        return self.base_price * (1 + margin)

Размещение:

projects/.../app/pim/domain/product.py

3.4. Schemas (DTO)

Назначение: Data Transfer Objects — данные для API.

Характеристики:
- Pydantic модели для валидации
- Request / Response schemas
- НЕ содержат бизнес-логику

from pydantic import BaseModel

class ProductCreate(BaseModel):
    """Схема создания товара"""
    article: str
    name: str
    base_price: Decimal

class ProductResponse(BaseModel):
    """Схема ответа API"""
    article: str
    name: str
    base_price: Decimal
    cost_price: Decimal
    retail_price: Decimal

Размещение:

projects/.../app/pim/schemas/product.py

4. СЛОИ ВНУТРИ ПРИЛОЖЕНИЯ

По стандарту TOGAF (5 слоёв):

app/pim/
│
├── design/                       ← MOTIVATION (зачем)
│   ├── VISION.md                 ← Зачем PIM
│   ├── CONCEPT.md                ← Концепция
│   └── DECISIONS.md              ← ADR
│
├── processes/                    ← BUSINESS (как работать)
│   ├── import_workflow.md        ← Процесс импорта
│   └── price_sync.md             ← Синхронизация цен
│
├── standards/                    ← DATA (схема данных)
│   ├── DATABASE.md               ← Таблицы
│   ├── MAPPING_1C.md             ← Маппинг
│   └── VALIDATION.md             ← Правила
│
├── [api/, core/, models/]        ← APPLICATION (код)
│
└── deployment/                   ← TECHNOLOGY (инфра)
    └── DEPLOYMENT.md

Внутри APPLICATION слоя:

api/              ← Внешний интерфейс (REST, GraphQL)
core/             ← Бизнес-логика
  ├── services/   ← Оркестрация
  ├── domain/     ← Domain models + правила
  └── use_cases/  ← Сценарии (опционально, CQRS)

models/           ← ORM модели (персистентность)
schemas/          ← DTO (API contracts)
repositories/     ← Доступ к данным (опционально)

external/         ← Внешние зависимости
  ├── connectors/ ← Специфичные коннекторы
  └── adapters/   ← Специфичные адаптеры

5. ПРАВИЛА РАЗМЕЩЕНИЯ

5.1. Алгоритм принятия решения

┌───────────────────────────────────────┐
 Это универсальный принцип?            
 (применим к любому проекту)           
└───────┬───────────────────────────────┘
        
   ДА      НЕТ
        
┌───────────────────────────────────────┐
 architect/                            
 L0-L2: Методология                    
└───────────────────────────────────────┘
        
         НЕТ
        
┌───────────────────────────────────────┐
 Это часть движка платформы?           
 (executor, scheduler, агенты)         
└───────┬───────────────────────────────┘
        
   ДА      НЕТ
        
┌───────────────────────────────────────┐
 system/core/                          
 L3: Движок                            
└───────────────────────────────────────┘
        
         НЕТ
        
┌───────────────────────────────────────┐
 Можно использовать в других проектах? 
 (OZON, Telegram, 1C, валидаторы)      
└───────┬───────────────────────────────┘
        
   ДА      НЕТ
        
┌───────────────────────────────────────┐
 library/                              
 L4: Универсальные компоненты          
└───────────────────────────────────────┘
        
         НЕТ
        
┌───────────────────────────────────────┐
 Это специфика конкретного проекта?    
 (ProductService, маппинг 1СPIM)      
└───────┬───────────────────────────────┘
        
   ДА   
        
┌───────────────────────────────────────┐
 projects/{project}/                   
 L6: Бизнес-приложение                 
                                       
  app/{app}/   Приложение             
  data/        Код про данные         
└───────────────────────────────────────┘

5.2. Матрица размещения

Сущность Универсальность Уровень Путь
Connector к OZON Да (многие проекты продают на OZON) L4 library/connectors/api/ozon/
Connector к 1С Да (многие используют 1С) L4 library/connectors/data/1c/
Excel парсер Да (универсальный) L4 library/parsers/xlsx/
Валидатор ИНН Да (универсальный) L3 library/functions/validate/inn.py
Маппинг 1С→PIM Нет (специфика пиротехники) L6 projects/.../data/connectors/1c/mapper.py
ProductService Нет (специфика PIM) L6 projects/.../app/pim/core/services/product.py
PimProduct модель Нет (специфика PIM) L6 projects/.../app/pim/models/product.py

6. ИМЕНОВАНИЕ

6.1. Суффиксы классов

Тип Суффикс Пример
Connector Connector, Client OzonConnector, TelegramClient
Parser Parser ExcelParser, CSVParser
Adapter Adapter OzonAdapter, Product1CAdapter
Mapper Mapper FieldMapper, CategoryMapper
Service Service ProductService, PricingService
Repository Repository, Repo ProductRepository
Factory Factory ParserFactory, ConnectorFactory
Model (ORM) Без суффикса или Model Product, PimProduct
Schema (DTO) Create, Update, Response ProductCreate, ProductResponse

6.2. Префиксы

Префикс Назначение Пример
Base- Абстрактный базовый класс BaseConnector, BaseParser
Abstract- ABC интерфейс AbstractRepository
I- Interface (TypeScript style) IProductService

6.3. Именование файлов

Содержимое Имя файла
Один класс class_name.py (snake_case)
Несколько связанных module_name.py
Константы constants.py или CONSTANTS.py
Типы types.py
Exceptions exceptions.py

Примеры:

library/connectors/api/ozon/
├── client.py               OzonConnector
├── types.py                OzonCredentials, OzonOrder
├── exceptions.py           OzonAPIError
└── constants.py            OZON_BASE_URL

7. МАТРИЦА ПРИНЯТИЯ РЕШЕНИЙ

7.1. Где разместить код?

Вопрос library/ projects/
Зависит от специфики проекта? ❌ Нет ✅ Да
Можно использовать в других проектах? ✅ Да ❌ Нет
Содержит бизнес-логику? ❌ Нет ✅ Да
Знает о предметной области? ❌ Нет ✅ Да
Универсальный компонент? ✅ Да ❌ Нет

Примеры:

# ❌ НЕПРАВИЛЬНО: OzonConnector в projects/
# Он универсальный, нужен многим проектам!
projects/pirotehnika/app/ozon/connector.py

# ✅ ПРАВИЛЬНО: OzonConnector в library/
library/connectors/api/ozon/client.py

# ✅ ПРАВИЛЬНО: ProductService в projects/
# Специфика PIM, не нужен другим проектам
projects/pirotehnika/app/pim/core/services/product.py

# ✅ ПРАВИЛЬНО: Маппинг 1С→PIM в projects/
# Специфика пиротехники (GUID категорий)
projects/pirotehnika/data/connectors/1c/field_mapper.py

7.2. Какой тип класса использовать?

Задача Тип класса
Обращение к внешнему API Connector
Чтение Excel/CSV Parser
Преобразование формата данных Adapter
Маппинг полей A → B Mapper
Бизнес-логика, оркестрация Service
Доступ к БД Repository
Создание объектов Factory
Данные для API Schema (DTO)
Таблица БД Model (ORM)
Бизнес-сущность Domain Model

8. ПРИМЕРЫ

8.1. Пример: PIM Service

Классификация компонентов PIM

Компонент Уровень Тип Слой Путь
ProductService L6 Service APPLICATION projects/.../app/pim/core/services/product.py
PimProduct L6 Model (ORM) DATA projects/.../app/pim/models/product.py
ProductCreate L6 Schema (DTO) APPLICATION projects/.../app/pim/schemas/product.py
FieldMapper (1C→PIM) L6 Mapper APPLICATION projects/.../data/connectors/1c/field_mapper.py
ExcelParser L4 Parser - library/parsers/xlsx/parser.py
1C OData Client L4 Connector - library/connectors/data/1c/client.py

Структура PIM (правильная)

projects/pirotehnika/

├── app/pim/                               APPLICATION
   ├── design/                            MOTIVATION
      └── CONCEPT.md
   
   ├── processes/                         BUSINESS
      └── import_workflow.md
   
   ├── standards/                         DATA (схемы)
      ├── DATABASE.md
      └── VALIDATION.md
   
   ├── api/                               APPLICATION: API
      ├── products.py
      └── pricing.py
   
   ├── core/                              APPLICATION: Логика
      ├── services/
         ├── product_service.py         ProductService
         └── pricing_service.py         PricingService
      └── domain/
          └── product.py                 Product (domain model)
   
   ├── models/                            DATA: ORM
      ├── product.py                     PimProduct
      └── pricing.py                     PimCostRule
   
   ├── schemas/                           APPLICATION: DTO
      ├── product.py                     ProductCreate, ProductResponse
      └── pricing.py
   
   ├── repositories/                      DATA: Репозитории (опционально)
      └── product_repo.py
   
   └── deployment/                        TECHNOLOGY
       └── DEPLOYMENT.md

└── data/                                  КОД ПРО ДАННЫЕ
    ├── connectors/                        Адаптеры к источникам
       ├── 1c/                            1С специфика проекта
          ├── field_mapper.py            FieldMapper
          ├── category_mapper.yaml       GUID  категории
          └── adapter.py                 Использует library/1c/
       
       └── suppliers/                     Парсеры прайсов
           ├── jf_pyro.py                 Специфичный парсер
           └── maxsem.py                  Специфичный парсер
    
    └── scripts/
        └── process.py                     Обработка входящих

Использование library/:

# projects/.../data/connectors/1c/adapter.py

from library.connectors.data.1c import OneCConnector  # L4
from library.functions.normalize import normalize_price  # L3

class PIM1CAdapter:
    """Адаптер 1С → PIM для пиротехники"""

    def __init__(self):
        self.client = OneCConnector(...)  # Универсальный клиент

    async def fetch_products(self) -> List[Dict]:
        """Получить товары из 1С"""
        raw_data = await self.client.get_catalog()
        return [self._adapt(item) for item in raw_data]

    def _adapt(self, item: Dict) -> Dict:
        """Преобразовать 1С → PIM"""
        return {
            'article': item['Артикул'],
            'name': item['Description'],
            'base_price': normalize_price(item['Цена']),  # L3 function
            'category': self.GUID_MAPPING[item['Parent_Key']]  # Специфика
        }

8.2. Пример: OZON Integration

Классификация

Компонент Уровень Тип Путь
OzonConnector L4 Connector library/connectors/api/ozon/client.py
OzonAdapter L4 Adapter library/adapters/ozon/order_adapter.py
OrderSyncService L6 Service projects/.../app/ozon/core/sync_service.py
Order (domain) L6 Domain Model projects/.../app/ozon/domain/order.py

Код

# library/connectors/api/ozon/client.py  (L4)
class OzonConnector:
    """Универсальный OZON API клиент"""

    async def get_orders(self, status: str) -> List[Dict]:
        """Получить заказы (raw API response)"""
        return await self._request("POST", "/v3/posting/fbs/list", {...})

# library/adapters/ozon/order_adapter.py  (L4)
class OzonOrderAdapter:
    """Адаптер OZON order → унифицированная Order"""

    def adapt(self, ozon_data: Dict) -> Order:
        """OZON dict → Order domain model"""
        return Order(
            order_id=ozon_data['posting_number'],
            customer_name=ozon_data['customer']['name'],
            ...
        )

# projects/.../app/ozon/core/sync_service.py  (L6)
class OrderSyncService:
    """Синхронизация заказов OZON → 1C"""

    def __init__(
        self,
        ozon: OzonConnector,      # L4
        adapter: OzonOrderAdapter, # L4
        onec: OneCConnector        # L4
    ):
        self.ozon = ozon
        self.adapter = adapter
        self.onec = onec

    async def sync_new_orders(self) -> int:
        """
        Бизнес-логика синхронизации:
        1. Получить новые заказы из OZON
        2. Адаптировать к Order
        3. Отправить в 1С
        """
        # 1. Extract
        raw_orders = await self.ozon.get_orders("awaiting_packaging")

        # 2. Transform
        orders = [self.adapter.adapt(raw) for raw in raw_orders]

        # 3. Load
        for order in orders:
            await self.onec.create_order(order.to_1c_format())

        return len(orders)

8.3. Антипаттерны

❌ НЕПРАВИЛЬНО: Бизнес-логика в Connector

# library/connectors/api/ozon/client.py
class OzonConnector:
    async def get_orders_and_create_in_1c(self):
        """❌ Коннектор не должен знать о 1С!"""
        orders = await self.get_orders()
        for order in orders:
            await self.onec.create(order)  # НЕПРАВИЛЬНО!

Правильно: Бизнес-логика в Service (L6).


❌ НЕПРАВИЛЬНО: Специфика проекта в library/

# library/connectors/data/1c/field_mapper.py
class FieldMapper:
    """❌ GUID категорий специфичны для пиротехники!"""
    GUID_MAPPING = {
        '0699197f-e960-11ed-919d-3cecefa69fd9': 'Батареи салютов',  # Специфика!
        ...
    }

Правильно: Маппинг в projects/.../data/connectors/1c/.


❌ НЕПРАВИЛЬНО: Обратная зависимость L4 → L6

# library/connectors/api/ozon/client.py
from projects.pirotehnika.app.pim import ProductService  # ❌ ЗАПРЕЩЕНО!

class OzonConnector:
    def __init__(self):
        self.pim = ProductService()  # L4 не может зависеть от L6!

Правильно: Dependency Injection в L6.


8.4. Чеклист проверки

Перед созданием класса:

□ Определил уровень (L0-L6)
□ Определил тип (Connector, Service, Model, etc.)
□ Определил слой TOGAF (если L6)
□ Проверил правило зависимостей (N → N-1)
□ Выбрал правильную папку
□ Использовал правильный суффикс
□ Написал docstring с назначением
□ Добавил в index.yaml (если модуль)

СВЯЗИ

Документ Связь
ECOSYSTEM.md Уровни платформы L0-L6
ORGANIZATION.md Слои TOGAF
../../../library/CLAUDE.md Управление library/
../4-policy/policy-code-data-separation.md Разделение код/данные

ИСТОРИЯ ИЗМЕНЕНИЙ

Версия Дата Изменения
1.0.0 2025-12-26 Первая версия стандарта

Версия: 1.0.0
Дата: 2025-12-26
Статус: СТАНДАРТ