1. Введение
Эта статья о Structurizr, инструменте, обеспечивающем программный подход к архитектурным определениям и визуализациям на основе модели C4 .
Structurizr отказывается от традиционных подходов перетаскивания в редакторах архитектурных диаграмм, таких как UML, и позволяет нам описывать наши архитектурные артефакты с помощью инструмента, который мы знаем лучше всего: Java.
2. Начало работы
Для начала добавим зависимость structurizr-core в наш pom.xml:
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-core</artifactId>
<version>1.0.0</version>
</dependency>
3. Системы
Приступим к моделированию образца архитектуры. Предположим, мы создаем платежный терминал с функцией обнаружения мошенничества, используемый продавцами для проведения платежей.
Во-первых, нам нужно создать рабочее пространство
и модель
:
Workspace workspace = new Workspace("Payment Gateway", "Payment Gateway");
Model model = workspace.getModel();
Мы также определяем пользователя и две программные системы в рамках этой модели:
Person user = model.addPerson("Merchant", "Merchant");
SoftwareSystem paymentTerminal = model.addSoftwareSystem(
"Payment Terminal", "Payment Terminal");
user.uses(paymentTerminal, "Makes payment");
SoftwareSystem fraudDetector = model.addSoftwareSystem(
"Fraud Detector", "Fraud Detector");
paymentTerminal.uses(fraudDetector, "Obtains fraud score");
Теперь, когда наша система определена, мы можем создать представление:
ViewSet viewSet = workspace.getViews();
SystemContextView contextView = viewSet.createSystemContextView(
paymentTerminal, "context", "Payment Gateway Diagram");
contextView.addAllSoftwareSystems();
contextView.addAllPeople();
Здесь мы создали представление, включающее все программные системы и людей. Теперь необходимо визуализировать представление.
4. Просмотр через PlantUML
В предыдущем разделе мы создали представление простого платежного шлюза.
Следующим шагом является создание удобной для человека диаграммы. Вероятно, самым простым решением для организации, уже использующей PlantUML , будет указание Structurizr выполнить экспорт PlantUML:
StringWriter stringWriter = new StringWriter();
PlantUMLWriter plantUMLWriter = new PlantUMLWriter();
plantUMLWriter.write(workspace, stringWriter);
System.out.println(stringWriter.toString());
Здесь результирующая разметка выводится на экран, но ее также легко можно отправить в файл. Визуализация данных таким образом дает диаграмму ниже:
5. Просмотр через сайт Structurizr
Существует еще один вариант рендеринга диаграмм. Архитектурный вид можно отправить на веб-сайт Structurizr через клиентский API. Затем диаграмма будет сгенерирована с использованием их богатого пользовательского интерфейса.
Давайте создадим клиент API:
StructurizrClient client = new StructurizrClient("key", "secret");
Ключевые и секретные параметры получены из панели управления рабочей области на их веб-сайте. Затем на рабочую область можно ссылаться:
client.putWorkspace(1337, workspace);
Очевидно, нам нужно зарегистрироваться на сайте и создать рабочее пространство. Базовая учетная запись с одной рабочей областью бесплатна. В то же время доступны и коммерческие планы.
6. Контейнеры
Давайте расширим нашу программную систему, добавив несколько контейнеров. В модели C4 контейнерами могут быть веб-приложения, мобильные приложения, настольные приложения, базы данных и файловые системы: почти все, что содержит код и/или данные.
Во-первых, мы создаем несколько контейнеров для нашего платежного терминала:
Container f5 = paymentTerminal.addContainer(
"Payment Load Balancer", "Payment Load Balancer", "F5");
Container jvm1 = paymentTerminal.addContainer(
"JVM-1", "JVM-1", "Java Virtual Machine");
Container jvm2 = paymentTerminal.addContainer(
"JVM-2", "JVM-2", "Java Virtual Machine");
Container jvm3 = paymentTerminal.addContainer(
"JVM-3", "JVM-3", "Java Virtual Machine");
Container oracle = paymentTerminal.addContainer(
"oracleDB", "Oracle Database", "RDBMS");
Затем мы определяем отношения между этими вновь созданными элементами:
f5.uses(jvm1, "route");
f5.uses(jvm2, "route");
f5.uses(jvm3, "route");
jvm1.uses(oracle, "storage");
jvm2.uses(oracle, "storage");
jvm3.uses(oracle, "storage");
Наконец, создайте представление контейнера, которое можно передать средству визуализации:
ContainerView view = workspace.getViews()
.createContainerView(paymentTerminal, "F5", "Container View");
view.addAllContainers();
Визуализация полученной диаграммы с помощью PlantUML дает:
7. Компоненты
Следующий уровень детализации в модели C4 обеспечивается представлением компонента. Его создание похоже на то, что мы делали раньше.
Во-первых, мы создаем некоторые компоненты в контейнере:
Component jaxrs = jvm1.addComponent("jaxrs-jersey",
"restful webservice implementation", "rest");
Component gemfire = jvm1.addComponent("gemfire",
"Clustered Cache Gemfire", "cache");
Component hibernate = jvm1.addComponent("hibernate",
"Data Access Layer", "jpa");
Далее, давайте добавим некоторые отношения:
jaxrs.uses(gemfire, "");
gemfire.uses(hibernate, "");
Наконец, давайте создадим представление:
ComponentView componentView = workspace.getViews()
.createComponentView(jvm1, JVM_COMPOSITION, "JVM Components");
componentView.addAllComponents();
Представление полученной диаграммы через PlantUML приводит к:
8. Извлечение компонентов
Для существующих баз кода, использующих среду Spring, Structurizr предоставляет автоматизированный способ извлечения компонентов с аннотациями Spring и добавления их к архитектурным артефактам.
Чтобы использовать эту функцию, нам нужно добавить еще одну зависимость:
<dependency>
<groupId>com.structurizr</groupId>
<artifactId>structurizr-spring</artifactId>
<version>1.0.0-RC5</version>
</dependency>
Далее нам нужно создать ComponentFinder
, настроенный на одну или несколько стратегий разрешения. Стратегии разрешения влияют на такие вещи, как то, какие компоненты будут добавлены в модель, глубину обхода дерева зависимостей и т. д.
Мы даже можем подключить собственные стратегии разрешения:
ComponentFinder componentFinder = new ComponentFinder(
jvm, "com.foreach.structurizr",
new SpringComponentFinderStrategy(
new ReferencedTypesSupportingTypesStrategy()
),
new SourceCodeComponentFinderStrategy(new File("/path/to/base"), 150));
Наконец, мы запускаем искатель:
componentFinder.findComponents();
Приведенный выше код сканирует пакет com.foreach.structurizr
на наличие bean-компонентов с аннотациями Spring и добавляет их в качестве компонентов в контейнер JVM. Излишне говорить, что мы можем реализовать свои собственные сканеры, аннотированные ресурсы JAX-RS и даже связыватели Google Guice.
Пример простой диаграммы из типового проекта воспроизводится ниже:
9. Заключение
В этом кратком руководстве рассматриваются основы проекта Structurizr for Java.
И, как всегда, пример кода можно найти на GitHub .