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

11. Стандартная библиотека

До сих пор мы использовали только базовый язык: module, facet, interface. Три ключевых слова. Каждый пример был помеченной рамкой с операциями и стрелками.

Этого достаточно, чтобы смоделировать что угодно структурно, но не хватает двух вещей, которые нужны реальным проектам:

  • Визуальное различие. База данных, микросервис, пользователь и внешний поставщик должны выглядеть на диаграмме по-разному. Только с module они так не выглядят.
  • Принудительные соглашения. Каждый микросервис в этой организации имеет команду-владельца. Базовый вид module ничего не принуждает; валидатор не отличит сервис от внешнего клиента.

Стандартная библиотека решает обе задачи. Она поставляет два пакета видов — arch.modules и arch.kinds, — которые вводят семантические подтипы базовых видов. Каждый каскадирует виджет по умолчанию и (как правило) требует несколько полей.

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

Подключение стандартной библиотеки

Добавьте две строки в package.archspace:

name: my-project
use * from arch.modules
use * from arch.kinds

arch.modules добавляет подтипы модулей (service, database, actor, …). arch.kinds добавляет подтипы интерфейсов (command, query, event, …). Оба пакета автоматически разрешаются через встроенную в инструментарий стандартную библиотеку — запись в dependencies не нужна.

Теперь ваши файлы .arch могут использовать более выразительные виды:

service Payments {
team: Payments
labels { domain: Payments }
command Authorize
event PaymentEvents
}

Импортируемые виды — это подтипы module и interface. Все правила из глав 4 и 5 применимы — поверх просто добавляются значения по умолчанию и требования.

Виды модулей (arch.modules)

Из коробки поставляется семь видов.

ВидОбязательные поляЗначения по умолчаниюВиджет по умолчанию
servicerequired cascade team, required labels.domainarch-service
frontendrequired cascade team, required labels.domainarch-frontend
databaserequired cascade team, required labels.data.classificationarch-database
componentcascade team (по умолчанию пусто)arch-component
systemcascade teamarch-system
external_systemrequired ext.vendor, required ext.contract.urlarch-external-system
actorarch-actor

Столбцы:

  • Обязательные поля должны быть заполнены или сброшены в каждом экземпляре. Их отсутствие — ошибка разбора.
  • Значения по умолчанию — предустановленные поля, которые наследует экземпляр; каскад распространяет их на вложенные модули.
  • Виджет по умолчанию — тег пользовательского элемента, который монтирует средство рендеринга. У каждого вида своя визуальная идентичность.

use * from arch.modules сразу даёт рабочую визуализацию; собственный скрипт виджетов не требуется. (Глава 20 посвящена настройке виджетов.)

Когда что использовать:

  • service — серверный сервис с поддерживающей командой.
  • frontend — приложение для пользователя (веб, мобильное).
  • database — хранилище данных.
  • component — более мелкая часть внутри другого модуля. Часто вложенная.
  • system — контейнер, группирующий другие модули (подсистема или продуктовая область).
  • external_system — поставщик или партнёр, который вам не принадлежит. ext.vendor и ext.contract.url обязательны, чтобы внешние зависимости всегда документировали, что они такое и где их контракт.
  • actor — человек или внешний клиент, инициирующий вызовы. Акторы не предоставляют операций; они их вызывают.

Используйте базовый вид module, когда ни один из этих не подходит — обычно редко. Если хочется «почти service, но ещё с тремя обязательными полями», определите подтип в рамках проекта (Глава 16).

Виды интерфейсов (arch.kinds)

Поставляется шесть видов.

ВидРодительСемантика
syncinterfaceУниверсальный синхронный интерфейс
asyncinterfaceУниверсальный асинхронный интерфейс
commandsyncОперация, изменяющая состояние
querysyncОперация только для чтения
eventasyncPub/sub-вещание
streamasyncДолгоживущий поток данных

Два родительских вида (sync, async) задают оформление рёбер: синхронные сплошные, асинхронные пунктирные. Четыре дочерних вида (command, query, event, stream) наследуют это оформление и передают конкретную семантику.

Только event и stream (или что-либо, наследующее их) — осмысленные цели для связи через subscribes:. Валидатор отклоняет subscribes: someCommand.

Базовый язык против стандартной библиотеки: одна и та же модель

Одна и та же архитектура, записанная двумя способами:

Базовая запись:

module Payments {
team: Payments
interface Authorize
interface OrderEvents
}
module Shipping {
team: Fulfillment
interface CreateShipment {
subscribes: Payments.OrderEvents
}
}

С использованием стандартной библиотеки:

service Payments {
team: Payments
labels { domain: Payments }
command Authorize
event OrderEvents
}
service Shipping {
team: Fulfillment
labels { domain: Fulfillment }
command CreateShipment {
subscribes: Payments.OrderEvents
}
}

Структура идентична — два модуля, три интерфейса, одна связь подписки. Версия со стандартной библиотекой добавляет:

  • Виджеты service (конкретная визуальная идентичность).
  • Виды интерфейсов command / event (оформление рёбер sync против async).
  • Метку domain (теперь обязательную, потому что её требует тип).

Базовая версия валидна; версия со стандартной библиотекой — то, что реально поставляют в проектах. Перевод механический.

Когда НЕ стоит использовать стандартную библиотеку

Несколько сценариев, где базовые виды имеют смысл:

  • Изучение языка. В главах 2–10 использовались базовые виды именно поэтому — меньше движущихся частей.
  • Маленькие черновые проекты без манифеста. Анонимные пакеты не могут ничего импортировать через use, поэтому базовые виды — всё, что доступно.
  • Создание собственного инструментария. Если вы встраиваете Archlang в систему, которая уже определяет собственную онтологию, может быть желательно полностью обойти словарь стандартной библиотеки.

Большинство проектов используют стандартную библиотеку.

Что дальше

Глава 12: Пакеты → — подробно о манифесте: зависимости, версия, экспорт типов.