The more I think about the advantages and disadvantages of upfront design, the more I find it complex, I mean, the whole software architecture diagramming in general. I’ve been following the development of the C4 model for a considerable time, I find it interesting, but it still brings me the old struggles about how much detail we should put into the diagrams and whether we should do it while planning the software, while developing it, or after.

I believe that when drawing architecture diagrams we should focus on getting the right purpose and the right level of abstraction.

I do think that the diagram should reflect the code in certain level of abstraction and that this could be really useful for a new engineer in a large project. Tackling a huge codebase is not an easy task, and the diagrams should act as a map of the code, saying how things communicate with each other.

Perhaps what we need is different types of architecture diagrams, each one for a specific development phase. What comes to my mind is:

Project planning phase: we can’t code without any upfront planning, at this level I feel necessary to draw the most visible containers and components, this way we can plan what to do next, how to split up teams to each part of the system. It’s when a deployment architecture can be written as well.

Project evolution and maintenance: as we reach this phase of the project, it’s interesting to see the Big Picture, the Not-So-Big Picture and the Small Picture. I can see many cases where this could be helpful, for instance: new engineers coming to the project, debugging something that crosses many components and containers, and I’m sure there are many more.

Given this task, I’d prefer taking a top-down approach, going from Big Picture architecture to a more detailed one. As an example, I’m going to use a side project I was working on, which is a simple webapp to search for simple food recipes.

I followed a backend + client side app approach: in the backend is where the main logic happens, the core business classes and everything, in addition to exposing a simple REST API. Client side just consumes the backend data through its API.

Each of these 2 parts will be a different application, which can be dockerized and run in different plataforms – two separate amazon EC2, for example. So if we’re planning it, we could start by saying:

The client will talk to the backend’s api over HTTP, the backend will communicate to the client and to a database instance. Ok, that’s a start. We can easily separate a team for the backend and its api and another team for the web client.

Still, it doesn’t say much about the inner details of each container, and now we need something more detailed. So we break it down a bit more:

As we can see, it’s the same structure, but with way more details, which makes it clearer to everybody how we can tackle the problem with actual coding. An extra level of detail would be going down one more level of abstraction and describe the classes through a class diagram, explaining how the core backend would be implemented, for example.

Now, this diagram, plus all requirements gathered can be a nice start for the implementation phase. We can add now how we would deploy it:

I believe those 3 diagrams plus the codebase could be helpful for efficient communication.

Though I still have many open questions about this, e.g: the cost of this upfront design is a concern,so I’m open to discussions.