Software Architecture as Code With Structurizr
Are you using the C4 model to create your architecture diagrams? In this article, explore Structurizr as an option to create and maintain your diagrams as code.
Join the DZone community and get the full member experience.
Join For FreeAre you using the C4 model to create your architecture diagrams? Then Structurizr might be a good option for you to consider. With Structurizr, you can create and maintain your diagrams as code. Let’s take a closer look at it in this blog!
Introduction
The C4 model helps you with visualizing software architecture. We all know the whiteboard diagrams cluttered with boxes and connectors. The C4 model approach helps you visualize software architecture in a more structured way. A good explanation is given on the C4 model website, so if you do not know what it is, it is worth reading it first.
The next question is which tool you use to create the diagrams. You can use Visio, draw.io, PlantUML, even PowerPoint, or whatever tool you normally use for creating diagrams. However, these tools do not check whether naming, relations, etc. are consistently used in the different diagrams. Besides that, it might be difficult to review new versions of diagrams because it is not clear which changes are made.
In order to solve these problems, Simon Brown, the author of the C4 model, created Structurizr. Structurizr allows you to create diagrams as code. Based on the code, Structurizr visualizes the diagrams for you and allows you to interact with the visualization. Because the diagrams are maintained in code, you can add them to your version control system (Git) and changes in the diagrams are tracked and can be easily reviewed.
In the remaining part of this blog, you will explore some of the features of Structurizr. You will only use two diagram types of the C4 model (the most commonly used ones):
- System context diagram: Your application as a black box indicating the users of your application
- Container diagram: An overview of your software architecture
Sources used in this blog can be found on GitHub.
Prerequisites
Prerequisites for this blog are:
- Basic knowledge of the C4 model
- Basic knowledge of Docker
- Linux is used, so if you are using a different Operating System, you will need to adjust the commands accordingly.
Installation
There are different installation options for Structurizr. In this blog, you will make use of Structurizr Lite, which is an easy installation using Docker which supports one workspace.
- Create in the root of the repository a data directory. This directory will be mapped as a volume in the Docker container.
- Execute the following commands from within the root of the repository.
$ docker pull structurizr/lite
$ docker run -it --rm -p 8080:8080 -v ./data:/usr/local/structurizr structurizr/lite
- Navigate in your browser to http://localhost:8080 and the Structurizr webpage is shown.
In the data directory, you notice that some data is added. When you take a closer look at it, you notice that all files have the root ownership. This is not very convenient, because when you want to edit the files, you have to do so as root.
$ ls -la
...
drwxr-xr-x 1 root root 22 feb 18 12:04 .structurizr/
-rw-r--r-- 1 root root 316 feb 18 12:03 workspace.dsl
-rw-r--r-- 1 root root 2218 feb 18 12:04 workspace.json
- Stop the container with CTRL+C and remove the contents of the data directory.
You will start the container with the same user you are using on your host machine. With the id
command, you can retrieve your uid and gid. It is important that you use the same uid and gid inside the container in order that files can be edited easily inside and outside the container.
Replace in the following command <uid>
and <gid>
with your uid and gid and start the Docker container again.
$ docker run -it --rm -p 8080:8080 -u <uid>:<gid> -v ./data:/usr/local/structurizr structurizr/lite
When you check the ownership of the files again, you will notice that the directory and files are now owned by your host user.
- Navigate again in the browser to Structurizr and enable Auto canvas size and Auto-layout. This will create a more beautiful diagram.
Initial DSL
First, let’s take a closer look at the initial DSL that has been created. The complete DSL reference can be found here.
The initial DSL is the following:
workspace {
model {
user = person "User"
softwareSystem = softwareSystem "Software System"
user -> softwareSystem "Uses"
}
views {
systemContext softwareSystem "Diagram1" {
include *
}
}
configuration {
scope softwaresystem
}
}
The following sections can be viewed:
model
: The model contains the actors and the software system. If you need to reference these in the DSL, e.g., in relations, you assign them to a variable. The variablesuser
andsoftwareSystem
are used here. The model also contains the relations. One relation fromuser
tosoftwareSystem
is created.views
: To visualize the model, you need to create views. In this initial DSL, a view of the System Context Diagram is created. With theinclude
keyword, you can include all or a part of the model.configuration
: This section will not be covered in this blog.
Basic System Context DSL
Now it is time to create a System Context Diagram for your application. The application is a webshop with two types of users, a customer and an administrator. The webshop makes use of a global payment system that handles bank transactions.
The DSL is the following:
workspace {
model {
customer = person "Customer" "The customer of our webshop"
administrator = person "Administrator" "The administrator of the webshop"
globalPayment = softwareSystem "Global Payment" "Used for all banking transactions"
myWebshop = softwareSystem "My Webshop" "Our beautiful webshop"
customer -> myWebshop "Uses"
administrator -> myWebshop "Uses"
myWebshop -> globalPayment "Uses"
}
views {
systemContext myWebshop "MyWebshopSystemContextView" {
include *
autolayout
}
}
}
Some things to notice here:
- Relations have the following format:
identifier -> identifier description technology
. The identifiers must correspond to a variable defined above the relations. - Views have the following format:
systemContext softwareSystem key
. ThesoftwareSystem
must correspond to an identifier defined in the model. The key can be chosen freely. - The
autolayout
option can be added to the view so that it is enabled by default for this view. - A problem I encountered is the following:
- Only one person was shown in the view, the last one defined. I managed to solve this by commenting on the entire view section. A default view is used this way. With this default view, all persons were shown. After this, I enabled the view section again, and now all persons were shown.
The System Context Diagram is shown as follows. You can also apply themes to the views, which will enhance your diagram.
You can also apply themes to the views, which will enhance your diagram.
views {
systemContext myWebshop "MyWebshopSystemContextView" {
include *
autolayout
}
theme default
}
The System Context Diagram becomes the following. This already looks more like a C4 model System Context Diagram.
Basic Container DSL
Time to create a diagram for the software architecture, the Container Diagram. Assume that you need a frontend for both users, a common backend, and, of course, a database.
The DSL becomes the following:
workspace {
model {
customer = person "Customer" "The customer of our webshop"
administrator = person "Administrator" "The administrator of the webshop"
globalPayment = softwareSystem "Global Payment" "Used for all banking transactions"
myWebshop = softwareSystem "My Webshop" "Our beautiful webshop" {
customerFrontend = container customerFrontend "The frontend for the customer"
administratorFrontend = container administratorFrontend "The frontend for the administrator"
webshopBackend = container webshopBackend "The webshop backend"
webshopDatabase = container webshopDatabase "The webshop database"
}
// system context relationships
customer -> myWebshop "Uses"
administrator -> myWebshop "Uses"
myWebshop -> globalPayment "Uses"
// software system relationships
customer -> customerFrontend "Uses" "https"
administrator -> administratorFrontend "Uses" "https"
customerFrontend -> webshopBackend "Uses" "http"
administratorFrontend -> webshopBackend "Uses" "http"
webshopBackend -> webshopDatabase "Uses" "ODBC"
webshopBackend -> globalPayment "Uses" "https"
}
views {
systemContext myWebshop "MyWebshopSystemContextView" {
include *
autolayout
}
container myWebshop "MyWebshopSoftwareSystemView" {
include *
autolayout
}
theme default
}
}
What has been added to the DSL?
- The application
myWebshop
in the model has been extended with the containers defining the architecture. - In the model, the relations are defined between the containers. Note that this time, also the used technology is added to the relations.
- A container view is added to the views.
The container view is represented as follows.
The fun part is that when you navigate to the System Context Diagram, you can double-click the myWebshop software system and it will show you the Container Diagram. Awesome!
Styling
In the Container Diagram, the database is represented as a rounded box. Normally, a database is represented as a cylinder. Is it possible to adjust this? Yes, you can. This can be done by means of styles. The list of possible shapes can be found here.
A style can be applied to an element by using a tag. First, in the views
section, add a style for an element with the tag Database
. You apply a shape Cylinder
to this element.
views {
...
styles {
element "Database" {
shape Cylinder
}
}
}
Now you need to add a tag to the corresponding container. When you define a container, you need to define it with the following format: container [description] [technology] [tags]
.
In the container definition, you did not specify the technology. There are two options here:
- Add a technology to the container. This is a bit error-prone, as you have to know the format by heart and you can simply forget to add the technology.
- Set the tags explicitly. This is the one chosen here.
webshopDatabase = container webshopDatabase "The webshop database" {
tags "Database"
}
The complete DSL can be found on GitHub. The resulting diagram is the following.
Conclusion
Structurizr helps you with creating diagrams according to the C4 model. The diagrams are created by means of a DSL which has several advantages. You need to learn the DSL of course, but this can be learned quite easily.
Published at DZone with permission of Gunter Rotsaert, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments