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

9. Поля и метки

Файл .arch в основном структурный: объявите модуль, объявите интерфейс, объявите процесс. Неструктурная часть — владельцы, версии, URL, оси классификации — живёт в двух связанных, но различных конструкциях: полях и метках.

Эта глава про обе. Короткая версия в начале:

  • Поля описывают, чем вещь является: её команда, URL её репозитория, её CMDB-идентификатор, её базовый путь.
  • Метки классифицируют вещь вдоль оси: её домен, её сетевой сегмент, её зона безопасности, её критичность.

Поля — первоклассные значения. Метки — теги, используемые для проекций (проекций, проверок, группировок). Многое могло бы правдоподобно быть и тем, и другим; практическое правило: если когда-либо захочется сделать по этому group by или focus проекции, делайте метку.

Поля

Поля живут прямо в теле, без обрамляющего блока:

module Orders {
team: Commerce
version: v2
repo.url: "https://github.com/acme/orders"
ext.cmdb.ci: "CI28304858"
base: "/orders"
"Order management service"
}

Каждое поле — это key: value, где:

  • Ключ — идентификатор или путь через точку (repo.url, ext.cmdb.ci). Точечные ключи эквивалентны вложенной объектной структуре; инструменты обрабатывают их единообразно.
  • Значение — один из четырёх скалярных типов:
    • идентификаторCommerce, v2
    • строка в кавычках"any text", многострочные разрешены
    • число42, 3.14
    • булевоtrue, false

Это весь язык значений. Никаких вложенных объектов, никакой системы типов на каждое поле, никаких дженериков, никаких пользовательских форм значений. Инструменты могут интерпретировать значения по соглашению (URL становятся кликабельными, точечные идентификаторы — копируемыми), но парсер обращается с ними со всеми как со скалярами.

Смена мышления. Если вы пришли из конфигурационных языков вроде HCL, JSON или YAML, отсутствие вложенных объектов может ощущаться как ограничение. Это намеренно. Архитектурные описания не нуждаются в выразительности конфигурации; им нужен плоский слой ключ-значение, по которому тривиально делать запросы и группировки. Форма с точкой в ключе (repo.url) покрывает то, для чего использовались бы вложенные объекты.

Описания голой строкой

Голая строка — это поле с зарезервированным смыслом: это описание:

module Payments {
"Core payment processing service for the platform."
}

В теле может быть несколько голых строк-описаний; они склеиваются через \n в порядке объявления. Это позволяет писать многоабзацные описания без одной огромной многострочной строки. Описания рендерятся как markdown плюс два расширения — см. Главу 10.

Метки

Метки идут внутрь блока labels { }:

module Payments {
team: Payments
labels {
domain: Payments
security.zone: PCI
network.segment: Internal
criticality: High
}
}

Каждый key: value внутри labels { } — это одна метка. Ключи могут быть с точкой (security.zone, network.segment); значения используют те же скалярные типы, что и поля.

Метки:

  • Каскадируются. Метка, объявленная на родительском модуле, видна на каждом вложенном модуле, фасете и интерфейсе — если они не объявят ту же метку сами. Именно так domain: Payments на модуле верхнего уровня достигает каждой операции внутри без повторов. См. Главу 18.
  • Управляют проекциями. focus domain: Payments работает, потому что domain — метка. group by team тоже работает — проекции принимают пути полей в дополнение к путям меток, а team — каскадирующее поле.
  • Управляют проверками. Валидаторы читают метки: каждый PCI-сервис должен иметь записанный security.contact, ни один сервис в network.segment: DMZ не может вызывать сервис в network.segment: Internal.

Поле или метка?

Практическое правило снова, с примерами:

Используйте метку, когдаИспользуйте поле, когда
По нему когда-либо захочется group byЗначение — единый факт, уникальный для этой вещи
По нему захочется focus для проекцииЗначение — URL, идентификатор, версия или счётчик
Это ось классификацииЭто идентификатор или указатель
Примеры: domain, security.zone, criticalityПримеры: team, repo.url, version, ext.cmdb.ci, base

team чётко на стороне полей — стандартная библиотека определяет его как required cascade team, обычное каскадирующее поле. Причина, по которой оно используется в group by team, в том, что проекции принимают пути полей наравне с путями меток; выбор между «полем для team» и «меткой для team» был сделан один раз в стандартной библиотеке, так что каждый проект разделяет одно и то же соглашение.

Обратите внимание на одну практическую деталь: метки всегда ведут себя в распространении как cascade-override. У вас не может быть метки «append». Если нужна аккумуляция (список тегов, растущий от родителя к ребёнку), используйте поле с модификатором append — см. Главу 18.

Многострочные строки

Значения-строки в кавычках могут занимать несколько строк. Лексер автоматически снимает отступ:

module Payments {
"
Core payment processing.
Owns authorization, capture, and refund.
Publishes events to the order pipeline.
"
}

Ведущая строка только из пробелов отбрасывается; минимальный отступ, общий для остальных строк, удаляется. Приведённое выше даёт значение "Core payment processing.\nOwns authorization, capture, and refund.\nPublishes events to the order pipeline.".

Единственная распознаваемая последовательность экранирования — \".

Строки в тройных кавычках

Для значений, содержащих двойные кавычки (HTML, фрагменты JSON, регулярные выражения), используйте строки в тройных кавычках. Обратные слэши не являются последовательностями экранирования внутри них:

module Cart {
widget: """
<div class="card" data-name="{{name}}">
<span class="label">{{team}}</span>
</div>
"""
}

Строки в тройных кавычках — сырые. Они не поддерживают интерполяцию в стиле ${expr} (так что будущие возможности шаблонных литералов можно будет добавить позже без конфликтов).

Никакого блока props { }

В ранних версиях Archlang был блок props { } для хранения «дополнительных метаданных». Его больше нет. Эта роль полностью покрывается полями с точечными ключами: ext.cmdb.ci: "...", repo.url: "...". Если вы читаете старые файлы с props { }, запустите форматтер — он их вынесет.

Итоги

  • Поля описывают, чем вещь является. Они живут прямо в теле, без обрамляющего блока.
  • Метки классифицируют вещь вдоль оси. Они живут внутри labels { }.
  • Значения — скаляры: идентификатор, строка в кавычках, число, булево. Никаких вложенных объектов.
  • Описания голыми строками зарезервированы; несколько голых строк склеиваются.
  • Метки управляют проекциями и каскадируются через вложенность; если нужна аккумуляция, используйте поле с append.
  • Выбор «поле или метка?» обычно сводится к: захотите ли вы group by или focus по этому?

Что дальше

Глава 10: Описания → — подмножество markdown и синтаксис перекрёстных ссылок внутри строк-описаний.