Приложение D: Шпаргалка
Для случая, когда вы знаете, чего хотите, и вам нужен синтаксис. Каждая строка — полная конструкция; главы и другие приложения связаны для полного контекста.
Простой module — строительный блок по умолчанию; конкретный тип (service, …) — это сахар, к которому прибегают, когда он окупается.
module Orders { rest_create createOrder } // plain module — the defaultservice Orders { // a typed module (sugar) aspect team: "Commerce" rest_create createOrder} // type + name + bodyservice #k7f2 Orders { ... } // with stable ID (random, meaningless)service AuthService in Platform { ... } // attach to a parent declared elsewhereservice Notifications // empty body, no bracesСм. гл. 4.
Интерфейс
Заголовок раздела «Интерфейс»Простой interface — соединение по умолчанию; тип на уровне протокола (rest_create, kafka, …) — это сахар. Называйте интерфейсы по глаголу/ресурсу протокола.
interface authorize // plain interface — the defaultrest_create authorize // typed leaf (sugar)rest_create authorize { // with body "Description" timeout: "5s"}kafka paymentEvents // async event interface (no subscribes:)// an event is an async interface reached by a normal `>` process edge — the edge IS the subscriptionСм. гл. 5.
Поверхность
Заголовок раздела «Поверхность»surface ordersResource { // generic surface base: "/orders" rest_create createOrder}resource ordersResource { base: "/orders" } // user-defined surface typesurface outer { surface inner { ... } } // nested surfacesresource — пользовательский тип, который команды определяют через type surface resource { ... }; стандартная библиотека поставляет только обобщённый surface. См. гл. 6 и гл. 16.
Процесс
Заголовок раздела «Процесс»process Checkout { order = Customer > Orders.createOrder // step, with result binding Orders > Payments.authorize(order) // step with arg list | > Ledger.record // fan: owner = previous line's HEAD (Orders) \ > Audit.log // snake: owner = previous line's TAIL (Ledger) "wait for fraud review" // bare note step (no edge) Orders "ops team double-checks the total" // actor-anchored note
Payments if "stripe-customer" { // exclusive conditional (free-form head) Payments > Stripe.charge } else { Payments > PayPal.charge }
Orders select "payment method" { // multi-way, inclusive (every match runs) stripe: Payments > Ledger.record applepay: Payments > Ledger.record }
Shipping parallel race { // concurrent branches; race = first wins branch: Shipping > Notifications.sendEmail branch: Shipping > Notifications.sendSMS }
Orders try { // error path (guard, continue forward) Orders > Payments.authorize } catch "declined" { Orders > Notifications.sendEmail }
Orders each item in order.items: Orders > Inventory.reserve(item) // iteration (one-liner body)
Order reversible { // saga: completed steps roll back Order > Inventory.reserve unwind Order > Inventory.release // each step compensates itself Order > Payments.charge unwind Order > Payments.refund }
do NotifyCustomer(order) // splice subprocess (ownerless) finish "checkout complete" // terminate: success}
process Checkout in Orders { ... } // attach to a modulesubprocess NotifyCustomer(arg) { Orders > Ledger.record } // reusable helper (args intent-only)Анонимность — минимальный черновик (каждая анонимная часть — это TODO):
module Orders { > Payments // bare step: anon process, implicit caller = Orders > Cart.add // name the interface; caller still implicit}A > B. // trailing dot: B is a module, interface unspecified (TODO)A > B.x > C.y // chain (ordered): desugars to A > B.x ; B > C.yГолые шаги неупорядочены (порядок даёт только обёртка process { }); цепочка — это один упорядоченный анонимный процесс; вызываемый-модуль синтезирует анонимный интерфейс. Ссылайтесь на модули, интерфейсы и подпроцессы, которых ещё нет, — компилятор синтезирует пунктирную заглушку и отслеживает каждый пробел как TODO (черновое проектирование «процесс сначала»), вместо того чтобы выдавать ошибку. archlang validate --complete гейтит модель с нулём TODO. См. гл. 7.
Проекция
Заголовок раздела «Проекция»view PaymentsLandscape { "Description — first line is the header zone" show @@domain:"Payments" or @@security.zone:"PCI" // union selectors; @@ = aspect axis show in Payments or in Gateway // subtree membership hide database // subtract after the show-union group by @@team // cluster by an aspect getter (by VALUE) group by in Payments // by CONTAINMENT — one frame per container style * { color: colorize(@@security.zone) } // colour; explicit cast feeds the legend style violating PciIsolation { color: crimson } // policy findings drive visuals}// one representation clause replaces the board:// table { column @name; sort by @name }// matrix { axis @@team; order by cluster } — or `rows`/`cols` for a rectangular one// grid { rows @@team; cols @@security.zone; color @kind } — cross-tab, cells list modules// flow <Proc> [sequence | bpmn] — `bpmn` opens { lane by @@team | pool by @@team | … }// no layout clause — layout is the solver's; pin per node with `style X { pin <x>, <y> }`.См. гл. 8.
История — направляемый обход проекции; не представление, поэтому сочетается с любым из них, и инертна, пока просмотрщик не открыт с ?present=1:
view PaymentsStory { show @@team:"payments" story { // at most FIVE chapters (hard grammar rule) chapter "Order comes in" { "Leading string is the chapter's note — optional, and it must come first." Web, Checkout, Orders // any node selector; written order IS the narration } chapter "Money moves" { Payments, Bank, Ledger } }}// beats, the relation each crosses, the sentence, the camera window and the// chapter handoff are all DERIVED. Doesn't compose with `focus`; one per view.См. гл. 36.
Поля и аспекты
Заголовок раздела «Поля и аспекты»Поля = структурированные данные. Аспекты = связи между плоскостями (key: "x" — классификация, key: X — членство). Описания = неструктурированная проза.
service Orders { region: euWest // identifier value (a plain field) repo.url: "https://..." // dotted key + string (structured property) version: 2 // number enabled: true // boolean "Description goes here as a bare string."
aspect { domain: "Orders" // string value = classification (a (key, value) tag) broker: KafkaBroker // bare module ref = membership (KafkaBroker becomes a place) }}См. гл. 9.
Описания и markdown-документы
Заголовок раздела «Описания и markdown-документы»"Plain markdown plus archlang extensions.**bold**, *italic*, ~~strike~~, `code`, [link](https://...), tables, lists.
[[#stable_id]] / [[Name]] link to a declaration[[@@key]] / [[@@key:value]] link to an aspect plane / a specific classification[[Doc#section]] link to a heading inside an .md document@@aspectPath substitute an aspect value from THIS node (descriptions only)[[ref]]@@aspectPath read an aspect value on a REFERENCED node (works in .md too)"Каждый элемент также получает автоматические обратные ссылки («упоминается в»). Файлы .md рендерятся той же флавор-разметкой и являются первоклассной поверхностью архпространства. См. гл. 10 и гл. 10a.
package: acme.shop // package root (opaque unit)version: "1.0.0"widgets: "./widgets.js"
repo: "https://github.com/acme/shop" // evidence pin — the repo `sources:` is checked againstcommit: "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0" // required whenever `repo:` is set
dependencies { acme.shared: "../shared"}
use database, frontend from arch.backend // explicit, pick-and-choose (never use *)use relational_db as managed_db from acme.shared // local renameexport use payments_provider from acme.payments // re-exportВложенный манифест пространства несёт name: вместо package::
name: acme.shop.loans // a space within the packageСм. гл. 12.
Привязки к исходному коду — обычное поле, называющее код, который свидетельствует о модуле; проверяется по закреплению repo:/commit: пакета:
module Checkout { sources: "src/checkout/index.ts:12-88", "src/tax.ts:5-40", "src/whole-file.ts"}// entries are repo-root-relative; ranges are 1-based and INCLUSIVE.// verdicts: verified | broken | unverified — `unverified` is never a pass and draws no badge.См. гл. 37.
Стабильные идентификаторы
Заголовок раздела «Стабильные идентификаторы»Идентификаторы бессмысленны и постоянны — случайные, никогда не кодируют домен, никогда не меняются (пусть их выдаёт инструментарий).
service #q8m3 Payments { ... } // module IDtype #b9k1 module service { ... } // type IDprocess #x4t7 Checkout { ... } // process IDview #h2w5 Landscape { ... } // view ID// Surfaces and interfaces do NOT carry IDs.См. гл. 13.
Декларации типов
Заголовок раздела «Декларации типов»Простые модули/интерфейсы — вариант по умолчанию; определяйте пользовательский тип только тогда, когда нужно ввести подтип, прикрепить виджеты, добавить пользовательские поля/требования или утвердить тип.
type module service { required cascade version // mandatory cascading blank field required aspect domain // mandatory blank aspect component metrics { rest_create emit } // pre-filled sub-declaration required database PrimaryStore // mandatory blank sub-declaration cascade widget: arch-service // default cascading field append base // append-mode field (path/list/object compose)}
type service paymentsService { version: "2.1" } // subtypeexport type service internal_service { ... } // visible to importersОбязательные пустые слоты
Заголовок раздела «Обязательные пустые слоты»// Two and only two ways to address an inherited `required` blank:field: value // fulfilldrop field // remove entirelyСм. гл. 17.
Режимы распространения (задаются на типе)
Заголовок раздела «Режимы распространения (задаются на типе)»| Модификатор | Поведение |
|---|---|
| (нет) — локально | Остаётся там, где задано, не растекается |
cascade | Растекается к потомкам; переопределение на ходу |
cascade * | Объявляет корень каскад-группы — подполя под этим путём участвуют в той же группе; замена корня сбрасывает группу; переопределение листа его сохраняет |
append | Растекается и композируется (пути конкатенируются, списки добавляются, объекты сливаются) |
Каскад-группы позволяют связать родственные подполя (например, widget, widget.icon, widget.color) так, что замена корневого тега автоматически очищает унаследованные подполя — без церемонии drop для каждого листа:
type module service { cascade * widget: arch-module { icon: service color: info }}type service custom { widget: my-element // drops icon, color}type service tweaked { widget.color: green // keeps icon}Аспекты всегда каскадируют с семантикой переопределения; модификатор на аспектах не нужен (и не разрешён). См. гл. 18.
Уточнение / override / drop (единообразно на уровне типа и экземпляра)
Заголовок раздела «Уточнение / override / drop (единообразно на уровне типа и экземпляра)»// Refine — same type or subtype, merges:component metrics { rest_create emitV2 }
// Override — switch to non-subtype type, requires keyword:override database metrics { db_read read }
// Drop — remove entirely:drop metricsdrop metrics.emit // remove a childНабор операций против унаследованного required пустого слота:
| Цель | Синтаксис |
|---|---|
| Уточнить до типа-подтипа, слот пустой | required <subtype> Name |
| Уточнить до типа-подтипа, заполнить | <subtype> Name { ... } |
| Переключить на тип не-подтип, слот пустой | override required <new-type> Name |
| Переключить на тип не-подтип, заполнить | override <new-type> Name { ... } |
| Заполнить, сохраняя унаследованный тип | Name: value или Name { ... } |
| Удалить полностью | drop Name |
См. гл. 19.
Виджеты
Заголовок раздела «Виджеты»widget: arch-service // custom-element formwidget.icon: server // widget propwidget.accent: accent
widget: "<div class='card'>{{name}}</div>" // inline template formwidget: """<archui-card>{{name}}</archui-card>""" // triple-quoted, rawСм. гл. 20.
archlang validate <path> # validate; exit non-zero on errorsarchlang validate --watch <path>archlang validate --complete <path> # fail (exit 3) if any TODO remainsarchlang info <path> # summarize a packagearchlang check <path> # validate + policy-check + format --check + evidencearchlang check <path> --against=main # + change-gate dry run vs a git refarchlang format <file.arch> # canonical formatting (whitespace, indent, ID minting)archlang format --check # exit non-zero if format would change anythingarchlang format --diff # print what would changearchlang set <path> <target> <field> <value> [--aspect] # headless field/aspect writearchlang set <path> <target> <text> --description # headless description writearchlang policy-check <path> # evaluate policies; error/warning/advisory findingsarchlang evidence <path> [--repo=<path>] # check `sources:` bindings; exit 1 only on BROKENarchlang export json <path> [-o <file>] # dump the resolved model as JSONarchlang export html <path> -o <file> # one self-contained HTML file, opens offlinearchlang render <path> --out=<f.svg|f.png> [--view=board|bpmn|flow|sequence] [--process=<name>] # headless diagram export (PNG via bundled resvg)archlang serve <path> [--port=<n>] [--web-root=<path>] # HTTP API + optional web UIarchlang lsp # language server on stdioarchlang conform <path> --source=jaeger|tempo --endpoint=<url> # check telemetry vs the modelСм. гл. 21.
Встраивание просмотрщика
Заголовок раздела «Встраивание просмотрщика»<archlang-viewer src="./diagram.arch" style="width: 100%; height: 480px"></archlang-viewer>Размеры задаются через CSS (style, class); элемент не принимает атрибуты width/height. См. гл. 23.
Напоминание о раскладке файлов
Заголовок раздела «Напоминание о раскладке файлов»my-project/├── package.archspace # manifest (required for non-anonymous package)├── widgets.js # custom-element registrations (optional)├── types.arch # type declarations├── orders.arch # instance declarations└── packages/shared/ # nested package (its own boundary) ├── package.archspace └── ...