§10.3.

Choosing an architecture

In the previous section, I defined software architecture as the expert developers' understanding of the design of a project.

So, how do you design an application’s architecture?

Design begins with a deep understanding of the problem. A designer must have a deep understanding of the project’s objectives, the desired characteristics of quality and the likely future directions.

Design is then a search for solutions, guided by your experience and the expertise of others. This search is iterative: generate possible solutions, then test to see if it will work.

For new programmers, this is not easy. At first, generating possible solutions could be random changes, then testing these ideas by implementing them in full to see if they work.

With experience, design will become easier. Experienced developers can draw from past successes to generate possible solutions. Experienced developers can test solutions by ‘mental simulation’: imagining the code, without writing it.

Such experience takes time and effort to gain. However, there is a short-cut. By studying the solutions created by experts, we learn from their hard-earned wisdom without replicating the efforts it took to find their solutions. Indeed, even a lifetime of experience will not eliminate the importance of listening to and learning from others.

The wisdom of other designers can be found online (in blogs, and best-practice guides) and in fantastic books on architecture and design patterns.

Recommended readings

The following books helped me grow my capability to generate and test solutions to software architecture problems. I like these books because they are extremely practical and readily applied to new situations.

  • Fowler (2002) Patterns of enterprise application architecture

  • Richards and Ford (2020) Fundamentals of software architecture

  • Evans (2004) Domain-driven design: tackling complexity in the heart of software

  • Kleppmann (2017) Designing data-intensive applications: the big ideas behind reliable, scalable, and maintainable systems

  • Gamma, Helm, Johnson and Vlissides (1994) Design patterns: elements of reusable object oriented software

Minimum viable architecture

Minimum viable architecture refers to the idea that software architecture should only be as sophisticated as it needs to be. You should not over-complicate your architecture.

Major software companies, such as Netflix and Facebook, often publish information about their internal infrastructure and software architecture. However, the architectures used by these organizations are incredibly complex. An organization serving 180+ million subscribers (Netflix) or 2.6+ billion users (Facebook) has needs that are different from an internal web application with a few hundred users.

Even if your ambition is to build the next billion-dollar company, a simple architecture will allow you to grow right now. You can gradually evolve your architecture when your ambitions become a reality.

When to evolve architecture

It’s time to improve your software architecture when:

  • Simple changes seem to consume a lot of time

  • Simple changes involve edits to many files or functions

  • Some files, functions or modules have become very large, long, complex or have too many parameters

  • Parts of the code are confusing and require an unusually high level of attention to change

  • There is a lot of repetitive or copied-and-pasted code

  • The same bugs keep occurring over-and-over again

  • Every single bug is tough to fix [1]

  • There are parts of the code that are ‘ugly’ or that team members want to avoid touching

  • The code seems to be ‘getting worse’ with every single change

All of these connect to the idea of simplicity. When code is no longer simple or clear, there is a good chance that thoughtful restructuring will bring back some simplicity.


1. There will always be some hard-to-fix bugs: some problems are fundamentally difficult. However, it is a sign that there is a problem when almost every bug seems to be hard to fix.