Rethinking Software Architecture

Rethinking Software Architecture

Some descriptions of Software Architecture describe it as "the stuff that we can't afford to get wrong"

I think that this is a big mistake, because if we can't afford to get it wrong, it means that we MUST GET IT RIGHT FIRST TIME, and the chances of that are slim. It implies a need for perfection on the first attempt, which is an unrealistic expectation in the complex realm of software development.

So a better approach, is to adopt an evolutionary approach to architecture, allowing us the freedom to make mistakes, to learn and make continuous refinement of both our understanding, and the architecture itself, as we make progress.

Get my FREE Guide to Evolutionary Software Architecture here.

Tools for Managing Complexity

The journey towards an evolutionary architecture is supported by key principles that help manage complexity:

  • Modularity
  • Cohesion
  • Separation of Concerns
  • Abstraction
  • Loose Coupling

Among these, the latter three—Abstraction, Separation of Concerns, and Loose Coupling—are particularly potent at the architectural level.

Isolating Uncertainty

A critical insight into effective architecture is the notion of isolating uncertainty. This was an idea I explored with @KevlinHenney (during a chat for my podcast “The Engineering Room" who pointed out, "As soon as someone says 'I don't know,' that's a seam in the design." These 'seams' are opportunities to abstract complexity and isolate uncertain elements, thereby simplifying the overall design.

Separation of Concerns

Separation of Concerns is a great tool to help us hide information in this way, processing an Order is a different thing to storing that order, so I want each of these acts to be represented in different parts of the code.

This allows me to make progress when I am unsure, if my processOrder code orchestrates payment, manages accounts and discounts and so on, and then calls a SEPARATE PIECE OF CODE to store the order, hiding details of how it is stored,

Then perhaps I can begin with code to store orders in a simple file, later when I decide that what I really need is a Relational DB, I can change the code in 'store', without changing any code in ‘process'!

When later, I learn that what I really needed all along was a graph DB, I can do that too. Still keeping the 'process' code unchanged.

The Art of Evolutionary Design

It is more complicated than this of course, but this idea of isolating and abstracting the parts of the system that you don't yet fully understand is a cornerstone of a more evolutionary approach to software architecture, defer decisions with abstraction!

There is some art to this kind of design - at its heart this is all about managing complexity in our systems, and crucially, working to maintain our freedom to change things when we learn different or better ways that we can solve a problem.

It's about embracing the complexity inherent in software systems and maintaining the agility to adapt as new insights emerge. The ultimate goal is to design code and systems that are inherently flexible, facilitating easier modifications over time.

I have several videos that explore ideas for great design in software architecture on my YouTube channel for example:

Software Architecture Tips I WISH I Knew Sooner

What Software Architecture Should Look Like

Software Architecture Principles from 5 Leading Experts

The Essence of Quality in Software

In my book - Modern Software Engineering, I argue that:

"the true measure of quality in software lies in its ability to change"


Great article : ) May I ask where the initial statement ("the stuff that we can't afford to get wrong") come from ? Your article make me think of some ideas I had read in « Software Architecture in practice » book : - not all early decisions are architectural. - it is not always possible to state that a decision is major or not, and sometimes only time would tell. - each decision become a constraint for future decisions. The more layers of decisions we add, the harder it will be to change the system. - the timing to bind a decision to the system is important. In case of uncertainty, it is better not to constraint the system with decisions that can become blockers later on.

Like
Reply
Baciu Wahl Cristian

🌐 Senior .NET Engineer | Azure Solutions Architect and DevOps | Remote Only Jobs 🏆 Microsoft Azure Certified

8mo

Modern Software Engineering is such a good book. This should be on the list of reads for all people involved in software development, testing and delivery.

Bilge P.

Software Engineer • Cloud • .NET • Distributed | Parallel Growth • Curiosity • T-Shape

8mo

'The true measure of quality in software lies in its ability to change.'

Christoph Jahn

CEO & Founder | Tools & Consulting for webMethods® | 𝗝𝗮𝗵𝗻𝗧𝗲𝗰𝗵.𝗰𝗼𝗺

8mo

Thanks for the great summary. One aspect that I would like mention is the understanding of the problem domain, which usually means the business context. This is implicitly part of the article, of course. Still, I wanted to point out that for me personally this understanding has always made design choices much easier. If I at least roughly understand the various parts of the problem, I also see the boundaries between them. Bounded contexts in DDD terminology. And those are the places in the real world where e.g. coupling occurs. Therefore in my opinion they also make obvious candidates for the software architecture side. Eric Evans, Martin Fowler #ddd #domaindriven #design

To view or add a comment, sign in

Insights from the community

Others also viewed

Explore topics