Thomas Sundberg

October 27, 2015

When is evolutionary design a good way to implement software?

This post has been migrated to

Designing software can be done in different ways. The time and effort spent on designing have an important effect on the result. An interesting question is: When should you allow the software to evolve using Test Driven Development, TDD, and when should you not?

Software Development Gang

This blog post is the result of a session at an open space with the Software Development Gang in Ghent, Belgium, June 2015.


Before it is possible to discuss when to use and when not to use evolutionary design, we need a definition.

Which domain are we talking about? This blog is about software development. Therefore, we are referring to software development and nothing else. That is, the process of writing a computer program that solves a problem its users have.

What do we mean with evolutionary design, then?

We see it as the process of building a solution in small steps and allowing concrete needs to steer the development. Needs that show up when we implement the solution. Needs that we didn’t really think of before we started the development.

That may seem as a strange view. Isn’t all development done this way? It turns out that the answer is no. All software isn’t implemented this way.

What is the preferred way to develop software then?

As we see it, designing when needed and building in small steps between the design sessions. Allow the design to appear when there is a need. Test-driving the implementation using Test Driven Development, TDD. Some initial design is OK and usually a good idea. You don’t have to start with no design. You probably have an idea of where you are headed.

This is the opposite of big design upfront where all details must be specified before the development is allowed to start. Big design upfront is sometimes the result of an offer for fixed price projects. If you don’t do a lot of thinking and estimating upfront, it is very complicated to give an offer that is valid. An offer you won’t loose money from but rather make money from. In our experience at least, big design upfront is never a good idea.

Remember, it is in doing the job you really discover what you need to do. Things that you missed even when you though very long and very hard.

Big design upfront vs. evolutionary design

How do you know the difference between big design upfront and evolutionary design?

The line may seem, and is, fuzzy. There are no clear rules that can be applied that will tell you what type of design you are doing. There is no recipe that you can lean against.

We think that when we are designing for days, it is a clear sign of something big. It is an example of a too big design upfront.

We prefer to design for a few minutes up to an hour at a time when there is a need. We never want to design our solution much more than an hour.

Taking small steps will allow the design to grow and evolve as needed.

First reaction

Thomas Sundbergs first reaction was that the question “When should you prefer to use evolutionary design and when should you prefer not to use evolutionary design?” is clearly wrong. Of course you would want to use evolutionary design. All the time. No exceptions.

It turns out, however, that it is not that easy. Things are seldom easy in the real world. There are definitely many cases when a test-driven approach to grow the design evolutionary doesn’t apply. Many more cases than he could imagine.

Will not

These are examples of situations where we most likely would not recommend using an evolutionary design.

Don’t know the technology

When you are in learning mode and lack experience of the technology you are trying out. It is a throw away experiment. And you know that you will throw it away. Or reformat it to become a blog post or similar. Then you will probably not have a need to use TDD to drive the design.

The team knows it’s impossible to do mistakes

When a team has the required experience of a domain and really knows that it is impossible to do mistakes.

We would still cover for regressions on some level, possibly end-to-end tests.

The framework can verify the wiring

We would not use low level TDD when a framework can help with verifying wiring of components.

We would, however, write end-to-end or acceptance tests. End-to-end would use the correct database etc.

Acceptance tests may or may not fake parts of the backend. The system can be accepted with a fake database, at least on a functional level.

The team doesn’t have the knowledge to use tests to drive the design

An inexperienced team can’t use tests to drive its design. Test-driving development is a skill that not every team possesses. If the team doesn’t know how to do it, it might be a better idea not to impose this habit onto them.

TDD doesn’t necessary lead to a good design. It can lead to good design, or at least prevent bad design. But learning good design is a skill in itself. Testing is another skill. It is possible to have both skills, but one of them will not automatically lead you to the other. In order to use TDD effectively you need to know the concepts of software design and constantly keep them in your mind.

We think it might be worth to point out that time alone does not necessarily make you an experienced developer. It is possible to spend many years writing software and not gain a lot of knowledge or experience. Time and practice may make you experienced. Time alone doesn’t necessary lead to anything useful.

Tests would break encapsulation of a supporting framework

There is an ongoing debate about test-induced damage to the design. We can’t get rid of the feeling that this is an example of a design that could be improved and therefore allow testing.

An example is Rails and Active records that are supposed to be hard to test without breaking the encapsulation.


These are examples of when we probably would use evolutionary design.

Want to learn a new framework or API

When you are in learning mode you could consider to use a test as a starting point for running small portions of the system. It would be very much the same thing as implementing a main method from where you can perform small experiments.

If you instead execute parts from a test, then you are able to keep all experiments. After a while, when you know enough, you can consolidate the knowledge and probably throw away the experiments.


These are examples where we would recommend to use an evolutionary design.

You know you will do mistakes of a specific type

It is hard to come up with good examples. That is mainly because we seldom trust ourselves not to do silly mistakes. We make silly mistakes far too often to be sure when we wouldn’t make any.

Adrian Bolbocoa always uses an evolutionary design when he need to write queries to aggregate data from multiple tables; he always write tests there because he does a lot of mistakes. The queries can be sql, in Hibernate or any other pseudo-language.

Thomas Sundberg always uses an evolutionary design when he is working with regular expressions. His view is that if you have a problem and solves it using a regular expression, then you have two problems. Allowing the solution to grow using tests solves one of them.

You want to create a good design

You know the

  • Technology
  • Supporting frameworks
  • Test Driven Development, TDD
  • You don’t know exactly what the solution should be, at least not every detail

This is the preferred mode for most development. This is why some developers call TDD test-driven design.


Evolutionary design is a great tool in many situations. But even a great tool should not be used for everything. Always remember, if the only tool you have is a hammer, all problems will look like nails. Many problems can be converted to nails. Some problems are, however, never a nail and will therefore require a different set of tooling.

It takes experience to be able to allow a design to evolve and avoid taking premature design decisions. Just saying “Listen to the tests” is not always enough for creating a good design. This is especially true if you don’t know the difference between good and bad design.

A long experience as a developer doesn’t always help. Many experienced developers still take important design decision way too early in our opinion.

Evolutionary design is a learnable skill. A skill that requires training.

We think that

  • Evolutionary design
  • Emerging design
  • Incremental design
  • Just in time design

could be viewed as synonyms. They mean pretty much the same thing.


This blog post is written by Thomas Sundberg but he did not come up with all the examples himself. Adrian Bolbocoa is the co-creator of the initial thoughts for this blog post.


Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

%d bloggers like this: