Let’s talk about something every software architect has encountered: how to design an architecture from scratch! Don’t worry, this article won’t be a boring, endless technical journey. On the contrary, I’ll guide you through each step of the process with a light approach and some practical insights from my experiences over the years. Whether you’re planning to design a new system or simply want to better understand what goes into a good architecture, you’re in the right place.
I know, I know... you’ve heard this a million times, but let me tell you: gathering requirements is like choosing the land where you’ll build your house. If you skip this step or do it poorly, the chances of running into problems later are very high.
Functional requirements are the tangible things the system needs to do. Think of something like a restaurant system: “place orders,” “register new products,” and so on. Non-functional requirements are more subtle but just as important. They define aspects like the volume the architecture needs to support (will there be 100 or 100,000 users?), security (what protection mechanisms will I implement?), and scalability. This information will determine whether your system can survive a spike in traffic or collapse like a house of cards on Black Friday.
A good architect knows that spending time on requirements gathering isn’t a waste of time but an investment. For me, this process is the foundation for setting the direction of the entire project. After all, no one wants to create a system that only holds up until the first demand increase, right?
Once you’ve mapped out the requirements, it’s time to organize the domains. Think of this like setting up the rooms in an apartment: each room has a purpose, and you don’t want to mix everything in one place, right? The same goes for your architecture.
Each domain is a specific area of the system. Let’s use the example of an online pharmacy: you can separate the system into domains like inventory, cash flow, and customer registration. Each of these domains will have its own data and functionalities, and keeping this division clear helps avoid the dreaded excessive coupling.
By using this strategy of bounded contexts, you not only make maintenance easier but also scalability. Want to add a new module? No problem, because each part is well separated. Want to migrate part of the architecture to another service? Easy, because your domains are well defined. This approach is widely recommended by experts like Eric Evans, the father of Domain-Driven Design (DDD). He always emphasizes the importance of keeping contexts clear to avoid confusion and ensure that each area functions independently.
With the domains in hand, now comes the part that many people find complicated but can actually be quite fun: architectural diagrams. Remember when you used to draw in school? It’s almost the same thing, but with boxes and arrows! 😅
Here, you can use traditional UML diagrams (like use case or sequence diagrams) or something more specific like the C4 Model, which is my favorite. It allows you to visualize the architecture progressively, starting with a broad overview (L1) and then diving into the details of the components (L2, L3...). This helps to have both a macro and micro view of the system.
But diagrams are not just for aesthetics. They are essential for making critical decisions, such as:
These decisions are only a few examples of decisions based on the requirements you’ve already gathered that will ensure that the architecture is consistent, scalable, and resilient.
Now we’ve reached the final step, but certainly not the least important: the final documentation. Have you ever heard of the famous Blueprint from civil architects? The idea is the same, but in the software world. This document will guide the system’s development from start to finish, serving as a sort of "instruction manual."
In it, you should include:
Besides guiding development, the Blueprint serves as a complete documentation of your architecture. This means that not only will you have a functioning system, but you’ll also have a documented system (and that’s rare!). As Martin Fowler highlights, documentation is a vital part of the process because it ensures that the project maintains its coherence and can be maintained and updated by others in the future.
Designing an architecture from scratch is like drawing a map for an epic journey: you need to plan every detail but also be flexible to adjust the course. The secret lies in listening to the requirements, organizing the domains, making experience-based decisions, and, of course, documenting everything clearly.
This method has worked well for me over the years, but like all good architecture, it’s always a work in progress. Each new project brings lessons, and the pursuit of continuous improvement is what keeps the work of software architecture so exciting and challenging.