From ThoughtfulReactionsToXp:
Not the most efficient way to write non-trivial software - system will take longer to build without up front design. In other words, God is faster and more to the point than evolution.
If I understand correctly a core idea of XP is not to attempt to predict the effects of changes to the requirements. In my experience that approach is very expensive. I agree that the full set of requirements will not be known when the software is being built. The preceding realization however, leads me in the opposite direction to XP in that I consider some form of up-front design which allows for a reasonable set of likely changes to be critical to the creation of non-trivial software.
Here's a concrete example: You have a system which needs to support 30+ reports. You decide to create a class whose responsibilities are to create the dataset needed by the report and to control the generation of the report using your programming platform's proprietary report system. You complete the class and create the required 30+ subclasses to implement the reports. Six months later you are informed that the reports must also be exportable as static hypertext and some need to be converted to text-merged documents. Unfortunately, your class is only designed to work with the proprietary reports. You are then faced with considerable work in addition to the creation of a new family of classes to handle different output types which you would have had to do anyway. Since you have changed the code you are faced with the necessity of regression testing the 30+ reports. A little up-front design would have revealed the likelihood of multiple output types, and suggested a design that separated the dataset generation and output responsibilities. In that case the new requirements would only require the creation of two new output classes.
The issue that XP doesn't seem to address is the progressively higher cost of changing a design. The example that I gave didn't even explicitly include changes to interfaces (which require that all client-code be changed and regression tested). In the initial concept stage change is very easy, after a real-world system has been created, the cost can be prohibitive. Some type of up-front design would seem like the best place to play a few what-if scenarios BEFORE the decisions are set in stone. On the other hand, perhaps decisions should NEVER be set in stone.
I like a number of the ideas in XP, but a complete lack of up-front design seems like the way most shops have been doing business for years, (and the results have not been pretty).
As this is my first exposure to the ideas of XP I may well have missed something. Clarifications and comments would be greatly appreciated. EdAmes
If you can predict what features the design needs to support, and you already know the best way to support those features in the design, and the cost of the extra design isn't excessive between now and when you start using it, the designing up front wins. By designing up front, you are betting on these things.
When you choose EvolutionaryDesign, you are betting the opposite way. You are betting that you might not know when you will have to support which features. You are betting that you might learn a better way to design between now and then. You are betting that going faster between now and then will pay off.
When I deliberately chose to give up designing up front, I did it a little at a time. I stopped looking two years ahead and only looked one year. My job got easier, I was more successful, now and later, and my designs improved. So I shrunk the horizon to six months. Then to two months. Then a week. Now I really truly design test case by test case. At each step, I went faster, with fewer mistakes, with cleaner designs, with less wasted effort, with less stress, with more flexibility.
Don't take EvolutionaryDesign on faith. Try the same experiment yourself. Deliberately leave out of your design a feature that is a little likely to fail one of the three tests. If that doesn't hurt you, raise the bar.
Or just jump in. You're going to have to evolve the design eventually. You may as well start the first day, when evolution is easy.
That's the real key: Most software systems will have to change. So build it so that it can change and take advantage of that flexibility by going "evolutionary" from the start. --KielHodges
We were discussing the book (ExtremeProgrammingExplainedEmbraceChange, KentBeck) yesterday, and it seems to several of us that it contains significant ambiguity on this topic. On the one hand, Kent describes doing the design as you implement each test case. On the other, he says that you should only do design until you start to ask interesting questions that are better answered in code. Then immediately write some code to explore the questions raised by the design.
In our practice, we do a little bit of designing as we implement each group of use cases. We walk through the use cases and employ CrcCards to sketch out the classes and responsibilities. (Remind me to tell you sometime how enthusiastic I am about CRC!) Then we want to get to writing code as quickly as possible. Within a given 8 week interval, we'll typically have at least two separate CRC sessions as we iterate through sets of use cases. We will typically produce a few class hierarchy and sequence diagrams to record the results of these sessions. But as JamesCollins has pointed out repeatedly, the experience of going through the design is much more important than the pictures produced at the end.
This allows us to bring the entire team to a shared understanding of the system design quickly. It also allows us to start validating the design (with real live code) as soon as possible. -- BillBarnett
My impression is that the gap between design and code can be narrowed using a design tool, like VAST UML Design, Rational Rose, or others. The purpose of any software development is to get to some final result. A crucial and not trivial step in the process is to understand, determine, describe, and analyze the requirements. The analysis should break down the requirements as much as possible into atomic parts. It is not necessary to do each step perfectly, but it should be the general direction. Once the analysis has produced enough material to get started with the design, the design tool helps organizing the different components and their relationships. It is from these relationships that the interfaces can be derived. Once this is done then coding is limited to filling the gaps and developing the necessary middleware to glue things together. As things progress, it may become relevant to iterate through the process, including the requirements, to introduce changes and refinements. -- VictorGoldberg?
Why is it necessary to design for more than one requirement at a time? The EvolutionaryDesign hypothesis is that the costs of designing ahead are greater than the benefits. Once you only have to design for the next requirement, you don't need a heavy tool to help you, you can effectively use powerful tools like little scraps of paper.
That said, there is great value in ensuring that everyone is on the same page WRT where the design seems to want to go next. I haven't ever used a team session only once a month, but I can imagine it working, as long as all the decisions made were acknowledged to be tentative until proven in code. --KentBeck
Kent, isn't one of your key points that, with the right practice, the cost of change can be substantially reduced? This make evolutionary development feasible because software is not really civil engineering. The value of up-front design is a function of the cost of change.
Victor, the DoIt team uses Rose -- very gently -- to capture some of our design decisions (after the fact), because it helps us easily produce pretty documentation. My experience, though, is that Rose wants to suck you into using it for much, much more. If you use it to drive the whole design process, you can become so enamored with the pictures and models (and the pretty documentation you produce) that you miss the fact that the design is over-complicated or just not very good. It tricks an individual designer into creating frameworks and interactions far beyond what are required by the current requirement. It is sort of the same way I feel about heavy project management tools (like MS Project). They are OK as far as they go, but they seduce you into using all these fancy features, and give you a false sense of control over the project.
By deliberately using simple tools (like CRC cards or a WorkQueueReport?) we help to keep from fooling ourselves with these sorts of illusions.
By requiring the team to focus on just designing the next "chunk" of functionality for the system, we keep from running off and getting emotionally invested in an elaborate object framework that we "just know" we'll need later.
By using a ResponsibilityDrivenDesign techniques, and running all design sessions as highly collaborative team efforts, we exert enormous pressure to keep the system as simple and efficient as possible.
By making sure that we get the object model "right" through these practices, we ensure that we limit the scope of even dramatic changes in the future.
That is what makes evolutionary design work for us. -- BillBarnett
How do you balance minimal up front design with the need to make build versus buy decisions?
Our current project actually does involve report generation. The highest priority item, generation of a very specific report, once a month, in HTML format, would tilt the project towards build all parts. Looking at multiple reports, using multiple formats, tilts the project towards using a COTS (commercial off-the-shelf) software package as the basic engine. Trade-off analysis of the different packages involves mainly evaluation of possible future benefits.
It is quite expensive to 'refactor' to a different commercial package, both in terms of API changes and in having to explain to the customer why we told him last week to buy one package and now we want to scrap it and buy a different one.
Does evolutionary design presuppose all code will be developed from scratch?
Wayne- You said "It is quite expensive to 'refactor' to a different commercial package..." and "...report... in HTML format...build all parts." These two seem to be talking about different situations.
In you situation, I would build the HTML reports by hand. When the time came for the commercial package, I would put an adapter layer on the package that made it look like my home-grown package. Then I would slowly evolve towards the "native" API, if I liked it better or needed more of its functionality surfaced. I would also look at my favorite commercial report generator for API ideas (metaphors). --KentBeck
Since I originally wrote this, I have seen our development evolve much like Kent suggested. Our problems arose from committing to a commercial package too early, before we (and the customer) understood the more subtle details of what was needed. I would answer my original question with a qualified "Yes, start developing code from scratch, but evolve to more complete commercial packages when (and only when) necessary." There is a great deal of benefit to testing the waters with a minimal home grown solution before jumping to a full featured commercial package. --WayneMack
The principle of DesignDecisionDeferment? is an important practice in XP. We should try to delay any decision until we are able to make it. We could use the ShieldPattern in any of its faces to lower or eliminate the impact of that delay.