Evolutionary Design

  • Emergent Design (Jeffries)
  • Incremental Design (Extreme Programming Explained, 2nd edition)
  • Simple Design (Refactoring)
  • YAGNI (Refactoring)


Is Design Dead?

Use of the term “evolutionary design:”

XP has rejuvenated the notion of evolutionary design with practices that allow evolution to become a viable design strategy.

Extreme Programming Explained, 1st Edition

Ch 17, Design Strategy

The design strategy in XP is to always have the simplest design that runs the current test suite.

…The principles also work into the design strategy.

  • Small initial investment—We should make the smallest possible investment in the design before getting payback for it.
  • Assume simplicity—We should assume that the simplest design we can imagine possibly working actually will work. This would give us time to do a thorough job in case is simplest design doesn’t work. In the meantime, we won’t have to carry along the cost of extra complexity.
  • Incremental change—The design strategy will work by gradual change. We’ll design a little at a time. There will never be a time where the system “is designed.” It will always be subject to change, although there will be parts the system that remain quiet for a while.
  • Travel light—The design strategy should produce no “extra” design. There should be enough to suit our current purposes (the need to do quality work), but no more. If we embrace change, we will be willing to start simple and continually refine.

Extreme Programming Explained, 2nd Edition

Incremental Design

Invest in the design of the system every day. Strive to make the design of the system an excellent fit for the needs of the system that day. When your understanding of the best possible design leaps forward, work gradually but persistently to bring the design back into alignment with your understanding.

Jeffries, Emergent Design

I’m suggesting that a few very simple rules can bring about good design. I’m suggesting that good design is an emergent property, given the application of these simple rules.

Understanding the Four Rules of Simple Design

Simple design, though, is one that is easy to change. Striving for a simple design — one that is adaptable to changing needs — is the key to a “better design.” Whenever we have a choice to make, look for the choice which would be easier to change.

Fowler, Refactoring

The real impact of refactoring on architecture is in how it can be used to form a well-designed code base that can respond gracefully to changing needs. The biggest issue with finishing architecture before coding is that such an approach assumes the requirements for the software can be understood early on. But experience shows that this is often, even usually, an unachievable goal. Repeatedly, I saw people only understand what they really needed from software once they’d had a chance to use it, and saw the impact it made to their work.

One way of dealing with future changes is to put flexibility mechanisms into the software. As I write some function, I can see that it has a general applicability. To handle the different circumstances that I anticipate it to be used in, I can see a dozen parameters I could add to that function. These parameters are flexibility mechanisms—and, like most mechanisms, they are not a free lunch. Adding all those parameters complicates the function for the one case it’s used right now. If I miss a parameter, all the parameterization I have added makes it harder for me to add more. I find I often get my flexibility mechanisms wrong—either because the changing needs didn’t work out the way I expected or my mechanism design was faulty. Once I take all that into account, most of the time my flexibility mechanisms actually slow down my ability to react to change.

With refactoring, I can use a different strategy. Instead of speculating on what flexibility I will need in the future and what mechanisms will best enable that, I build software that solves only the currently understood needs, but I make this software excellently designed for those needs. As my understanding of the users’ needs changes, I use refactoring to adapt the architecture to those new demands. I can happily include mechanisms that don’t increase complexity (such as small, well-named functions) but any flexibility that complicates the software has to prove itself before I include it. If I don’t have different values for a parameter from the callers, I don’t add it to the parameter list. Should the time come that I need to add it, then Parameterize Function is an easy refactoring to apply. I often find it useful to estimate how hard it would be to use refactoring later to support an anticipated change. Only if I can see that it would be substantially harder to refactor later do I consider adding a flexibility mechanism now.

This approach to design goes under various names: simple design, incremental design, or yagni (originally an acronym for “you aren’t going to need it”). Yagni doesn’t imply that architectural thinking disappears, although it is sometimes naively applied that way. I think of yagni as a different style of incorporating architecture and design into the development process—a style that isn’t credible without the foundation of refactoring.

The Art of Agile Development, 2nd Edition

  • Ch. 14: Design

The practices in this chapter are based on Extreme Programming’s approach to design. In the conversation surrounding XP, it was called “evolutionary design,” which is the umbrella term I’m using here. Kent Beck called it Simple Design in the first edition of XP [Beck2000a] and Incremental Design in the second [Beck2004].