[Перевод] Structurizr, описание, перевод (часть 3/3)

Введение

В данной статье содержится вольный перевод документации по Structurizr.

Из-за большого объема информация разделена на три статьи:

Amazon Web Services

Представление развертывания можно использовать для моделирования развертывания вашей программной системы в Amazon Web Services.

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application" "" "Spring Boot"
            database = container "Database" "" "Relational database schema"
        }

        u -> webapp "Uses"
        webapp -> database "Reads from and writes to"
        
        live = deploymentEnvironment "Live" {
            deploymentNode "Amazon Web Services" {
                deploymentNode "US-East-1" {
                    route53 = infrastructureNode "Route 53"
                    elb = infrastructureNode "Elastic Load Balancer"

                    deploymentNode "Amazon EC2" {
                        deploymentNode "Ubuntu Server" {
                            webApplicationInstance = containerInstance webapp
                        }
                    }

                    deploymentNode "Amazon RDS" {
                        deploymentNode "MySQL" {
                            containerInstance database
                        }
                    }
                }
            }
            
            route53 -> elb "Forwards requests to" "HTTPS"
            elb -> webApplicationInstance "Forwards requests to" "HTTPS"
        }
    }

    views {
        deployment s live {
            include *
            autoLayout lr
        }
    }
    
}

Этот код определяет среду развертывания с именем Live, с иерархией узлов развертывания, показывающих различные сервисы AWS, используемые для развертывания. Он также определяет некоторые узлы инфраструктуры, представляющие службы, на которых не развернуты какие-либо программные системы/контейнеры.

7a558bebcfc1e48fcc27a5d7e8ce3492.png

Для добавления цвета можно использовать готовую тему Amazon Web Services, а также набор значков AWS.

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application" "" "Spring Boot"
            database = container "Database" "" "Relational database schema"
        }

        u -> webapp "Uses"
        webapp -> database "Reads from and writes to"
        
        live = deploymentEnvironment "Live" {
            deploymentNode "Amazon Web Services" {
                tags "Amazon Web Services - Cloud"
                
                deploymentNode "US-East-1" {
                    tags "Amazon Web Services - Region"
                
                    route53 = infrastructureNode "Route 53" {
                        tags "Amazon Web Services - Route 53"
                    }
                    elb = infrastructureNode "Elastic Load Balancer" {
                        tags "Amazon Web Services - Elastic Load Balancing"
                    }

                    deploymentNode "Amazon EC2" {
                        tags "Amazon Web Services - EC2"
                        
                        deploymentNode "Ubuntu Server" {
                            webApplicationInstance = containerInstance webapp
                        }
                    }

                    deploymentNode "Amazon RDS" {
                        tags "Amazon Web Services - RDS"
                        
                        deploymentNode "MySQL" {
                            tags "Amazon Web Services - RDS MySQL instance"
                            
                            containerInstance database
                        }
                    }
                }
            }
            
            route53 -> elb "Forwards requests to" "HTTPS"
            elb -> webApplicationInstance "Forwards requests to" "HTTPS"
        }
    }

    views {
        deployment s live {
            include *
            autoLayout lr
        }

        theme https://static.structurizr.com/themes/amazon-web-services-2020.04.30/theme.json
    }
    
}

Этот DSL добавляет некоторые теги элементов и ссылку на тему Amazon Web Services.

a54050f8ed65863dd666cd705c7dce5a.png

При желании также могут быть добавлены дополнительные стили.

2d9b84b72e293ffe671735ae80bf81d7.png

Component view

Представление компонентов позволяет увеличить масштаб контейнера, чтобы увидеть компоненты, которые находятся внутри него.

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application" {
                c1 = component "Component 1"    
                c2 = component "Component 2"    
            }
            database = container "Database"
        }

        u -> c1 "Uses"
        c1 -> c2 "Uses"
        c2 -> database "Reads from and writes to"
    }

    views {
        component webapp {
            include *
            autoLayout lr
        }
    }
    
}

Этот код определяет представление компонента для контейнера webapp, а include * включает набор элементов модели по умолчанию для представления.

2cd896a0a215aec1ec968efceb95725c.png

Container view

Представление контейнера позволяет увеличить масштаб программной системы, чтобы увидеть приложения и хранилища данных (то, что модель C4 называет «контейнерами»), которые находятся внутри нее.

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application"
            database = container "Database"
        }

        u -> webapp "Uses"
        webapp -> database "Reads from and writes to"
    }

    views {
        container s {
            include *
            autoLayout lr
        }
    }
    
}

Этот DSL определяет представление контейнера для программной системы s, а include * включает набор элементов модели по умолчанию для представления.

fa260c1d07a77d3c5b766f117cf1131d.png

Container view (для нескольких систем)

По умолчанию ключевое слово **include ***, используемое внутри определения представления контейнера, будет включать все контейнеры внутри программной системы в области видимости вместе с любыми зависимостями от внешней программной системы. Например, следующий код сгенерирует приведенную ниже диаграмму.

workspace {

    model {
        s1 = softwareSystem "Software System 1" {
            c1 = container "Container 1"
        }

        s2 = softwareSystem "Software System 2" {
            c2 = container "Container 2"
        }
        
        c1 -> c2
    }

    views {
        container s1 {
            include *
            autoLayout lr
        }
    }
    
}

32251858edd7dee85d88115830cd286a.png

Хотя этого достаточно для большинства целей, могут возникнуть ситуации, когда необходимо показать зависимость между двумя контейнерами, каждый из которых находится в отдельной программной системе. Чтобы сделать это, нужно изменить инструкцию include, как показано в примере ниже.

workspace {

    model {
        s1 = softwareSystem "Software System 1" {
            c1 = container "Container 1"
        }

        s2 = softwareSystem "Software System 2" {
            c2 = container "Container 2"
        }
        
        c1 -> c2
    }

    views {
        container s1 {
            include c1 c2
            autoLayout lr
        }
    }

}

8d09e2cf443d741507e89a9182e353ce.png

Чтобы не указывать каждый контейнер по отдельности, можно использовать выражение и заменить оператор include одним из следующих:

DSL и код

Можно использовать как DSL, так и библиотеку на основе кода вместе. Например, определить базовую модель с помощью DSL и использовать автоматическое извлечение для добавления компонентов в модель. Для этого нужно определить рабочее пространство, используя DSL:

workspace {

    model {
        s = softwareSystem "Software System" {
            webapp = container "Web Application"
            database = container "Database" {
                webapp -> this "Reads from and writes to"
            }
        }
    }

    views {
        container s {
            include *
            autoLayout lr
        }
    }
    
}

Java

Поскольку синтаксический анализатор DSL написан на Java, его можно использовать напрямую, добавив зависимость от библиотеки structurizr-dsl, которая доступна в Maven Central:

Пример Java-программы, которая анализирует определение DSL и расширяет рабочее пространство:

StructurizrDslParser parser = new StructurizrDslParser();
parser.parse(new File("workspace.dsl"));

Workspace workspace = parser.getWorkspace();
Container webApplication = workspace.getModel().getSoftwareSystemWithName("Software System").getContainerWithName("Web Application");

// add components manually or via automatic extraction
...

// add a component view
ComponentView componentView = workspace.getViews().createComponentView(webApplication, "Components", "Description");
componentView.addDefaultElements();
componentView.enableAutomaticLayout();

Java-библиотека Structurizr предназначена только для добавления данных. Невозможно удалить/изменить элементы/связи, которые уже существуют в модели.

Другие ЯП

Порты библиотеки «Structurizr для Java» доступны для ряда других языков программирования. В этом случае нельзя использовать синтаксический анализатор DSL напрямую, но можно добиться того же эффекта, выполнив следующие действия:

  1. Преобразовать рабочее пространство DSL в формат JSON. Это можно сделать с помощью команды экспорта Structurizer CLI.

structurizr export -workspace workspace.dsl -format json
  1. Загрузите файл JSON и добавьте в рабочую область. Пример Structurizr для .NET платформы:

FileInfo fileInfo = new FileInfo("workspace.json");
Workspace workspace = WorkspaceUtils.LoadWorkspaceFromJson(fileInfo);
Container webApplication = workspace.Model.GetSoftwareSystemWithName("Software System").GetContainerWithName("Web Application");

// add components manually or via automatic extraction
...

// add a component view
ComponentView componentView = workspace.Views.CreateComponentView(webApplication, "Components", "Description");
componentView.AddDefaultElements();
componentView.EnableAutomaticLayout();

Deployment groups

Допустим, есть сервис, состоящий из API и базы данных, которые развернуты вместе на одном сервере. Причем существуют два экземпляра этой службы, каждый из которых развернут на отдельном сервере.

workspace {

    model {
        softwareSystem = softwareSystem "Software System" {
            database = container "Database Schema"
            api = container "Service API" {
                -> database "Uses"
            }
        }

        production = deploymentEnvironment "Production" {
            deploymentNode "Server 1" {
                containerInstance api
                deploymentNode "Database Server" {
                    containerInstance database
                }
            }
            deploymentNode "Server 2" {
                containerInstance api
                deploymentNode "Database Server" {
                    containerInstance database
                }
            }
        }
    }

    views {
        deployment * production {
            include *
            autolayout
        }
    }

}

Отношения экземпляров контейнера основаны на отношениях контейнеров, определенных в статической структурной части модели. Хотя во многих случаях это работает «из коробки», здесь «Service API» на «Server 1» имеет подключение к «Database Schema» на «Server 2», и наоборот.

0f33fa33efa73c4b301637bdd038fe42.png

Если это нежелательное поведение, можно использовать функцию «deployment group», которая предоставляет способ группировать экземпляры программной системы/контейнера и ограничивать способ создания связей между ними. Например, можно создать две группы развертывания и поместить по одному экземпляру как «Service API», так и «Database Schema» в каждую.

workspace {

    model {
        softwareSystem = softwareSystem "Software System" {
            database = container "Database Schema"
            api = container "Service API" {
                -> database "Uses"
            }
        }

        production = deploymentEnvironment "Production" {
            serviceInstance1 = deploymentGroup "Service instance 1"
            serviceInstance2 = deploymentGroup "Service instance 2"

            deploymentNode "Server 1" {
                containerInstance api serviceInstance1
                deploymentNode "Database Server" {
                    containerInstance database serviceInstance1
                }
            }
            deploymentNode "Server 2" {
                containerInstance api serviceInstance2
                deploymentNode "Database Server" {
                    containerInstance database serviceInstance2
                }
            }
        }
    }

    views {
        deployment * production {
            include *
            autolayout
        }
    }

}

1c0b87f971d0c252be1241fd233696b6.png

Deployment view

Представление развертывания позволяет показать, как развертываются программные системы и контейнеры, путем отображения отображения экземпляров программной системы и контейнера на узлах развертывания.

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application" "" "Spring Boot"
            database = container "Database" "" "Relational database schema"
        }

        u -> webapp "Uses"
        webapp -> database "Reads from and writes to"
        
        development = deploymentEnvironment "Development" {
            deploymentNode "Developer Laptop" {
                containerInstance webapp
                deploymentNode "MySQL" {
                    containerInstance database
                }
            }
        }
    }

    views {
        deployment * development {
            include *
            autoLayout lr
        }
    }
    
}

Этот DSL определяет среду развертывания с именем Development, с экземплярами webapp и контейнерами базы данных, развернутыми на некоторых узлах развертывания. Он также определяет представление развертывания для этой среды развертывания, и include * включает набор элементов модели по умолчанию для представления.

dd07cc7c6f01814935bb867703e9c615.png

Представления развертывания могут быть отрисованы с помощью облачной службы Structurizr/локальной установки или экспортированы в ряд других форматов с помощью команды экспорта CLI Structurizr.

Dynamic view

Динамическое представление позволяет показать подмножество элементов модели и взаимосвязи между ними, чтобы описать, как работает конкретный вариант использования/история/функция. Динамические представления отображают упорядоченные экземпляры связей, что сокращает количество связей, которые необходимо определить в статической модели.

workspace {

    model {
        customer = person "Customer"
        onlineBookStore = softwareSystem "Online book store" {
            webapp = container "Web Application"
            database = container "Database"
        }

        customer -> webapp "Browses and makes purchases using"
        webapp -> database "Reads from and writes to"
    }

    views {
        container onlineBookStore {
            include *
            autoLayout lr
        }
        
        dynamic onlineBookStore {
            title "Request past orders feature"
            customer -> webapp "Requests past orders from"
            webapp -> database "Queries for orders using"
            autoLayout lr
        }
        
        dynamic onlineBookStore {
            title "Browse top 20 books feature"
            customer -> webapp "Requests the top 20 books from"
            webapp -> database "Queries the top 20 books using"
            autoLayout lr
        }
    }
    
}

Этот DSL определяет три вида:

  1. Представление контейнера, показывающее пользователя и контейнеры — отношения между пользователем и веб-приложением довольно общие («Просматривает и совершает покупки с помощью»).

  2. Динамический просмотр для функции «запросить прошлые заказы».

  3. Динамический просмотр для функции «просмотреть 20 лучших книг».

2e6096053ce500963d726137d073f4f7.png

Dynamic view с параллельными последовательностями

Динамические представления также могут использоваться для отображения параллельных последовательностей взаимодействий, чтобы указать на некоторую степень параллелизма. В таких случаях можно использовать синтаксис блока DSL { и } для определения параллельных последовательностей.

workspace {

    model {
        a = softwareSystem "A"
        b = softwareSystem "B"
        c = softwareSystem "C"
        d = softwareSystem "D"
        e = softwareSystem "E"

        a -> b
        b -> c
        b -> d
        b -> e
    }

    views {

        dynamic * {
            a -> b "Makes a request to"
            {
                {
                    b -> c "Gets data from"
                }
                {
                    b -> d "Gets data from"
                }
            }
            b -> e "Sends data to"

            autoLayout
        }
    }

}

3aa62e77ad063477b72d2344a2327cb8.png

Поддержка параллельных последовательностей через DSL относительно ограничена.

Стили элементов

По умолчанию все элементы оформлены в виде серых прямоугольников.

d133a2bbfc01f5358e74267def7781cd.png

Стилизация всех элементов

Стиль всех элементов можно изменить, добавив стиль для тега Element:

workspace {

    model {
        a = softwareSystem "A"
        b = softwareSystem "B"
        c = softwareSystem "C"

        a -> b
        b -> c
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
        
        styles {
            element "Element" {
                background #1168bd
                color #ffffff
                shape RoundedBox
            }
        }
    }
    
}

b78250f5e2c909d2afe17b0cc0535529.png

Стилизация отдельных элементов

Чтобы изменить стиль отдельного элемента нужно:

  1. Пометить элемент тегом.

  2. Добавить стиль для этого тега.

workspace {

    model {
        a = softwareSystem "A" {
            tags "Tag 1"
        }
        b = softwareSystem "B"
        c = softwareSystem "C"

        a -> b
        b -> c
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
        
        styles {
            element "Tag 1" {
                background #1168bd
                color #ffffff
                shape RoundedBox
            }
        }
    }
    
}

a816769ed72e7d37bf00e2fa4748ed37.png

Стили элементов предназначены для работы с облачным сервисом Structurizr/локальной установкой и могут не полностью поддерживаться форматами экспорта PlantUML, Mermaid и тому подобными.

Filtered view

Фильтрованное представление представляет собой «представление поверх другого представления», которое может использоваться для фильтрации (включения или исключения) определенных элементов и/или связей на основе их тега.

Рассмотрим следующее определение рабочей области:

workspace {

    model {
        a = softwareSystem "A" {
            tags "Tag 1"
        }
        b = softwareSystem "B" {
            tags "Tag 2"
        }
        c = softwareSystem "C" {
            tags "Tag 3"
        }
        
        a -> b
        b -> c
    }
    
    views {
        systemLandscape "landscape" {
            include *
            autolayout lr
        }
    }
        
}

Этот DSL определяет три программные системы со связями между ними, а также ландшафтный вид, показывающий эти программные системы.

8e5ee037f4bbb846005c27ff1196983d.png

Функция «Фильтрованный вид» может использоваться для определения видов поверх этого ландшафтного вида. Например, следующий DSL определяет два отфильтрованных вида:

workspace {

    model {
        a = softwareSystem "A" {
            tags "Tag 1"
        }
        b = softwareSystem "B" {
            tags "Tag 2"
        }
        c = softwareSystem "C" {
            tags "Tag 3"
        }
        
        a -> b
        b -> c
    }
    
    views {
        systemLandscape "landscape" {
            include *
            autolayout lr
        }
        
        filtered "landscape" include "Tag 1,Tag 2,Relationship" "landscape1"
        filtered "landscape" exclude "Tag 1" "landscape2"
    }
        
}

Первое из этих отфильтрованных представлений включает все элементы/взаимосвязи, помеченные «Tag 1», «Tag 2» или Relationship.

81917efe471962b52e7c718f69dff13b.png

А второй исключает все элементы/отношения, помеченные «Tag 1».

fb06518e302c081e2dd930b772526b91.png

При использовании фильтрованных представлений исходное «базовое представление» больше не отображается в списке доступных для просмотра диаграмм. Это сделано специально. Если требуется увидеть базовое представление, нужно создать другое отфильтрованное представление, показывающее все элементы и взаимосвязи:

filtered "landscape" include "Element,Relationship" "landscape-all"

ba02a0bc93aa4baf72c73e962b55803f.png

Groups

Ключевое слово group предоставляет способ определения именованной группировки элементов, которая будет отображаться как граница вокруг этих элементов.

workspace {

    model {
        group "Company 1" {
            a = softwareSystem "A"
        }
        
        group "Company 2" {
            b = softwareSystem "B"
        }

        a -> b
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
    }
    
}

785fd95c22d64fb8375de71174543884.png

По умолчанию группы отображаются в виде пунктирных границ светло-серого цвета. Чтобы изменить стиль для всех групп, можно добавить стиль элемента для тега Group.

workspace {

    model {
        group "Company 1" {
            a = softwareSystem "A"
        }
        
        group "Company 2" {
            b = softwareSystem "B"
        }

        a -> b
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
        
        styles {
            element "Group" {
                color #ff0000
            }
        }
    }
    
}

59dd40501420edb15166fda09387fb91.png

Чтобы изменить стиль отдельной группы, можно добавить стиль элемента для тега Group: XXX, где XXX — название группы.

workspace {

    model {
        group "Company 1" {
            a = softwareSystem "A"
        }
        
        group "Company 2" {
            b = softwareSystem "B"
        }

        a -> b
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
        
        styles {
            element "Group:Company 1" {
                color #ff0000
            }
        }
    }
    
}

77a096220dc499950c9846b24126bab2.png

Вложенные группы

Группы могут быть вложенными.

Группы элементов определяются как свойство одной строки для элемента с именем group, и для определения вложенных групп требуется разделитель, который будет использоваться для разделения этой отдельной строки на набор иерархических/вложенных групп.

Для этого нужно добавить свойство модели с именем structurizr.group Separator, которое определяет используемый разделитель, и НЕ использовать этот разделитель в именах групп. Для оформления вложенных групп требуется использовать полное имя иерархической группы при определении стиля элемента.

workspace {

    model {
        properties {
            "structurizr.groupSeparator" "/"
        }

        group "Company 1" {
            group "Department 1" {
                a = softwareSystem "A"
            }

            group "Department 2" {
                b = softwareSystem "B"
            }
        }

        a -> b
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
        
        styles {
            element "Group:Company 1/Department 1" {
                color #ff0000
            }
            element "Group:Company 1/Department 2" {
                color #0000ff
            }
        }
    }
    
}

6b72fb84e0fbeee977fb415ddc27deee.png

Image view

Представление изображений — для включения в рабочую область Structurizr изображений, отрисованных вне Structurizr. Изображения могут быть загружены из произвольного файла PNG/SVG или диаграммы PlantUML/Mermaid/Kroki. Примером использования представления изображений является увеличение «уровня 4» диаграммы компонентов.

workspace {

    model {
        softwareSystem "Software System" {
            container = container "Container" {
                component1 = component "Component 1"
            }
        }
    }

    views {
        properties {
            "mermaid.url" "https://mermaid.ink"
            "mermaid.format" "svg"
        }

        component container {
            include *
            autoLayout lr
        }

        image component1 {
            mermaid https://docs.structurizr.com/dsl/cookbook/image-view/component1.mmd
            title "Class diagram for Component1"
        }
    }
    
}

Этот DSL определяет представление изображений для компонента «Component 1» на основе диаграммы классов Mermaid.

933b7eb43e90a48a0d904a9dcfa4a4e7.png

Подразумеваемые связи

По умолчанию Structurizr DSL автоматически создает «подразумеваемые связи». Например, есть DSL, который определяет связь между пользователем и контейнером:

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application"
        }

        u -> webapp "Uses"
    }

    views {
        systemContext s {
            include *
            autoLayout lr
        }
    }
    
}

Хотя DSL не определяет явную взаимосвязь между человеком и программной системой, эта взаимосвязь подразумевается из-за взаимосвязи между человеком и контейнером, который находится внутри программной системы.

90a5f01897c2cbbab832f7fffe821693.png

Отключение подразумеваемых связей

Данная функциональность может быть отключена с помощью ключевого слова ! impliedRelationships. Например:

workspace {

    !impliedRelationships false

    model {

        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application"
        }

        u -> webapp "Uses"
    }

    views {
        systemContext s {
            include u s
            autoLayout
        }
    }
    
}

83c90fff89407f225c8e7c8d822581f8.png

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

Множественные подразумеваемые отношения

При создании подразумеваемых отношений Structurizr DSL использует стратегию из клиентской библиотеки Java, которая предотвращает создание нескольких подразумеваемых отношений. Например, следующий DSL создаст только одну подразумеваемую связь между пользователем и программной системой (первую, которая определена в DSL).

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application"
        }

        u -> webapp "Uses 1"
        u -> webapp "Uses 2"
    }

    views {
        systemContext s {
            include *
            autoLayout lr
        }
    }
    
}

6353951c37c2884dc19946acba544e04.png

Чтобы показать обе взаимосвязи, нужно явно определить их следующим образом:

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System" {
            webapp = container "Web Application"
        }

        u -> s "Uses 1"
        u -> s "Uses 2"
        u -> webapp "Uses 1"
        u -> webapp "Uses 2"
    }

    views {
        systemContext s {
            include *
            autoLayout lr
        }
    }
    
}

2233ca8339289e54d97ff3e70ac28b06.png

Лучшим подходом является сведение нескольких взаимосвязей в единое описание, моделируя сводку всех взаимосвязей, а не каждую отдельную взаимосвязь. Это приводит к уменьшению загроможденности диаграмм.

Перспектива

Structurizr поддерживает концепцию «перспектив», когда требуется взглянуть на диаграмму с целью ответа на конкретный вопрос. Допустим, есть диаграмма системного ландшафта, показывающая программные системы, и нужно увидеть владельца каждой программной системы. Или есть схема контейнера, и требуется увидеть подробную информацию о том, как каждый контейнер удовлетворяет требованиям безопасности.

Перспективы могут быть добавлены к любому элементу модели или взаимосвязи, например:

workspace {

    model {
        a = softwareSystem "A" {
            perspectives {
                "Ownership" "Team 1"
            }
        }
        
        b = softwareSystem "B" {
            perspectives {
                "Ownership" "Team 2"
            }
        }
    }

    views {
        systemLandscape {
            include *
            autoLayout
        }
    }
    
}

Этот DSL определяет перспективу «Ownership» для каждой программной системы, которую можно просмотреть, следуя инструкции: https://structurizr.com/help/perspectives.

4c9551f42a961eac2e3516e38e98919c.png

Стили связей

По умолчанию все взаимосвязи оформлены в виде пунктирных серых линий.

efbe76cf1454178126920da2179b2c0c.png

Стиль всех связей

Чтобы изменить стиль для всех связей, нужно добавить стиль связи для тега Relationship.

workspace {

    model {
        a = softwareSystem "A"
        b = softwareSystem "B"
        c = softwareSystem "C"

        a -> b
        b -> c
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
        
        styles {
            relationship "Relationship" {
                color #ff0000
                dashed false
            }
        }
    }
    
}

8e7fa7859ceeabc0759b55eac4cb376d.png

Стиль отдельных связей

Чтобы изменить стиль отдельной связи нужно:

  1. Пометить связь тегом.

  2. Добавить стиль связи для этого тега.

workspace {

    model {
        a = softwareSystem "A"
        b = softwareSystem "B"
        c = softwareSystem "C"

        a -> b
        b -> c {
            tags "Tag 1"
        }
    }

    views {
        systemLandscape {
            include *
            autolayout lr
        }
        
        styles {
            relationship "Tag 1" {
                color #ff0000
                dashed false
            }
        }
    }
    
}

9a727635383cd458c91a62831180393b.png

Стили связей предназначены для работы с облачным сервисом Structurizr/локальной установкой и могут не полностью поддерживаться форматами экспорта PlantUML, Mermaid и тому подобными.

Scripts

Ключевое слово ! script предоставляет способ запуска сценариев, написанных на Groovy, Kotlin, Ruby и JavaScript. Доступ к базовой рабочей области организован через переменную с именем workspace, на случай, если нужно сделать что-то, не поддерживамое DSL. Другие переменные (элемент, связь, представление) доступны в зависимости от того, где определен скрипт.

Представление по умолчанию без автоматической компоновки

!script groovy {
    workspace.views.createDefaultViews()
    workspace.views.views.findAll { it instanceof com.structurizr.view.ModelView }.each { it.disableAutomaticLayout() }
}

Программное добавление элементов в представление

workspace {

    model {
        group "Group 1" {
            a = softwareSystem "A" {
                tags "Tag 1"
            }
            b = softwareSystem "B" {
                tags "Tag 2"
            }
        }
        group "Group 2" {
            c = softwareSystem "C" {
                tags "Tag 1"
            }
            d = softwareSystem "D" {
                tags "Tag 2"
            }
        }
    }

    views {
        systemLandscape "key" {
            !script groovy {
                workspace.model.softwareSystems.findAll { it.group == "Group 1" && it.hasTag("Tag 1") }.each{ view.add(it); };
            }

            autolayout
        }
    }

}

Запуск Graphviz локально

!script groovy {
    new com.structurizr.graphviz.GraphvizAutomaticLayout().apply(workspace);
}

(требуется локальная установка Graphviz).

Добавить тег контейнерам

!script groovy {
    workspace.model.elements.findAll { it instanceof com.structurizr.model.Container }.each { it.addTags(it.technology) }
}

Общие компоненты

Построение диаграмм компонентов, совместно используемых контейнерами, относительно просто с помощью комбинации ! identifiers hierarchical и ! include.

Сначала нужно определить общие компоненты во фрагменте DSL:

loggingComponent = component "Logging Component" {
    technology "Java"
    description "A wrapper around the log4j framework"
    tags "Shared Component"
}

Затем определить контейнеры и включить общие компоненты, используя инструкцию ! include:

workspace {

    !identifiers hierarchical

    model {
        s = softwareSystem "Software System" {
            app1 = container "Application 1" {
                group "shared-library.jar" {
                    !include shared-library.dsl
                }

                c = component "Component" {
                    -> loggingComponent "Writes logs using"
                }
            }

            app2 = container "Application 2" {
                group "shared-library.jar" {
                    !include shared-library.dsl
                }

                c = component "Component" {
                    -> loggingComponent "Writes logs using"
                }
            }
        }
    }

    views {
        component s.app1 {
            include *
            autolayout lr
        }

        component s.app2 {
            include *
            autoLayout lr
        }

        styles {
            ...
        }
    }
    
}

Использование ! identifiers hierarchical предотвращает конфликт идентификаторов общих компонентов, и при необходимости можно ссылаться на общие компоненты через s.app1.loggingComponent и s.app2.loggingComponent соответственно.

В этом DSL также используется group для выделения общих компонентов. Оператор group был включен в основной файл DSL в этом примере, но при желании его можно переместить в файл shared-library.dll.

6fd9aa1a9dd183c83b3c48a277512e00.png

Представление системного контекста

Представление системного контекста является хорошей отправной точкой для построения диаграмм и документирования программной системы, позволяя сделать шаг назад и увидеть общую картину. В центре показана программная система, окруженная своими пользователями и другими системами, с которыми она взаимодействует.

workspace {

    model {
        u = person "User"
        s = softwareSystem "Software System"

        u -> s "Uses"
    }

    views {
        systemContext s {
            include *
            autoLayout lr
        }
    }
    
}

Этот DSL определяет системное контекстное представление для программной системы s и включает в себя все элементы модели, которые имеют прямое отношение к ней.

3931c17810458a8cb1ab49026a47fdae.png

Темы

Существуют готовые темы оформления, помогающие составить схему архитектуры, подражая популярным облачным провайдерам, таких как Amazon Web Services, Microsoft Azure, Google Cloud Platform и тому подобное.

Что такое «тема»?

Тема — это файл JSON, состоящий из одного или нескольких стилей элементов/отношений, которые определены для определенных тегов. Темы должны размещаться по общедоступному URL-адресу и размещаться по протоколу HTTPS, для использования в облачном сервисе Structurizr.

Использование тем

Ключевые слова theme или themes можно использовать для включения одной или нескольких тем в рабочее пространство. Также потребуется добавить соответствующие теги к элементам/связям модели.

workspace {

    model {
        softwareSystem "Authentication Service" {
            tags "Microsoft Azure - Azure Active Directory"
        }
    }

    views {
        systemLandscape {
            include *
            autoLayout lr
        }
        
        theme https://static.structurizr.com/themes/microsoft-azure-2021.01.26/theme.json
    }
    
}

c1d0650fe4dccfbcbec0ba3389ef479b.png

Для дальнейшей настройки, темы можно использовать в сочетании со стилями элементов/взаимосвязей, которые определены в рабочей области.

workspace {

    model {
        softwareSystem "Authentication Service" {
            tags "Microsoft Azure - Azure Active Directory"
        }
    }

    views {
        systemLandscape {
            include *
            autoLayout lr
        }
        
        styles {
            element "Software System" {
                background #ffffff
                shape RoundedBox
            }
        }
        
        theme https://static.structurizr.com/themes/microsoft-azure-2021.01.26/theme.json
    }
    
}

e436099003bcdeba5240ea2a5fe49f3a.png

Workspace

В терминологии Structurizr «workspace» — это оболочка (рабочая область) для модели архитектуры программного обеспечения (элементов и взаимосвязей) и представлений.

workspace "Name" "Description" {

    model {

    }
    
    views {

    }
    
}

Рабочей области можно присвоить имя и описание, хотя они используются только облачным сервисом Structurizr и локальной установкой. Не нужно указывать имя/описание, если представления экспортируются в один из форматов PlantUML, Mermaid и другие.

Workspace extension

Structurizr DSL предоставляет способ расширения существующего рабочего пространства, позволяя повторно использовать общие элементы/взаимосвязи в нескольких рабочих пространствах. Чтобы использовать эту функцию, нужно определить рабочее пространство как обычно:

workspace {

    !identifiers hierarchical

    model {
        a = softwareSystem "A"
        b = softwareSystem "B"
        
        a -> b "Gets data X from"
    }
        
}

Затем определить дочернюю рабочую область, используя ключевое слово extends, чтобы указать рабочую область, которая должна быть расширена. Например:

workspace extends https://docs.structurizr.com/dsl/cookbook/workspace-extension/system-landscape.dsl {

    model {
        !ref a {
            webapp = container "Web Application"
            database = container "Database"
            
            webapp -> b "Gets data X from"
            webapp -> database "Reads from and writes to"
        }
    }
    
    views {
        systemContext a "A-SystemContext" {
            include *
            autolayout lr
        }

        container a "A-Containers" {
            include *
            autolayout
        }
    }
    
}

В этом примере расширяется рабочая область, доступная по общедоступному URL-адресу, но также можно указать имя локального файла. Можно использовать ключевое слово ! ref для ссылки и расширения существующей программной системы с именем «A», которая идентифицируется в родительской рабочей области как a. Поскольку b уже определен в родительской рабочей области, мы можем ссылаться на него из дочерней рабочей области, как если бы он был определен локально.

Этот код создаст системную контекстную диаграмму:

559c76c096610cc1d8d363d6bf0acae3.png

И диаграмму контейнеров:

94ed440124be95b3bda968d6856a2115.png

© Habrahabr.ru