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

Направляемые истории

Глава 8 дала вам кураторскую проекцию: нужные узлы, сгруппированные и стилизованные для одной аудитории. Но проекция — это всё ещё картинка, а картинка отвечает на вопрос «что здесь есть», а не «как это читать». Тот, кто её нарисовал, закрывает этот пробел голосом поверх диаграммы, и как только он уходит, пробел возвращается.

История закрывает его в самой модели. Это упорядоченный обход того, что проекция уже рисует — конструкция, которая делает архитектуру объяснимой, а не просто правильной.

view PaymentsStory {
show @@team:"payments"
story {
chapter "Приходит заказ" {
"Покупатель заходит в витрину; создаётся заказ."
Web, Checkout, Orders
}
chapter "Двигаются деньги" {
"Payments списывает с карты, затем Ledger это записывает."
Payments, Bank, Ledger
}
}
}

Это вся авторская поверхность. Заголовки, необязательная заметка и упорядоченный список узлов — намеренно ничего больше.

Читайте этот заголовок буквально. Клауза story не перестилизует доску, не меняет её порядок и ничего не фильтрует. Откройте PaymentsStory обычным образом — и вы получите ровно ту доску, которую описывает show @@team:"payments", как будто клаузы вовсе нет.

История инертна, пока просмотрщик не попросят её показать — параметром ?present=1 в URL (?play=1 включает автопроигрывание и подразумевает ?present=1). В этом весь смысл конструкции: история — это прочтение проекции, поэтому её объявление никогда ничего не стоит обычному читателю. См. Режим презентации ниже.

Ограничение в пять глав — жёсткое правило грамматики, а не рекомендация по стилю. История это обход, который читатель держит в голове, и всё утверждение конструкции состоит в том, что авторская часть остаётся достаточно маленькой, чтобы её имело смысл ревьюить. Шестая глава вызывает диагностику и отбрасывается.

chapter "Двигаются деньги" {
"Payments списывает с карты, затем Ledger это записывает."
Payments, Bank, Ledger
}

Она необязательна и подчиняется тому же закону, что описания модулей и проекций (Глава 10): строка идёт первой, раньше всего остального в теле. Строка, написанная после узлов, это диагностика, а не тихое дописывание — она читается как подпись к отдельному узлу, а у главы нет такого слота.

Узлы разделяются запятыми или переводами строк, и работает любой селектор узлов (Глава 31), а не только голое имя:

chapter "Всё, что закрывает шлюз" {
PaymentGateway, @@zone:"dmz", nodes of (PaymentGateway > *)
}

Порядок и есть смысл. Такт (beat) выводится из каждой пары соседних узлов, поэтому написанный порядок это порядок повествования. Внутри одного селектора, который разрешается в несколько узлов, порядок задаётся детерминированным возрастающим ключом. Узел, названный в главе дважды, появляется один раз — там, где он был введён впервые.

Всё, чего нет в списке выше. Вы никогда не пишете такт, переходную фразу или движение камеры:

ВыводитсяИз чего
тактыкаждая пара соседних узлов
отношение, которое пересекает тактвызывает / вызывается / взаимно / содержит / содержится в / достижим за N переходов / не связаны — от самого конкретного, поэтому прямой вызов никогда не описывается как достижимость за 1 переход
фраза на тактотношение плюс интерфейсы, через которые оно идёт
окно слежения камерыпокинутый узел, текущий узел и следующий (≤3)
передача между главамиразница множеств «остался / вошёл / вышел» относительно предыдущей главы

Именно поэтому история переживает рефакторинг. Перенесите вызов из Payments в новый модуль Settlements, и фраза такта изменится вместе с моделью — потому что эта фраза никогда не была текстом, который вы набрали.

Повествование намеренно не утверждает, синхронный вызов или асинхронный. Это не свойство ребра — это соглашение о поле виджета stdlib в цепочке типов целевого интерфейса (Глава 11) — поэтому такое утверждение было бы догадкой.

Глава обходит только то, что проекция рисует

Заголовок раздела «Глава обходит только то, что проекция рисует»

История едет поверх выборки проекции; она никогда её не расширяет. Глава, выбирающая что-то вне show, сохраняет остальные свои узлы, а глава, у которой не осталось ничего, отбрасывается с диагностикой.

Практическое следствие: когда главе нужен якорь из другого домена, покажите его явно.

view PaymentJourney {
"Как деньги на самом деле движутся через систему."
show @@domain:"Payments" or @@domain:"Orders"
// Шлюз и ledger закрепляют первую и последнюю главы, но живут в других
// доменах — глава может обойти только то, что проекция РИСУЕТ.
show APIGateway or Ledger
story {
chapter "Приходит заказ" {
"Трафик попадает на шлюз и становится заказом."
APIGateway, Orders
}
chapter "Двигаются деньги" {
"Заказ просит Payments списать; шлюз направляет это наружу."
Orders, Payments, PaymentGateway
}
chapter "Внешний мир" {
"Только шлюз общается с процессингом — всё остальное внутреннее."
PaymentGateway, Stripe
}
chapter "И это записывается" {
"Каждое движение попадает в ledger, который никто не вызывает."
Payments, Ledger
}
}
}

Проекция несёт не более одной клаузы представления — table, matrix, grid, flow — а доска это её отсутствие (Глава 8). История не претендует на этот слот. Она едет поверх того, чем проекция уже является, поэтому сочетается с любым из них.

Действуют два ограничения:

  • Не сочетается с focus. Стоящий focus и история оба претендуют на канал акцента, а композиция даёт пересечение — глава, пересечённая с focus, схлопывается почти в пустую доску. Написать оба ничто не мешает; результатом будет просто история, которую незачем показывать, — выберите что-то одно.
  • Одна на проекцию. Экземпляр проекции (Глава 8) не может добавить вторую story поверх родительской. Побеждает собственная история экземпляра, с диагностикой.

?present=1 это ссылка, которую вы кому-то даёте — в этом вся форма фичи:

  • Позиция читателя живёт во фрагменте URL как #beat=<глава>.<остановка>, поэтому на любую остановку можно сослаться из комментария к ревью.
  • ?play=1 включает автопроигрывание и подразумевает ?present=1.
  • Пока история идёт, она забирает канал акцента целиком: узлы главы это фигура, всё остальное — фон.
  • Режим презентации показывает ту проекцию, на которой вы уже находитесь, если у неё есть история, и иначе открывает первую проекцию, которая её объявляет — ссылка на презентацию обязана работать для того, кто никогда не открывал воркспейс, а режим презентации прячет навигацию, через которую он иначе искал бы её. Он направляет один раз: если посреди рассказа вы перешли на другую вкладку, вы там и останетесь.

Параметры ставятся на ту поверхность, которая хостит просмотрщик: встроенный <archlang-viewer> (Глава 23), сессия archlang serve или экспортированный самодостаточный HTML-файл (Глава 21).

  • Онбординг. Тот обход, который старший инженер проводит для новичка у доски, записанный один раз и поддерживаемый в истинности компилятором.
  • Ревью и проектные документы. Ссылка #beat= это цитата: «вот тот переход, к которому у меня вопрос», закреплённая на остановке, а не на скриншоте.
  • Доклад, который вы читаете дважды. Если вы уже объясняли одну и ту же диаграмму в одном и том же порядке больше одного раза, этот порядок и есть история, и ему место в модели.

Не беритесь за историю, чтобы обойти перегруженную доску. Если картинка вообще нечитаема без истории, лечится это более узким show — история объясняет читаемую проекцию, а не спасает нечитаемую.