The Scatology of Agile Architecture 24
One of the more insidious and persistent myths of agile development is that up-front architecture and design are bad; that you should never spend time up front making architectural decisions. That instead you should evolve your architecture and design from nothing, one test-case at a time.
Pardon me, but that’s Horse Shit.
This myth is not part of agile at all. Rather it is an hyper-zealous response to the real Agile proscription of Big Design Up Front (BDUF). There should be no doubt that BDUF is harmful. It makes no sense at all for designers and architects to spend month after month spinning system designs based on a daisy-chain of untested hypotheses. To paraphrase John Gall: Complex systems designed from scratch never work.
However, there are architectural issues that need to be resolved up front. There are design decisions that must be made early. It is possible to code yourself into a very nasty cul-de-sac that you might avoid with a little forethought.
Notice the emphasis on size here. Size matters! ‘B’ is bad, but ‘L’ is good. Indeed, LDUF is absolutely essential.
How big are these B’s and L’s? It depends on the size of the project of course. For most projects of moderate size I think a few days ought to be sufficient to think through the most important architectural issues and start testing them with iterations. On the other hand, for very large projects, I seen nothing wrong with spending anywhere from a week to even a month, thinking through architectural issues.
In some circles this early spate of architectural thought is called Iteration 0. The goal is to make sure you’ve got your ducks in a row before you go off half-cocked and code yourself into a nightmare.
When I work on FitNesse, I spend a lot of time thinking about how I should implement a new feature. For most features I spend an hour or two considering alternative implementations. For larger features I’ve spent one or two days batting notions back and forth. There have been times when I’ve even drawn UML diagrams.
On the other hand, I don’t allow those early design plans to dominate once I start TDDing. Often enough the TDD process leads me in a direction different from those plans. That’s OK, I’m glad I made those earlier plans. Even if I don’t follow them they helped me to understand and constrain the problem. They gave me the context to evaluate the new solution that TDD helped me to discover. To paraphrase Eisenhower: Individual plans may not turn out to be helpful, but the act of planning is always indispensable.
So here’s the bottom line. If you are working in an Agile team, don’t feel guilty about taking a day or two to think some issues through. Indeed, feel guilty if you don’t take a little time to think things through. Don’t feel that TDD is the only way to design. On the other hand, don’t let yourself get too vested in your designs. Allow TDD to change your plans if it leads you in a different direction.

LDUF – Brilliant – that’s going straight in my acronym bag.
Thanks, Bob. I’m glad you mention this. It’s useful to spend some “UML Design” time before diving into solving a new user story, with the motto “We’re doing design, the design is wrong, and that’s ok”.
Eivind wrote:
I’ve heard people refer to things like this as:I like that. As Bob mentioned (from Eisenhower): the plan is nothing, planning is everything. Feedback provides orientation. So we need to find a balance between planning and sticking our heads up out of our gopher holes to get some feedback.
Hi Uncle Bob,
Always looking forward to your next post. Any thoughts about the following?
In Extreme Programming Explained – Embrace Change 2nd Ed, Kent Beck says:
... ...Here is my attempt to reproduce three of his graphs:
Purely instinctive design is sufficient
Some design thought or experience is necessary
No amount of pure thought will suffice
Ah yes – I totally agree but you have triggered me to pose a question. First a little context. During this past week my software design course discussed the “Big Ball of Mud” paper by Foote and Yoder [http://www.laputan.org/mud/].
On page 10 the following is stated:
“When it comes to software architecture, form follows function. Here we mean “follows” not in the traditional sense of dictating function. Instead, we mean that the distinct identities of the system’s architectural elements often don’t start to emerge until after the code is working.”
In your discussion, you stated:
“However, there are architectural issues that need to be resolved up front. There are design decisions that must be made early.”
Are you using architecture and design in these two sentences to mean the same thing?
Is there a need to define a word for the structure that we create when beginning the design versus a word for the structure we achieve when we refactor? – after gaining more knowledge about the domain and how the software works?
@Uncle Bob
You said: One of the more insidious and persistent myths of agile development is that up-front architecture and design are bad; that you should never spend time up front making architectural decisions. That instead you should evolve your architecture and design from nothing, one test-case at a time.
In Extreme Programming Refactored: The Case Against XP, the authors kick off the chapter on Emergent Architecture and Design by juxtaposing two carefully chosen extracts (attributed to Ron Jeffries) from Extreme Programming Installed:
From Extreme Programming Refactored: The Case Against XP:
In my mind Agile means “reducing the costs of mistakes”
As it applies to design; this means if you designed the wrong thing, or just neglected that part of the design, that’s ok. it can be refactored to the right design cheaply.
It this refactoring that allows for ‘emergent design’.
Nowhere have I seen something that advocates actively making mistakes over not making mistakes, unless the cost of not making the mistake is higher than the cost of mistake.
In other words, do not pay $10 to insure a $9 item.
And this is where my ‘gut’ kicks in. If I can code something in 5 minutes, or talk about it for 20, let’s code. If it’s going to take a day to code, let’s talk about it.
I have told people this for years:
You will probably start practising “test-first programming”, which I say to mean drawing your detailed design up front, then using tests to ensure you type in your design correctly. Soon you’ll begin to notice that making tests pass causes you to change some of the design you’d diagrammed. When that happens, try not designing that kind of thing up front next time. Over time, you’ll find you need less and less design up front. You might even experiment with doing no design up front and seeing what that teaches you about how little design you can get away with. At equilibrium, you’ll find the right amount of up-front design for you.
I ask you and everyone else: do we need any more than that, really?
I really believe J. B. Rainsberger hit the nail on the head. It comes down to skill and experience. If I am on a team of highly skilled developers with plenty of experience then a solid design would probably evolve from doing a form of behavior driven development with very little if any design up front. It is all about communication! I cannot stress that enough, collaboration is huge especially the early stages of a sprint.
If one is not fortunate enough to work on a full team of skilled developers with plenty of test driven experience (which is often the case), then yes I agree some guidance is very important.
But I see too often how just doing a little “architecture” can lead to massive over-engineering and end up costing the project a lot of time and money.
I am currently working on a project where there was a lot of design that went on yet the architecture has some serious problems. So yet again I argue that it comes down to the skill and experience of your developers.
As in many situations in life there can hardly be a clear cut rule saying “thou shalt not make upfront architecture/design”.
It simply depends. On the problem, on the (technical and probably even more on the soft) skills of the team, on the domain, on the company’s culture etc.
I’ve been both in situations where I wondered a) why we took so long discussing about the architecture when a few days implementation showed how vain our efforts were or b) why we didn’t take a bit more time to get a common understanding of the prospective architecture/design as it would quite certainly have saved us much “coding into a dead end” and the subsequent refactorings.
At the end of the day though I’d agree with J.B. – but probably primarily because I’ve so far always been working in companies where there was some sort of upfront architecture/design “holy cow” and I hardly ever had the feeling that the result of that upfront effort was really worth it. And JEDI sounds marvelous – if we only could measure “just enough”...
And definitely yes: the upfront architect/design can be no more than a first attempt, an initial guidance, that has to adapt to the stubborn facts of testing/implementing. Architecture/design are living things – not sentences written/pictures drawn in a document.
The software architect (I think we need this role – I wonder what’s the feeling of the commenters and readers of this column BTW) is in this context a person who has the skills and the will to prevent things from getting out of hand and keep the whole software “consistent” (avoiding design island that can hardly communicate with each other or even competing architectures fighting each other until someone throws the towel…).
The core message of Agile for me is “Think for yourself, communicate, take responsibility and be willing to learn” – but that’s of course only one of billions of possible interpretations. Starting from there anything goes, depending on the concrete context – though some paths certainly look more promising than others…
Uncle Bob said: Size matters! ‘B’ is bad, but ‘L’ is good. Indeed, LDUF is absolutely essential. How big are these B’s and L’s?
What do people think about what Martin Fowler said in this interview:
Hi Bob,
You said: There are design decisions that must be made early. It is possible to code yourself into a very nasty cul-de-sac that you might avoid with a little forethought.
Does your LDUF typically cover some or all of the FURPS+ -ilities of a system? Does it cover infrastructure? e.g. How aggressive an XPer are you?...do you sometimes delay putting in a database until you really know you’ll need it? Or do you work with files first and refactor the database in during a later iteration?
Do you consider security, transactions, and internationalisation as hard problems that require up-front design, or do you sometime refactor them in later?
For the benefit of less experienced readers (if any), let me provide some background with excerpts from various sources…
From Capturing Architectural Requirements:
Craig Larman in Applying UML and Patterns : an introduction to object-oriented analysis and design and the Unified Process – 2nd Ed
Martin Fowler in Is Design Dead? (last significant update: 2004):
Ron Jeffries in XP Installed (2000):
From Extreme Programming Refactored: The Case Against XP:
From Jim Shore’s 2004 article Continuous Design:
One thing that I do not see is why we would imagine that less-qualified people would do better with up-front design unsupported by code. They are relatively clueless. Their ideas are more suspect, not less.
I think about design all the time. Almost always before starting something, I think about design and enjoy talking about it. At the same time, I’ve been designing for a half-century and my thoughts about design are pretty well-informed. Even so, I discover almost invariably that my thoughts aren’t good enough and that important things have eluded me.
I do not conclude from that that I should do more up front design, or try harder. I conclude that I should find out what the code thinks as soon as I can.
If I were less skilled at design than I am, why should I speculate longer?
Each of the issues you have brought up was something we encountered in FitNesse. In each case we deferred the decision until necessary. In the case of the database, we found we didn’t need one and simply left the file system approach in place. Security, transactions, and internationalization were all left till later, and have caused no particular difficulty.
OTOH I think we made a fundamental error in FitNesse by using regular expressions to parse the wiki text. This decision was easy to make, and has supported FitNesse for years; and yet has always been an impedance. That impedance has grown significantly and has finally become a fairly large problem.
In most cases I’d say that the early benefit we got by using regexp was the right trade off to make. However, in this case it would have cost us very little to put in a LALR parser (like ANTLR or something). That would have saved us a lot of fussing around and I would not now be facing the prospect of ripping out the whole parser and rewriting it.
Great post and I agree – a responsible amount of design up front is not only prudent it can significantly mitigate risk the system doesn’t meet some required quality levels. But “design” must not only include what runs in the JVM / CLR, it must include the “whole system”.
In my experience, the biggest area architects (agile or not) too often ignore are the system qualities (throughput, scalability, maintainability, portability, recoverability, etc.). These aren’t merely acceptance criteria on user stories, they need to be defined and managed with the architecture – otherwise a designer is not sure what levels the system must meet (and the stakeholders are willing to pay for).
I’ve proposed a way to do this in my Agile Engineering for Architects presentation ( http://bit.ly/wlBre). It’s based upon Tom Gilb’s wonderful work on quantification of system requirements (http://www.gilb.com). You don’t have to do Big Upfront Design – but you must quantify the key system qualities and explore how design ideas will help meet these levels.
IMO, architects must be actively involved in both defining qualities AND designing to meet them. Doing this before iterating and writing code, as described in your post, would be the perfect time for this.
I can certainly attest that the code we’ve written after a short design session was orders of magnitude cleaner than the code we simply tried to TDD. And the code we “tested after” was even less clean. I can also attest that the longer the design session goes, the farther from the reality of the system it gets. I agree with Ron that we should design all the time. You are correct that too many Agile projects assume no design and the design will take care of itself.
As far as how big ‘L’ is, I like the distance analogy. If the perceived end of the project is 9 months away, architect to the level of detail that you can ‘see’ from that far away. If it’s 6 months, add more detail, if it’s 12 months add less. Always always always revisit the architecture. Revisit the design.
Evolutionary design means the design evolves from constant attention, not that the system will just design itself if we do A, B, and C really really well.
Philip,
What is your secret to quoting so many books? Are you a human being or a markov chain algorithm running as a background process on Bill Gates’ personal supercomputer?
@John Zabroski
I’ll take that as a compliment.
I am afraid there is no secret: I just spend too much money on books, and too much time reading them; the rest, as explained by Andy Hunt in Pragmatic Thinking & Learning – Refactor Your Wetware, is done by my standard-issue R-mode CPU:
It is a compliment. You should set-up a tumblelog where you backtrack link-to all the blog comments you make and book references. It is then an informal, ad-hoc book review system.
I do read a lot, too, but your synthesizing skills are off the charts.
Sir, why are you being called “Uncle Bob”? Is there a story behind it? Didn’t find anything on the Web or your Wikipedia article. Thank you for a brief explanation.
??? ? ?? ? ?? ??
Erik said the following:
“The software architect (I think we need this role – I wonder what’s the feeling of the commenters and readers of this column BTW) is in this context a person who has the skills and the will to prevent things from getting out of hand and keep the whole software “consistent” (avoiding design island that can hardly communicate with each other or even competing architectures fighting each other until someone throws the towel…).”
a while back.
Isn’t figuring out what the “design islands to avoid” about the system architecture in general. For example we generally know that it is a “good idea” to use certain kinds of patterns – generally like loose coupling, generally like the ability to scale components independently – we have seen mainframe monoliths where to get mode DB performance we need a fork lift upgrade. So there are whole lot of principles that good designers/architects/developers have in their hip pockets. As we put these things together we have, guess what, an ARCHITECTURE. It’s probably a good idea to get that stuff done up front so we all know what principles we are espousing.
Eventually the software we build will have to be in production (no snide comments about canceled projects here!). One principle we developers need to espouse is a principle that makes the solution resilient enough for its production environment. Knowing the desired resilience affects/constrains design/architecture. My quick Sudoku solver is rather different from software that controls a heart monitor.
I love the LDUF and absoulutely agree that the size of the L is rather important. There is an essence that we need up front. The challenge is getting it right. The Goldilocks principle seems to be a nice way to look at it.
Great to know Uncle Bob thinks similar about that myth. I did touch somehow the topic of design’s bad name in Agile in a post: The Agile missing point and the Waterfall Illusion
There is Design as a Documentation Excercise, and Design as Coding. (actually, I’m polishing another post about coding vrs development where I mention Just code is not the solution)
Coding to me is the actual description of the solution in a language, not necessarily executable.
Now, you can describe the solution at strategic, tactical and operational levels. The last one is executable code.
That means, Design should be done at tactical level, where you decide if using message queues or RPC, not at operational level where you decide if using an if or a switch. If a Design description reassembles every line of code to be written, is a totally non-sense. They should be at different abstraction levels
The people that thinks design is documentation, are way-off. People that think design is coding at early stage, should focus on a tactical view of the situation, with major classes and important relations, not all the classes and interfaces.
Design is always revisited. Do design to start operational coding, and then do more design or adjust the old one based on operational coding output.
Another point: Moving design around makes no sense at all. If you read my post, there is not way to make design after operational coding. You just chop design and do so little before coding one line, that looses its strength. You just made a waterfall into a rain. But water still falls. In other words, design does not got out of code (maybe documentation does), design is created before operational coding in little chunks, and documented after-wards.