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

2. Ваша первая архитектура

Эта глава ведёт через построение полной (маленькой) архитектуры из пустого каталога. К концу у вас будет три модуля, один процесс, связывающий их, диаграмма и ощущение формы языка.

Мы будем использовать только базовый язык — базовые виды module, facet, interface плюс конструкции верхнего уровня process и view — без стандартной библиотеки. Дальнейшие главы вводят более богатые виды (service, command, event); Глава 11 подробно их разбирает. Старт с базовым языком держит фокус на том, что делает сам язык, отдельно от соглашений.

Смоделируем платёжный домен: клиент платит, платёжный сервис авторизует, реестр записывает. И больше ничего.

Пакет

Каждый проект начинается с манифеста. Создайте package.archspace:

name: shop

Одна строка. Имя идентифицирует пакет; стандартную библиотеку пока не импортируем, потому что используем только базовые виды.

Глава 12 подробно разбирает манифест. Пока хватит этого.

Три модуля

Добавьте payments.arch в тот же каталог:

module Payments {
team: Platform
"Авторизует и проводит карточные платежи."
interface Authorize
interface Capture
interface Refund
}
module Ledger {
team: Finance
"Неизменяемая финансовая запись каждой транзакции."
interface Record
}
module Customer {
"Человек, инициирующий платёж."
}

Вы объявили три модуля базовым видом module. У каждого есть:

  • Вид (module) — базовый вид языка.
  • Имя (Payments, Ledger, Customer) — как остальная часть модели на него ссылается.
  • Поле team — кто им владеет (необязательно; базовый вид не требует).
  • Описание — простой строковый литерал. Обычный markdown плюс два расширения, с которыми вы познакомитесь в Главе 10.
  • Ноль или больше интерфейсовinterface Authorize и т. д. Это то, что другие модули могут попросить этот сделать.

У Customer интерфейсов нет. Это нормально — не каждый модуль выставляет операции наружу. (Виды стандартной библиотеки добавляют семантические различия вроде actor для сущностей, которые только инициируют вызовы; пока всё — просто module.)

Попробуйте вживую — отредактируйте исходник выше, диаграмма обновится ниже. Наводитесь на идентификаторы, жмите F2 для переименования, Ctrl/⌘ Space для автодополнения:

Loading editor…

Сохраните файл и запустите:

Окно терминала
archlang validate .

Ошибок быть не должно. Откройте каталог в редакторе (с установленным расширением Archlang) и вызовите панель встроенного предпросмотра — появятся три коробки, пока ни с чем не связанные. Это ожидаемо — мы не сказали, как они взаимодействуют.

Диаграмма выглядит просто, потому что у базового вида module нет специализированного отображения. Коробки подписаны именами; один общий виджет для всех трёх. Стандартная библиотека вводит виджеты под каждый вид (Глава 11); в этой главе суть в простых коробках — они делают лежащую под ними структуру очевидной.

Процесс

Добавьте checkout.arch:

process Checkout {
Customer > Payments.Authorize
Payments > Ledger.Record
Customer > Payments.Capture
Payments > Ledger.Record
}

Процесс — последовательность шагов. Каждый шаг имеет форму Вызывающий > Принимающий.Интерфейс:

  • Вызывающий (слева от >) — модуль, делающий вызов.
  • Принимающий (справа от >) — интерфейс, конкретная вызываемая операция.

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

Сдвиг мышления. В большинстве инструментов диаграмм вы рисуете стрелку, потому что два сервиса общаются. В Archlang вы объявляете шаг процесса; стрелка появляется, потому что что-то объявило, что общается. Удалите шаг — стрелка исчезнет. Добавьте ещё шаг — появится новая стрелка. Граф зависимостей — всегда функция поведения.

Изменение

Откройте payments.arch и добавьте четвёртый интерфейс:

module Payments {
team: Platform
"Авторизует и проводит карточные платежи."
interface Authorize
interface Capture
interface Refund
interface Void // новый
}

Сохраните. Предпросмотр обновится. Void появляется в узле Payments; стрелок к нему нет, потому что ни один процесс пока его не вызывает.

Теперь откройте checkout.arch и добавьте шаг:

process Checkout {
Customer > Payments.Authorize
Payments > Ledger.Record
Customer > Payments.Capture
Payments > Ledger.Record
Customer > Payments.Void // новый — клиент отменяет посреди оплаты
}

Сохраните. Предпросмотр снова обновится. К Void теперь идёт стрелка.

Вы добавили интерфейс и шаг процесса в две правки, и диаграмма последовала за вами. Не надо переделывать схему, не надо двигать коробки.

Что вы построили

shop/
├── package.archspace
├── payments.arch
└── checkout.arch

Три файла, три модуля, один процесс. Полная (хоть и минимальная) архитектура, написанная на чистом базовом языке. Каждая диаграмма, каждая стрелка зависимости, каждый анализ влияния, который Archlang может для вас сделать, выводится из этих файлов.

Сводка

  • Рабочее пространство начинается с манифеста package.archspace, называющего пакет.
  • Базовых видов module и interface хватает для моделирования структуры и выставленных наружу операций.
  • Процессы — последовательности шагов Вызывающий > Принимающий.Интерфейс. Стрелки в диаграммах выводятся из процессов — они не рисуются напрямую.
  • Предпросмотр редактора перерендеривается на сохранение. Цикл разработки: править файл → видеть диаграмму.

Что дальше

Глава 3: Чтение диффа → — внести изменение в архитектуру и посмотреть, как Archlang показывает, что изменилось.