En route to Dev Nexus in Atlanta , Simon Brown was in Dublin on Thursday evening (2025-02-27) for a very interesting talk about his C4 model for Software Architecture. The first of the evening was an overview of C4 and then after the pizza break, Brown's second talk was about mechanisms to help identify components in existing code bases in order to help you reverse-engineer meaningful component diagrams. The event was hosted by the Dublin Java User's group.
I first came across C4 a few years ago as I felt the various classical approaches to software architecture, such as:
all had a few impractical things in common. More specifically, they take too long to deliver real value and can just feel dated. This is likely because they evolved in a pre-agile, pre-CI/CD and pre-micro-service world.
So, Google took me to C4. After watching a few YouTube videos and reading some well-structured documentation, I was comfortable to get started. I really liked how easy C4 was to pick up.
Pairing some domain knowledge and systems knowledge about the external systems we were interacting with, I had enough to put together a useful C4 Context diagram. A C4 Context reminded me of a System Context viewpoint. Although as Brown went further into his presentation I noticed he tends to use the term: "System Landscape" to describe that very big picture others may call "System Context".
Anyway, what I really liked about the Context view was the emphasis it put on describing the people who use your system. Give them an icon, a role / persona and a terse description. In no time you have all the various types of people interacting with your system on one page. Similarly, depicting your software system as a blue-colored box and everything it interacted with as their own grey boxes provided a useful big-picture view of the wider ecosystem— and a reminder software rarely exists on its on.
The Containers view (similar to a deployment view in other Arch modelling styles) is next. Again you can put these together fairly quickly. The Containers view isn't something to be confused with Docker. Brown does make the point he came up with the use of the word "container" first but of course his usage of the word isn't the Docker one. To me, what he means is the "containers" is like something that can just be independently deployed. This covers you for various micro-services you may have and those other services that deviate a little from mirco-services principles but are still deployed separately (probably a bit more like SOA).
Some key C4 principles at play here included:Give the diagram a name
Give every box a terse description
Say what the technology it is: Spring Boot, J2EE app.
In this view we can also throw in a few AWS services (or whatever you need) and you quickly also have something else very useful on one page.
Note: for both of the Context and Container diagrams, I used draw.io, which conveniently includes built-in C4 icons (as well as an extensive AWS palette and and many other useful bits and bobs)
C4 has two further levels of abstraction:Components, are the view lower than containers and higher than code - but you can define the level as you see fit. For me, I try to line this up with either higher level java packagers or jar files. But you need to ensure these things themselves are using some modular principles otherwise the components are not going to be pretty.
The Code view in C4 is really just class and package diagrams. You can use UML here if you want to.
What I really like about C4 is that you move from a high level of abstraction that helps align with Product Managers / Product Owners (so business emphasis and little technical jargon) to something that helps you align with development teams quickly. This mind set of zooming in and zooming out is a key part of software architecture. Get too stuck in the weeds you miss the big picture, but avoid the weeds completely and they just end up growing all the way up to your ivory tower until another form of havoc gets you!
So C4, is definitely something helpful. Not surprisingly about half the attendees on the evening said they were also using it in their own respective roles and companies (most using draw.io or mermaid).
There was some interesting discussion points why some people really dislike UML. Simon went through the proverbial reasons why people don't like it and made one really good point I never thought about before: for some reason it creates this sense for the need of perfection. You can't just draw a line, you have to know if it's a clear diamond or a black diamond? And isn't that just so annoying? The inclination for perfection starts slowing everyone down and creates a sense of "sign - off" - and thus increases inertia to any change.
Simon made the salient point he does in many of his presentations: "moving fast as a team requires great communication". Simple but true. How can any sort of team (not just software) move fast if communication is a challenge?
The C4 attempts to hit the sweet spot. Make communicating with the various stakeholders (business stakeholders to development teams) easier so you can all move faster.
All good stuff.
The second half of the evening was Simon's second presentation. He went through some techniques he was using to reverse engineer a component architecture out of an existing code base. Roughly speaking, it was based on looking for primary and secondary style responsibilities, identifying naming conventions and then using some DSL style stuff to get some neat looking diagrams.
He made a prescient point that you can only really do this if the code base is at a minimum level of health. Too much technical debt and you are wasting your time. GIGO holds true.
Hard to disagree with that.
One last point, he did emphasise the importance of package name spacing and governance in terms of component governance and really think this point is crucial. If you can't control the packaging, you are probably not controlling any sort of components beneath the level of deployables. And if don't have components of any sort - do you really have any sort of architecture useful for developers and construction?
He used the term "model - code gap" (coined by George Fairbanks) a few times to describe the phenomenon of software architects thinking there's an architectural model but the code doesn't line up to this in any way at all. It's a useful term to politely describe the pitfalls of ivory tower architecture - drawing nice pictures when the reality is the code base is closer to a ball of mud.
Overall, a highly relevant and practical talk.