Мозаический подход¶
«Мозаика — это не просто сборка из частей. Это способ видеть целое через связи.»
Мозаичный подход — это инструмент против энтропии системы.
Он удерживает структуру живой, потому что каждая часть понимает, зачем она существует и к чему она присоединена.
Tip
Когда связи не описаны, проект начинает жить в режиме “латания”: каждое исправление рождает новое искажение.
Но когда связи встроены в саму архитектуру, система становится самообъясняющейся —
изменения происходят без хаоса, потому что их контекст виден изнутри.
Мозаичный подход возвращает смысл связям —
он не про структуру ради структуры, а про осмысленное сопряжение компонентов
📖 Оглавление¶
- 1. Мозаичный подход: от частного к общему
- 2. Ключевые компоненты архитектуры
- 3. Полная структура проекта
- В заключение: применение мозаичного подхода
- Дополнительные материалы
1. Мозаичный подход основан на принципе от частного к общему¶
Это принцип проектирования, при котором проект строится снизу вверх — от автономных элементов (stage) к целостной структуре (pipeline, продукт).
Каждый элемент проверяется, а потом соединяется с другими как часть мозаики.
Принципы¶
- Независимость: каждый этап (stage) можно разрабатывать и тестировать изолированно.
- Инкрементальность: новые этапы добавляются постепенно, без нарушения работы других.
- Гибкость: легко заменить любой
stage, не переписывая систему. - Гармония: финальный пайплайн собирается как мозаика из проверенных модулей (stage).
Преимущества¶
- Параллельная разработка: разные разработчики из команды могут работать над своими этапами независимо.
- Минимизация ошибок: интеграция происходит только после локального тестирования.
- Упрощённое тестирование: каждый элемент проверяется отдельно (unit), а потом в связке (integration).
- Лёгкость масштабирования: систему можно расширять новыми “плитками” (stage).
Ниже рассмотрим ключевые компоненты проекта: pipeline, stage, router, service и utils.
2. Ключевые компоненты архитектуры¶
Базовая структура проекта, опирающегося на мозаичный подход
NameProject/
├─ pipeline/ ← ядро: содержит этапы (stage) и pipeline.py
├─ router/ ← управляет запуском пайплайна и логикой маршрутизации
├─ config.yaml ← ключевые настройки проекта
├─ cli.py ← точка входа для запуска через консоль
├─ README.md ← описание проекта
…
Это только основа основ: ниже приведена полная расширенная структура с примерами и комментариями.
1. Что такое пайплайн¶
Пайплайн — это последовательность логических этапов (stage), которые выполняются для достижения общей цели проекта.
Каждый этап решает свою задачу, но все они связаны одной цепочкой обработки данных и могут быть протестированы как единое целое.
2. Структура этапа (Stage)¶
Каждый stage — это самостоятельная папка, которая реализует конкретную часть логики пеплайна.
В базовом виде структура выглядит так:
pipeline/
├── one_stage_<name>/
│ ├── Stage1Service.py # бизнес-логика этапа
│ ├── __init__.py # пакетный инициализатор
│ └── ...
├── two_stage_<name>/
│ └── ...
└── pipeline.py # задаёт последовательность выполнения
Каждый этап начинается с универсального префикса, отражающего его позицию в цепочке:
one_stage_...— первый этапtwo_stage_...— второй этапthree_stage_...— третий этап- и так далее
💡 Почему текстовые, а не числовые обозначения:
цифры в названиях файлов и пакетов могут вызывать проблемы при импортах.
Поэтому используется текстовая нумерация (one, two, three и т.д.), которая безопасна для Python и читаема человеком.
Название конкретного этапа придумывается кодекс-агентом, который пишет код,
либо разработчиком вручную — важно, чтобы имя отражало суть выполняемой задачи. Запуском этапа управляет StageServer — он активирует нужный модуль и, при необходимости,
обращается к функциям из папки utils/ (см. раздел 6. Бизнес-логика и техническая логика).
3. Service: исполнитель бизнес-логики¶
Service — это модуль или объект, который реализует бизнес-логику конкретного этапа (stage).
Он описывает что именно делает этот этап: собирает данные, анализирует, обрабатывает или публикует.
Для выполнения задач Service использует функции из utils/ — технические инструменты, отвечающие за «как сделать».
💡 Пример:
ВнутриStage1Service.pyбизнес-логика собирает новости.
Для этого она вызывает функции изutils, которые читают файлы, форматируют текст и обращаются к API.
Отличие от роутера:
если Service — это «исполнитель» конкретного действия,
то роутер — это «диспетчер», который решает, какие сервисы и в какой последовательности запускать.
4. Роль роутера (router/)¶
Роутер — это управляющий модуль, который координирует выполнение всего пеплайна.
Он не содержит бизнес-логики, а только запускает нужные этапы (StageService.py) в нужной последовательности.
Обычно роутер появляется на завершающем этапе разработки, когда все stage уже готовы и протестированы отдельно.
На этом этапеrouterстановится своего рода дирижёром, который просто вызывает каждыйStageService.py
в порядке, заданном вpipeline.py.
Основные сценарии работы роутера:
1. Запуск всего пеплайна:
роутер считывает порядок из pipeline.py и запускает все этапы по очереди —
от первого (one_stage_...) до последнего (final_stage_...).
2. Запуск отдельного этапа:
можно вызвать конкретный stage напрямую — например, чтобы проверить новый модуль,
не прогоняя всю цепочку.
💡 В перспективе роутер можно расширить, чтобы он сам определял, какие этапы запускать —
например, на основе параметров, статусов или внешних условий (режимы работы, тестирование, продакшен и т.д.).
5. Организация utils¶
Папка utils — это техническое ядро проекта.
Здесь живёт техническая логика — универсальные функции, которые не зависят от конкретного этапа пеплайна и могут использоваться где угодно.
Если stage — это что делаем, то utils — это чем делаем.
💡 Другими словами:
utils— это набор инструментов, не «знающих» контекста,
но умеющих выполнять стандартные операции: читать файлы, преобразовывать данные, форматировать текст, вызывать API и т.д.
Принцип организации:
utils группируются по типам функций, а не по смыслу этапов.
Это позволяет избежать дублирования и сделать систему модульной:
каждая функция решает одну техническую задачу и может быть вызвана из любого stage.
Пример структуры utils/
utils/
├── io.py # операции с файлами: чтение, запись, парсинг
├── net.py # сетевые операции: запросы, API-вызовы
├── text.py # работа с текстом: очистка, нормализация, токенизация
├── data.py # обработка данных: JSON, CSV, словари
└── system.py # конфигурации, логи, вспомогательные системные вызовы
☝️Важно:
utils никогда не должны «знать», какой конкретный stage их вызывает.
Это делает их чистыми, независимыми и переиспользуемыми —
как строительные блоки, из которых можно собирать любую систему.
3. Полная структура проекта¶
Ниже приведена полная структура проекта, который реализует мозаичный подход.
Она отражает базовый стандарт организации директорий и файлов, принятый в рамках Технического стандарта U.L.I.
Каждый элемент этой структуры соотносится с компонентами, описанными выше: пеплайном, этапами, сервисами, роутером и утилитами. Для оформления описания проекта рекомендуется использовать шаблон 📄 README-template
Основная структура проекта (база)
NameProject/
└── pipeline/
├── one_stage_<name>/ # этап 1 пайплайна
│ ├── Stage1Service.py # скрипт запуска этапа
│ ├── __init__.py
│ └── ... # все подмодули,этапа
├── two_stage_<name>/
│ ├── Stage2Service.py
│ ├── __init__.py
│ └── ...
├── three_stage_<name>/ # этап 3 пайплайна
│ ├── Stage3Service.py
│ ├── __init__.py
│ └── ...
└── pipeline.py
├── router/ ← Роутер
│ └── routes.py
├── utils/ ← Технические утилиты
│ ├── io/ ← Ввод/вывод
│ ├── net/ ← Сетевые операции
│ ├── text/ ← Текстовые операции
│ ├── data/ ← Работа с данными
│ └── system/ ← Логирование, конфиг
├── logs ← Логи системы
├── scripts/
├── tests ← Тесты
├── upgrades ← Апгрейды
├── connectors ← Подключения
├── statistics
├── config.yaml ← Главные настройки
├── cli.py ← Точка входа
├── README.md ← Описание проекта
├── Directory_structure.txt ← Структура директории
├── Makefile
└── __init__.py
NameProject/
├── presets/ ← Пресеты (опционально)
│ ├── default_config.yaml ← Конфигурации по умолчанию
│ └── README.md ← Описание изменений
├── data/ ← Данные (опционально)
├── 🗂️ Chronology_versions/ ← Описание версий проекта
├── templates/ ← Шаблоны (опционально)
└── bootstrap/ ← Инициализация
📘 Пояснение к отдельным папкам проекта¶
📜 scripts/¶
Папка scripts содержит самостоятельные исполняемые скрипты, которые работают вне основного пеплайна. В классической IT-практике сюда помещаются служебные и утилитарные сценарии, выполняющие отдельные задачи: от очистки временных файлов и пересборки данных до тестовых вызовов API и прототипов будущих функций. Эти скрипты могут использовать общие модули из utils/, но не зависят от конкретных stage. Таким образом, scripts/ служит пространством для автономных решений и временных инструментов, которые со временем могут быть интегрированы в основной пеплайн как полноценные этапы.
upgrades/¶
Папка upgrades служит временным пространством для хранения мелких апгрейдов, правок и патчей, возникающих между версиями проекта (например, v1.1, v1.2, v1.3).
В неё помещаются изменения, для которых пока не определено точное место.
Когда таких улучшений накапливается достаточно (формируется “критическая масса”), при переходе на новую крупную версию проекта (v2.0, v3.0 и т.д.) содержимое upgrades/ разбирается:
часть изменений встраивается в существующие stage (если логика дополняет уже имеющийся этап); часть оформляется как новые stage (если апгрейд стал самостоятельным шагом); в исключительных случаях формируется новый pipeline (если изменения создают новую производственную ветвь проекта).
Таким образом, upgrades/ обеспечивает гибкость между версиями и позволяет вносить оперативные улучшения без нарушения целостности структуры пайплайна.
🟡 Важно: папка
upgrades/создаётся и начинает использоваться только после перехода проекта на версию 2.0 и выше.
Она «оживает» тогда, когда в Redmon (или в файле версионности) зафиксировано, что текущая версия проекта ≥ 2.0 — то есть система уже вступила в фазу активных апгрейдов и промежуточных улучшений.
🔌 connectors/¶
Папка connectors/ — это локальная граница интеграций внутри конкретного проекта.
Здесь размещаются адаптеры к внешним сервисам и системам: Telegram, VK, GitHub, Google Docs, OpenAI, webhook, внешним API и другим интеграционным точкам. Каждый connector прячет технические детали взаимодействия: токены, URL, SDK, HTTP-запросы, retries, форматы ответа и обработку ошибок.
Бизнес-логика проекта не должна напрямую знать, как устроен внешний сервис. Вместо этого она вызывает понятные функции уровня проекта: send_operator_message(), publish_post(), load_source_doc(), create_issue() и т.д. Конкретная реализация вызова Telegram, VK, GitHub или OpenAI остаётся внутри connectors/.
Пример локальной структуры:
project/
├── core/ # бизнес-логика проекта
├── connectors/ # адаптеры к внешним сервисам
├── config.py
└── config.toml
Важно: connectors/ не является общей библиотекой для всего DETai-org. Не следует создавать один глобальный каталог connectors/ и подключать его во все проекты: это создаёт неявную связанность между проектами.
Общий код выносится только после того, как один и тот же адаптер стабильно повторился в нескольких проектах и его контракт стал понятен. В этом случае он оформляется не как общий connectors/, а как отдельный пакет или репозиторий, например detai-integrations, detai-common, detai-clients или отдельный репозиторий под конкретную интеграцию.
🧪 tests/¶
Папка tests содержит систему проверок, выстроенную по принципу мозаичной инкрементальной сборки. Каждый этап — например, one_Stage_<name>/, запускаемый через Stage1Service.py, — тестируется изолированно (unit-тесты) для проверки корректности выполнения своей логики. Лишь убедившись, что все stage работают корректно, выполняются mock-тесты, которые имитируют взаимодействие между этапами и проверяют корректность передачи данных, контрактов и последовательности выполнения, гарантируя, что любой stage пайплайна можно заменить или обновить без нарушения целостности всего проекта.
🗂️ Chronology_versions/¶
Папка Chronology_versions хранит описание эволюции проекта — феноменологию изменений между версиями. Здесь фиксируется не только содержательная динамика (какие смыслы, задачи и подходы менялись), но и технологическая хронология, которую можно проанализировать через Codex: какие stage были изменены, какие добавлены, какие, возможно, преобразовались в новые. В редких случаях отмечаются и появления новых pipeline, если они возникли как результат накопленных обновлений и логического роста системы.
В заключение: применение мозаичного подхода¶
Мозаичный подход — не уникальное изобретение, а отражение общепринятых принципов современной инженерии.
Он используется в:
- Микросервисной архитектуре — независимые сервисы объединяются в систему.
- CI/CD-процессах — этапы сборки, тестирования и деплоя выполняются последовательно и автономно.
- Тестировании — от юнит-тестов (проверка отдельных функций) к интеграционным (проверка связей).
Для унификации описаний проектов рекомендуется использовать шаблон 📄 README-template, основанный на том что описано в этом документе.
Дополнительные материалы¶
В этом разделе собраны вспомогательные таблицы и пояснения, которые расширяют понимание мозаичного подхода.
Они показывают, как различать уровни логики, применять архитектуру в разных типах проектов и определять границы пеплайна.
Бизнес-логика 🆚 техническая логика¶
| Характеристика | Бизнес-логика | Техническая логика |
|---|---|---|
| Что делает | Решает смысловую задачу (что нужно системе) | Реализует технические операции (как это сделать) |
| Где живёт | Внутри stage/service.py |
Внутри utils/ |
| Примеры | собрать новости, рассчитать рейтинг, отправить пост | читать файл, форматировать текст, вызвать API |
| Меняется при изменении целей проекта | ✅ Да | ❌ Нет |
| Переиспользуется в других проектах | Иногда | Часто |
Идея:
utils — это сервисы нижнего уровня.
Если stage — это «плитка бизнес-уровня», то utils — это «инфраструктурный слой», поддерживающий все плитки.
Типы проектов и где применима мозаика¶
| Тип проекта | Суть | Подходит ли мозаичная архитектура | Почему |
|---|---|---|---|
| 🧩 Сценарные / логические системы | цепочки шагов, сценарии, обработка данных | ✅ идеально | каждый этап — отдельный stage (обработка, анализ, фильтрация, постинг и т.д.) |
| 🤖 Боты и ассистенты | взаимодействие с пользователем, обработка ответов, логика ветвлений | ✅ подходит | каждый тест, опрос или сценарий можно оформить как отдельный stage или пайплайн |
| ⚙️ Интеграционные системы | сбор, обработка и передача данных между сервисами | ✅ подходит | каждый этап — источник, обработчик или отправитель |
| 🧠 ML / Data Science проекты | анализ и обучение моделей на данных | ⚙️ частично | можно использовать stage-подход, но лучше классическая DS-структура (data/raw → processed → models) |
| 🌐 Web-приложения и сайты | интерфейс, сервер, API | ⚙️ частично | архитектура мозаики может использоваться внутри backend-логики, но не для фронтенда |
| 🎮 Игровые / UX-проекты | визуальные сцены, пользовательские взаимодействия | 🚫 нет | нужна сцено- или объектная структура, мозаика слишком жёсткая |
| 📊 Отчётные / статические проекты | отчёты, визуализации, дашборды | 🚫 нет | нет этапности, это просто визуальный слой |
Как определить границу пеплайн❓¶
Чтобы понять, относится ли новый элемент к существующему пеплайну или это уже отдельный, нужно задать три вопроса:
| Вопрос | Если ответ «да» → остаётся в пеплайн | Если «нет» → создаём новый пеплайн |
|---|---|---|
| 1. Зависит ли этап напрямую от результата предыдущего? | ✅ да | ❌ нет |
| 2. Логика этапов объединена одной целью? | ✅ да | ❌ нет |
| 3. Можно ли протестировать цепочку целиком как один сценарий? | ✅ да | ❌ нет |
Если хотя бы на два вопроса ответ «нет» — это новый пеплайн.
🔸 На практике не всё можно решить только стандартами.
Если считать, что каждый проект — это самостоятельный продукт, то внутри него обычно существует один основной пеплайн. Однако бывают ситуации, когда логика работы требует нескольких пеплайнов — например, для независимых ветвей задач или параллельных процессов. В таких случаях важно не формально следовать правилам, а обсуждать с командой: является ли новый пеплайн на самом деле новым проектом, или он всего лишь ещё одним этапом (stage) в рамках существующего проекта
Чётких критериев здесь нет — граница определяется через коммуникацию, осмысление идеи и общий контекст. Именно это делает мозаичный подход живым: он не фиксированная схема, а способ совместно выстраивать смысловую структуру работы.
Документ подготовлен в соответствии с архитектурными принципами мозаичного подхода и стандартом U.L.I. v1.0.