Good architecture is a steeping stone to good software. Creating an architecture seems to be a scarce skill today. It should not be, it is a very important tool in a professional’s toolkit.
Before we go any further I want to talk some more about architecture and design. It may come as a surprise to many, as it did to me, that architecture is not design. They are different topics. Obviously they go hand in hand, ergo the confusion between them.
The architecture is the “what“, while the design is the “how“. The architecture defines what the system does while the design defines how the system does it. The architecture is the blueprint, the documentation, while the design is the implementation abstraction, the code being the implementation.
From a different perspective, the architecture is on a higher level of abstraction compared to the design.
A software architecture model is a rigorous diagram or a set of diagrams, based on available standards, used to describe a software system.
The example application
A sample software system is provided to show the C4 software architecture modeling in action. You can get it from here.
FoodTavern (the provided software system) is an 5-tier full stack system based on clean architecture:
The system is composed of the following containers:
- Android client application
- Desktop client application
- Web client application
- RESTfull web service
More on the reason they are called containers later.
The presentation layers are represented by the Android, Desktop and Web applications. Each presentation layer is implemented as an asynchronous Model View Presenter (MVP) design:
The API layer, Business layer, Data layer and Database layer are implemented at package level by the RESTfull web service.
If you want to see a Maven module approach to clean architecture, based on the same system, see: FoodTavern – v2.0.
A brief overview of the C4 software architecture model
C4 is a four step top down approach to architecture modeling.
The steps are:
- The system context diagram.
- The container diagram.
- The component diagram(s).
- The class diagram(s).
You start with the first step, and work your way through to the fourth step. That is it!
It is surprisingly simple and actually fun to use.
More details about each step next.
The system context diagram
This is the starting point of your architecture. It represents a big picture of your system, how it interacts with other systems, how it interacts with people, how it fits in the overall IT environment.
Some systems might only interact with other systems, others might interact with both people and other systems, or like in the case of FoodTavern only with people.
You can design the architecture either at package level or module level. It depends on the context of your application. It you have a small system, I would suggest package level design for clean architecture. For complex projects module is the answer.
Detail isn’t important here, this is a big picture and the sort of diagram that can be understood by non-technical people.
You represent the system with a block which contains the name of your system and the block type: Food Tavern [System].
You show user – system interactions with simple arrows and simple descriptions of actions.
FoodTavern can be used by an Android user, a Desktop user and a Web user.
That is it! That is your system.
Now let’s continue by zooming into the system to see the high-level technology choices evolved.
The container diagram
The high-level technologies choices are represented in C4 by a container diagram.
A container is something like a mobile application, desktop application, console application, web application, web service, database, etc.
A system is usually comprised of multiple containers, each with its own technology choice.
FoodTavern has four containers: an Android client application, a Desktop client application, a Web client application and a RESTful web service. All of them put together represent the system.
Just like the system context diagram, the system here is represented by a big box with the name and type: Food Tavern [System].
Similar, the containers are represented by boxes with name, type, and high level technology choices: Android App [Container: Android], Desktop App [Container JavaFX], Web App [Container: HTML + CSS + JS] and RESTful Web Service [Container: SpringBoot]. You can also add a brief description of the responsibility of each container.
Container interactions are shown with simple arrows, while the description of the interaction can use expressions like “reads from” or “writes to” or something more appropriate for your domain context.
So the container diagram shows how the responsibility of the system is distributed across containers, the high level technology choices per container, and how containers interact with each other.
At next level we zoom in into each container and decompose the architecture further.
The component diagram(s)
If this step feels a bit like design for you, then try to forget for the moment the high level technology choice for the containers.
To identify the components of the containers approach this is a more abstract manner.
For example, based on the requirements, if we must build a GUI application with a single screen to display items and add items, then ask yourself how to abstract this in smaller parts. Well, we need a single UI and everything happens in the context of this single UI. We display items and add new items, these being fruits, cheeses, sweets. This “feels” like a component, or feature if you like. A component is an abstraction of some functionality with high level of cohesion and low coupling. In this case, all functionality that has to do with displaying or adding new items has a high level of cohesion.
So there you go, you have identified your first component, in this case for the Android app.
The next component diagram is for the Desktop app. The approach to identify components is the same as for the Android app.
The difference is that now we have a new component called Main, this is because the application entry point mindset is different in Android versus a Desktop JavaFX application.
An Android application can have multiple entry points, most commonly it is an activity usually started by the user. In the context of FoodTavern‘s Android client, the main activity is implemented in the only existing component, and represents the view in an MVP design pattern.
The JavaFX Desktop application having a different approach, imposed by the technology choice, has an isolated application entry point. Because of this we can consider it as a separate component, even though it is just a single class.
Next comes the component diagram for the Web application.
The Web App contains two extra components, Navigation and ServerConnection, which are not displayed on the component diagram. The server connection is just a reminiscence of something I have tried in another project, while the Navigation is a singleton that facilitates navigation between the Food component and ServerConnection component.
So for the sake of consistency just ignore them.
And finally the diagram for the Web Service application.
This application has three components. Just like the JavaFX the main component starts the application and creates the other components.
The Food component and the ServerConnection component represent the API of the FoodTavern system. All the other containers communicate with the Web Service via this API.
The application normally runs on a server and is started by some else who is responsible for such tasks.
As already mentioned, for the sake of consistency, ignore the ServerConnection component.
The class diagram(s)
The C4 model specifies this as an optional step.
My opinion is that this step, a very important step nevertheless, is a design topic, therefor I have decided to continue this discussion in Design Considerations After Architecture Modeling With C4.
Lessons learned
Architecture is not design, design comes after the architecture, and after design comes implementation.
A good architecture and design will make implementation a simple task because you just have to translate the design into code. This rule generally applies to whatever programming language you choose to use, obviously with some differences imposed by the technology you chose to use.
The level of detail used in the architecture modeling with C4 is according to the system complexity. FoodTavern is not a complex system, so the details are just enough for a clear overview of the system, and a good starting point for a healthy design. If your context requires communicating more details, then please do so. Consider C4 a school of thought, understand how it works and decide with your team on how to apply it to your context, and adding the particularities of your context to the architecture modeling with C4.
You can design the architecture either at package level or module level. It depends on the context of your application. It you have a small system, I would suggest package level design for clean architecture. For complex projects module is the answer.