gitaspen docs

REUSE — конфлюэнтность и переиспользование

Один закон, работающий на всех уровнях гранулярности: то же, что делает хорошим коммит, делает хорошим модуль, компонент, движок и продукт. BM (BMFP / BMBP / BMAP) описывает один продукт изнутри. Этот документ — как единицы переиспользуются между продуктами и как это удерживается в git.

5 минут

Один закон, работающий на всех уровнях гранулярности: то же, что делает хорошим коммит, делает хорошим модуль, компонент, движок и продукт. BM (BMFP / BMBP / BMAP) описывает один продукт изнутри. Этот документ — как единицы переиспользуются между продуктами и как это удерживается в git.

Конфлюэнтная единица

Единица любого размера конфлюэнтна, если держит четыре свойства одновременно:

СвойствоЧто значит
Цельностьодна ответственность; ничего лишнего, ничего недостающего
Самодостаточностьимеет свою границу (контракт), собирается и проверяется сама, не втягивает соседей внутрь
Неразрушениене ломает рабочее состояние соседей и прошлого; добавляется, не подламывая существующее
Однонаправленностьпотребители зависят от неё; она не зависит от того, кто выше неё

Детектор костыля: если внутри единицы появляется знание о конкретном потребителе (if (хост == X)), свойство самодостаточности нарушено — знание выносится наружу, в потребителя.

Уровни — одно правило, разная гранулярность

УровеньЕдиницаКонтракт (граница)Где живёт
Коммитсвязное изменениесообщение + рабочее деревоистория репо
Модуль / функцияслой sharedсигнатурывнутри пакета (BM)
Компонент / виджетUI-кусокprops / событияпакет, алиас в сборку
Движокhost-agnostic ядропубличный APIотдельный репо
Сервисдоменная зонаконверт { status, data }отдельный бэк (BMBP)
Продуктсборка единицпоставкаотдельный репо (BMAP)

Четыре свойства из предыдущего раздела одинаковы на каждой строке. Меняется только размер единицы и форма её контракта. Поэтому правило не нужно учить заново на каждом уровне — оно одно.

Движок и оболочка

Внутри продукта единица расслаивается по знанию о хосте:

  • Движок — host-agnostic ядро (чистая логика + рендер), не знает, где исполняется.
  • Оболочка — тонкая привязка движка к конкретному хосту (ОС, чужая ОС, киоск, сайт).

Переиспользуется движок; оболочка остаётся в продукте. Это та же однонаправленность слоёв из BM, но на оси «знание о хосте»: движок ← оболочка, не наоборот.

Жизненный цикл выделения

Корень — расширяемость: модульность нужна, чтобы система росла; переиспользование — её побочный приз. Выделение не проектируется заранее — оно вызревает:

  1. Рождение в месте нужды

    Способность живёт внутри продукта, который первым её потребовал. Выносить раньше — преждевременная абстракция, тот же костыль наоборот.

  2. Перерос место — выделение

    Способность выделяется, когда переросла своё место: либо нужна второму потребителю, либо выросла в самостоятельную часть, которой нужен свой пайплайн/жизненный цикл. Тогда она переезжает в свою единицу за границами продукта — свой репо/папка, своя история, своя обвязка (манифест зависимостей, тесты, README), свой контракт.

  3. Потребление по зависимости

    Оба продукта подключают её как зависимость, закреплённую версией. Никто не копирует и не форкает.

Триггер выделения — реальная потребность (второй потребитель или собственный размер/пайплайн), не предполагаемая. Не раньше — но и не держим силой, когда единица уже переросла место.

Топология

  • Продуктовый репо содержит сборку и оболочки (всё хостовое) и зависит от shared-единиц.
  • Shared-единица — сосед продуктов, а не их ребёнок. Её канонический репозиторий, история и владение находятся вне продукта. Локальный checkout зависимости может быть смонтирован в канонический слот продукта (например, frontend/modules/<module> BMAP) через workspace или submodule, но это не меняет владение и не превращает модуль в дочерний репозиторий продукта.
  • Зависимости между репозиториями однонаправленны, как слои внутри BM: продукт → shared → фундамент. Shared не знает о продукте. Циклов нет.
  • Подключение — менеджером пакетов / workspace / submodule, с закреплённой версией. Контракт стабилен и версионируется: внутренние изменения единицы не ломают потребителя (semver по смыслу).

Git

  • Всё под git с первого файла. Кода вне git нет — ни у продукта, ни у shared-единицы.
  • Local-first. Git работает полностью локально; удалённый репозиторий — синхронизация и бэкап, не условие работы.
  • Граница репо = граница единицы. Выделили способность — она получает свой репо и свою историю, а не размазана по чужой.

Локальная разработка shared-единицы и продукта идёт в одном workspace: весь исходный код уже на диске, IDE видит обе границы, а сборка не требует сети. Универсальное изменение коммитится в репозиторий shared-единицы, после чего продукт обновляет закреплённую версию. Специфичное для продукта знание остаётся в его оболочке. Постоянные ветки и отдельные копии shared-кода под потребителей не создаются.

Коммит — наименьшая конфлюэнтная единица

Те же четыре свойства, спроецированные на коммит:

СвойствоНа коммите
Цельностьодна подсистема = один коммит; часто и гранулярно
Самодостаточностьсобирается и проходит проверки сам по себе
Неразрушениедерево рабочее на каждом коммите (история bisectable); прошлое не переписывается деструктивно
Однонаправленностьопирается на предыдущие коммиты, не требует будущих
  • Сообщение — сухое, type(scope): что. Факт, без пафоса.
  • Автор — человек; без авто-атрибуции инструментов.

Словарь

  • Конфлюэнтность — свойство единицы быть цельной, самодостаточной, неразрушающей и однонаправленно-зависимой; одинаково на всех уровнях.
  • Единица — носитель конфлюэнтности любого размера: коммит / модуль / компонент / движок / сервис / продукт.
  • Движок / оболочка — host-agnostic ядро и тонкая привязка к хосту; переиспользуется ядро.
  • Выделение (graduation) — переезд способности из продукта в собственную shared-единицу при появлении второго потребителя.
  • Shared-единица — самодостаточный переиспользуемый пакет за границами продуктов, со своим контрактом, историей и обвязкой.
  • Контракт единицы — её публичная форма (props/события, API, конверт); внутренности скрыты, потребитель зависит только от формы.
Инструкция не помогла?

Откройте исходник документа по ссылке «Предложить правку» — там же видно, что и когда в нём менялось.