Tuesday, May 15, 2012

5' on IT-Architecture: three laws of good software architecture

The issue with architectural decisions is that they effect the whole system and/or you often need to make them early in the development process. It means a lot effort if you change that decision a couple of months later. From an economic standpoint architectural decisions are often irrevocable. Good architecture is one that allows an architect to make late decisions without superior effect on efforts and costs. Let's put that on record.

Law 1: Good architecture is one that enables architects to have a minimum of irrevocable decisions.

To minimize the set of irrevocable decisions the system needs to be responsive to change. There is a major lesson I have learned about software development projects: Nothing is permanent except change. The client changes his opinion about requirements. The stakeholders change their viewpoint of what's important. People join and leave the project team. The fact that change alone is unchanging leads me to the second rule of good architecture, that is:

Law 2: To make decisions revocable you need to design for flexibility.

This is the most provocative statement and I am having controversial discussions here. The reason is that flexibility introduces the need for abstraction. Abstraction uses a strategy of simplification, wherein formerly concrete details are left ambiguous, vague, or undefined (from Wikipedia). This simplification process isn't always simple to do and to follow for others in particular. "Making something easy to change makes the overall system a little more complex, and making everything easy to change makes the entire system very complex. Complexity is what makes software hard to change." from M. Fowler) This is one core problem of building good software architecture: Developing software that is easy to change but at the same time understandable. There are several concepts that try to tackle this paradox problem: design patterns and object oriented design principles. Polymorphism, loose coupling and high cohesion are flexibility enablers to me.

Law 3: To make use of flexibility one needs to refactor mercilessly.

Flexibility is not an end in itself. You need to actively make use of flexible design. If something is changing and it makes a previous design or architectural decision obsolete you need to go into the code and change the software. Otherwise the effort of building flexible software is useless and technical debt may cause late delays and a maintenance nightmare. The fact that you take rigorous action on your code base requires continuous feedback about the qualities of your software. To be able to refactor it is therefore essential that the code base is covered by a sufficient amount of automated tests. In an ideal scenario everything is integrated into a continuous integration environment to receive permanent feedback about the health of your code base.


  1. Great post. It is nice to be reminded once in a while that creating software is hard :).

  2. I disagree: build the simplest thing possible that solves the problem.
    To use the same quote from Martin Fowler: "Complexity is what makes software hard to change.". Building in flexibility will build in redundant code and therefore increase complexity.
    You know the least about a project when it starts so you just don't know what needs to be flexible.

    1. Couldn't it be simple and at the same time (at least a little) flexible by using design patterns and oo principles? I don't believe that the truth lies in the extremes ...

    2. Graham, The approach for simplicity lead often to stove-pipe anti-pattern. Growing code base, difficult reuse and most of all expensive to maintain. I side with Niklas here, design is key. Often neglected in so called agile projects.

  3. This is my reply:


    1. Hey Jonathan,
      thx for the replay :-)
      I didn’t read it as attack to me personally … I do believe though that the truth doesn’t lie in extremes. Of course simplicity is important. So is flexibility, and you also mentioned important concepts to achieve flexibility like IoC Containers. IoC isn’t easy to understand, but as it gets more and more “standard” many people know it now. The same is true for other design patterns. Polymorphism isn’t simple for many people but it is the most important “flexibility enabler” in object-oriented languages, wouldn’t you agree?
      I agree to all your laws. Of course its not possible to predict what’s happening. And I’m not talking about putting any silly over engineered stuff into software that is compilcated anyway. I am talking about “a necessary degree of flexibility” to make change possible without superior impact on cost and schedule. In my experience that’s key to meet the teams objectives.
      Cheers, Niklas

  4. >>"Polymorphism isn’t simple for many people but it is the most important “flexibility enabler” in object-oriented languages, wouldn’t you agree?"

    Most uses of inheritance I've seen in the wild have been harmful. You end up with complex inheritance hierarchies that are difficult to follow and understand. And code trapped in an inheritance tree that would be much more appropriate being used via delegation.

    "I am talking about 'a necessary degree of flexibility' to make change possible without superior impact on cost and schedule." Adding in enough flexibility and abstraction to let you easily swap out frameworks means adding a huge amount of complexity. There is no free lunch.

    See my comment here (when it makes it past moderation):

    1. I'v also seen the endless 'I don't know where I am anymore' hirarchies. Most of the times the were due to misuse of inheritance for plain reuse purposes. Use it right and your system will be nice :-) Many of Uncle Sam's design principles are based on inheritance (eg Open/Closed Principles) ... Many (if not all) design patterns are based on inheritance ...