Once I was sold on the C4 concept it was only a matter of time before I tried to build a DSL that targets it's abstractions.

Introducing ArchitectureScript

In the previous post I talked about the C4 model and I implied that you should avoid Visio. I'm not going to complain about Visio, it's a great tool, it's just not my tool of choice for creating diagrams that change frequently. There's a few reasons for this.

Firstly, the result looks (kind of) polished. I will admit to spending a good half an hour making sure all of the lines in my Visio diagram are lined up perfectly, and that all of my boxes are the same size, only to then add two new boxes and have the auto-layout algorithm in Visio completely rearrange my carefully arranged pixels. This isn't Visio's fault, it's mine. I was focused on minute detail at a time in the process when it wasn't really appropriate. "Rearranging deck-chairs on the Titanic" as one colleague likes to say.

This is a good case for a whiteboard or hand-drawn diagram. When most lines aren't straight and multiple pens have been used to make annotations (often by people with vastly different handwriting and drawing skills) people stop looking at the presentation and start looking at the content. You can see something similar in prototyping with the Balsamiq mock-up tool using a messy looking "hand-written" style for it's visual components. Make it look too real and people complain about the font size instead of noticing that you built the wrong screen.

The second reason that I don't like Visio diagrams is that it is very difficult to figure out what's changed from one version to the next. This is also not Visio's fault. Visio is all about the diagram and to be honest, I really don't care what's changed in the diagram. I care what's changed in the underlying model that the diagram is representing. Now that's a complaint that can be levelled against hand-drawn diagrams too. Although, come to think on it you could simply make all changes with blue/red pen and then take a black and white photocopy after each session :)

Simon Brown (inventor of C4) proposed a solution that extracts system context information from a codebase. The way this works is that it constructs an in-memory model of the system, related systems and people using Java code and then serialises this information in a JSON format. You then upload this JSON model to a web application named Structurizr which generates a nice HTML Canvas diagram that you can arrange to your hearts content and then export as an image. There's no automated layout with this yet which means you still are going to spend a few minutes stuffing about with dragging elements around but hopefully that will come in a future version.

There's a couple of benefits to this approach. Firstly, the model is in code which means you can check it in to source control and use your standard diff tools to figure out what's changed from version to version. Secondly, when you want to go beyond the System Context diagram and into the Container and Component diagrams, you can use reflection to build the model directly from your codebase! (this too has been proposed by Simon and I recommend the follow up post which talks about handling complexity that can be caused by doing this)

This is great news as it means that your architectural diagrams could be generated from your build, thereby guaranteeing that they are up to date with each new release.

This had me very excited but I don't work in Java, I work in C# (actually at the time I was working in VB.NET but that's a different story). So I started working on my own implementation of the model. You can find it on GitHub (/ArchitectureScript/Model/Model.cs). If you create a model using that class and serialize it to JSON (I used Json.NET to do so), it works with Structurizr just fine.

But then I started thinking. I don't want to kick off a Visual Studio solution and a C# application to describe a high-level solution architecture? I also don't want to have to diff c# code to find changes in my model. What I want is a very simple domain-specific language that knows about the abstractions prescribed by C4 that I can use to build up my high level model. And so, ArchitectureScript is born.

The idea behind ArchitectureScript is that I can rapidly prototype what I think the model looks like, generate a diagram from it, gather feedback and then incorporate that into my model. The fact that it is almost plain text means that I can get people not-familiar with the format to make changes fairly easily and I can diff changes to the model in a way that is very simple to understand.

Here is an example of an ArchitectureScript which describes the techtribes.je ecosystem that Simon uses as an example:

internal system techtribes.je
  desc techtribes.je is the only way to keep up with the IT, tech and digital sector in Jersey and Guernsey, Channel Islands
  uses Twitter
    Gets profile information and tweets from.
  uses Github
    Gets information about public code repositories from.
  uses Blogs
    Gets content using RSS and Atom feeds from.

external person Anonymous User
  desc Anybody on the web
  uses techtribes.je
    View people, tribes (businesses, communities and interest groups), content, events, jobs, etc from the local tech, digital and IT sector.

external person Aggregated User
  desc A user or business with content that is aggregated into the websites.
  uses techtribes.je
    Manage user profile and membership.

external person Administration User
  desc A system administration user.
  uses techtribes.je
    Add people, add tribes and manage tribe membership.

external system Twitter
  desc twitter.com

external system Github
  desc github.com

external system Blogs
  desc RSS and Atom feeds

view context techtribes.je

This description flows reasonably well and when processed by ArchitectureScript produces a JSON file that Structurizr can turn into

Techtribes.je System Context

Now obviously this toolchain is still pretty raw. Here are some pain points that I hope can be addressed this year:

  1. I have to manually upload the JSON to Structurizr
  2. I have to arrange the boxes on the diagram myself
  3. I have to export the diagram as an image

All of these things make it basically impossible to have the diagrams come out of my build but I can generate the JSON for now so I can track the model over time. Simon has already mentioned that a Structurizr API may be coming eventually so hopefully that will at least eliminate the 1st issue. The 2nd is actually a reasonably hard problem to solve although there are algorithms out there for auto-layout of diagrams. Once that is done, the 3rd issue can simply be built into the API. Or Structurizr could become a local build-time tool.

Or here's an idea. Currently I am typing this blog post into MarkPad which has an edit panel on the left and a fully formatted preview window on the right. Wouldn't it be great to be able to type ArchitectureScript in an editor and have a System Context diagram appear in real-time on the right? That could lead to some pretty rapid prototyping sessions.

But Mike, I hear you cry, the whole point was to pull the model into the code so that we could use it for all of that fun reflection stuff! True enough and you can do that by simply constructing the model in memory, adding in your auto-discovery bits and then serializing the model. The advantages to the text-based DSL are:

  1. It's more human-readable
  2. Easier to diff (because it's more human-readable)
  3. Language independent

This last point is important. There is nothing stopping you from using Json.NET (or the Java equivalent) to de-serialize the JSON file back into in-memory objects, performing your reflection to add in components and then re-serialize the model. I'd actually propose it would be just as easy to spit out ArchitectureScript files based on your component reflection. Whether or not you're going generate a diagram from them the ArchitectureScript file is a nice human readable way to list out your components and how they interact.

So that's ArchitectureScript. As it stands currently you can use it to describe Software Systems,People, Containers, and Components. You can also use it do define System Context diagrams, Container diagrams and Component diagrams from the C4 model. By default, each view is centred on one element and any other element that is not eventually connected gets dropped out of the diagram. If you want to go to the class level you'd need a different tool. Check out the github wiki for more info on the ArchitectureScript language.

What are your thoughts on this approach to describing static structure?

Posted by: Mike Minutillo
Last revised: 29 Jan, 2015 07:47 AM History


No comments yet. Be the first!

No new comments are allowed on this post.