Deferring decisions in Evolutionary Architecture

When building Evolutionary Software, the practice of "deferring decisions" is key.
To defer a decision means "to put off to a later time; to postpone". Remember, the most important Quality Attribute of an evolutionary architecture is Evolvability or Changeability. It should allow for incremental and guided change as its primary principle.

Delay your design decisions until they're absolutely necessary. Make decisions based on facts, not guesses or (known) unknowns.

Why

Especially when you're designing architectures for large enterprise applications, things can get complicated, fast. Capturing all requirements before the start of the actual implementation phase can be difficult (if not impossible). Throw the fast-paced changing technology landscape on top of that, and you're left with the realization that you have to incorporate change in your design. I have started numerous projects where core-frameworks were outdated and replaced by the time of actual release!

Start the development business value as soon as possible. If you build correct abstractions; replacing frameworks, technologies and even host runtime should be possible. The higher the internal quality, the faster functionality can be delivered. And that point should occur in weeks, not months.

Rapid Application Development

Rapid development, as the name suggests, focuses on fast development. It relies heavily on prototyping, capturing as much functional and non-functional requirements as possible, but keeps the focus on the development part.
Make no mistake, the prototypes eventually become products. But, RAD allows us to write code extremely fast, without cutting into the quality aspect of the application.

Prototyping, when done right, can ignore (or at least postpone) the impact of the decision making process. Once the decisions is made, it can be implemented without compromise.

It's not about sacrificing quality, it's about building an architecture that's adaptable and flexible. It relies on different paradigms to allow hard choices to be made at a later stage. Did you ever have the "which-orm-framework" discussion? Or the "how-to-log-the-correct-things" discussion? I have, and they are endless. Deferring decisions allows you to choose an ORM later. Or a logging framework. Or a database technology. Or even a cloud environment. All these things should be thought of as dependencies. And they should be treated as such.
Do you business requirements change if you choose to work with Dapper, EF or NHibernate? Nope. So why should you make these decisions from the start?

The pro's

  • Better quality. That's right!! If you build an application that allows for constant change, that embraces evolution, that chooses one -ility above all other -ilities, namely changeability, that application will be, without a doubt, a better application!
  • Better risk management and mitigation. You are constantly pushing yourself to think about peripherals, about risks. If I postpone my decision, what will the effects be? Is this something I can postpone. Why not?
  • Focus on the complex bit, in a prototype kind of way. All the rest, is just all the rest, which will be added later anyhow. For the most part I have found that developers love working this way.
  • Incredibly fast delivery and short feedback cycles with a focus on user and business input.
  • Super flexible and adaptable. The lean and mean approach. Focus on getting things done, without planning and documentation overhead.

The con's

  • It's complex. Your whole team needs to adopt this approach, or it just won't work. You need the skill-set, knowledge and know-how to playfully write production quality code. And that's not easy. You need highly skilled developers who can keep up with the agility and challenges this WoW imposes.
  • Risk management is not easy. You'll get it wrong. A component couldn't be as "adaptable" as you originally thought. You slow down development only for important decisions, but who's to say what's important? That's you, and you could be wrong 😉.
  • The bigger the project, the bigger the problems. Scalability is not really the best suit for this model. The business and landscape you find yourself in are real factors when choosing to adopt this model.
    If you have to build an event driven server-less micro service architecture that runs on Kubernetes on a hybrid cloud platform; I strongly suggest you think a bit before you start development.
    But, I have successfully delivered applications built in the RAD/evolutionary model, in complex environments and organizational structures, that eventually evolved into server-less distributed systems. So it can be done!

Photo by Kaleidico on Unsplash

Further reading:

Architectural Decision Record
I firmly believe there is no such thing as a “bad” or a “good” architecture. It either fits the business needs from a technical perspective, or it doesn’t. A technical design is always the result of a series of “choices” and “decisions” throughout the lifetime of that design. But it’s
Using Fitness Functions to create Evolving Architectures
Fitness Functions are objective functions, used to summarize how close a prospective evolutionary design solution is to achieving a set of aims or goals.