|Exampler.com||Driving Software Projects with Examples
Consulting, training, and writing from Brian Marick
This is a
Thu Sep 23 16:55:41 CDT 2004
Commentary: Key Themes
Talking and showing are the key joint acts
One thing I hope you noticed in the story was that everyone was always jabbering to each other about the product. That's a characteristic of Agile projects, and the use of examples changes nothing about that. As before, the main way that programmers learn what the product owner wants is through conversation. The main way the programmers learn what each other knows is also through conversation.
Conversations work better when people can point at something and say, "See? There. That's what I mean." That's one of the reasons that Agile methodologies emphasize frequent iterations that produce deployable business value. The team can show everyone with a stake in the product what they've gotten for the last iteration's money, and then they can all talk about what would make sense to do next.
Examples are something you can point at early in a task. They help people navigate between the concrete and the abstract, between discussing specifically what the product should do and why it should do it. With examples, the programmer can most efficiently learn what code to write.
Examples are not requirements
Requirements, as used in software engineering, are written descriptions of what must be true for a problem to be solved. Requirements documents aim toward an ideal in which the text contains all the background knowledge required to interpret it, and in which any competent technologist would interpret the document the same way.
Examples explicitly do not aim for the same ideal. The examples are not intended to be understood outside the conversation that surrounded their creation and use. If knowledge is to be transmitted outside the team, either a team member must accompany the examples or the team will have to write commentaries on them. Those commentaries might look like shorter versions of a requirements document. Should I have a chapter about that?
Examples maintain programming pace
Once the conversation that creates the example is finished, the programmer uses them as a guide to what to do next. A programming task consists of getting more and more of the task's guiding examples working, step by small step. The programmer also uses the examples to check that the latest small step hasn't broken anything that used to work.
That's not to say that business-facing examples created with the product owner are the only examples programmers use. As we saw in the story, programmers may create more localized examples to help them break specific subtasks into manageable pieces (or for other reasons, such as designing internal programmatic structures). But it is to say that part of the art of creating examples is to create ones that lend themselves to this piecewise development.
I want to emphasize this point strongly: when the programmers do not see the business-facing examples as helping them code, that starts a vicious negative feedback loop that will sap the substance, though maybe not the form, of example-driven development.
Examples must be speedy
Programmers will not see examples as helping them code unless feedback is fast. Programmers want to ask the computer two questions frequently: "What I just did - did it make forward progress?" and "Did I break anything that used to work?" If the computer is too slow at answering, programmers will stop asking and the examples will have then lost an enormous amount of their value.
Examples signal task completion
Once all the task's examples work - including new ones created during the task - the programmer is finished and can move on to a new task.
For that to work, the product owner has to be justifiably confident that finishing a task's examples means that her vision has been adequately realized, the programmers have done their job, and the new business value could be deployed. Without this confidence, tasks the programmer considers finished will have to be revisited, and that's constant sand in the gears of the project.
I say that such sets of examples have breadth. Broad sets of examples, together with the good programming practices of chapter whatever, produce working, extensible code. We'll talk a lot about how to achieve breadth. But note here that it's easy to overwhelm programmers with a broad and dense set of examples that ruin pacing, that don't allow the programmer to proceed in small, intellectually controllable steps. We saw that in the story. Sophie's desire to cover all the relevant combinations of orders - to produce one example with a lot of breadth - got in Paul's way. They would have been better off starting off with the four simpler examples.
Lean toward "just in time" examples.
Or perhaps Paul and Sophie should have started with one example, the simplest. A way to keep examples from being overwhelming is to produce them one at a time, each one coming into being just as a programmer needs it. That way, it can be made to both contribute to breadth and also help the programmer proceed in a convenient direction. We saw this in the story, where Paul's objection to the large example was guided by his current idea of a good sequence of coding subtasks.
But, again, there's a balancing act. Discussion of early examples allows the whole team to better understand the scope of a task. If examples are deferred until programming, programmer estimates will be worse and therefore the product owner will select the wrong tasks for the iteration. Had Paul estimated without a worked-through example of a lactating animal in intensive care, he would have missed the connection between caretaker and student milking, he would have underestimated the programming needed, and the team would have been sad that the task took longer than they said it would. So a team has to learn how many, and what kind of, examples should be done in up-front iteration planning and which are best deferred. Paul and Sophie had thought that the original complex example was all they needed for estimation; they deferred creation of others. As it turns out they were right. The estimate was good even though they broke up the example into simpler ones along the way.
The examples are revisable
The bitter phrase, "there's never enough time to do it right, but there's always time to do it over" is true in agile projects, but true in an unexpected way.
We saw Paul and Sophie take a "finished" example and rip it apart into four. That's absolutely typical. Paul needs to learn to be a bit more carefree about throwing away work, including throwing away finished examples.
Why is Paul afraid of throwing away work? It might be because he thinks they should have gotten it right the first time. But in Agile projects, it ought to be faster, on average, to get something wrong and fix it than to think harder and get it right the first time. If it's not, change your practices, your tools, and the code so that it is.
No one "owns" examples
When an example changes during a task, people should worry. Is the example still a true description of how the system is to behave? Has some nuance been lost?
Ideally, the product owner would be instantly available to rule on each revised or new example. Most, like Dr. Morin, will be unavailable a lot of the time. The team can either go ahead with an unchecked example (and bring it to the product owner later) or wait on the product owner. They should go ahead. A project should err on the side of action, not on the side of waiting.
More generally, in no case should anyone be a bottleneck because she "owns" an example and is the only one allowed to change it. Change is good, so long as it's done with due care. (Due care usually means getting someone else's eyes on it.)
In many teams, team members will develop enough understanding of the domain that the product owner won't want to bother checking all their examples. She'll trust them to get the safer examples right often enough enough, and to know when they don't know enough to proceed without her. She might well delegate decision-making authority to someone on the team (often the tester).
The examples are wrong. So?
The examples will never have perfect breadth. There will always be glitches. Because the team is made of imperfect people with imperfect knowledge, they'll overlook real-life examples of use. It may even be, as we saw in the story, that the task was somewhat misconceived. But it should be rare that such problems, once discovered, prevent deployment of a new bit of business value that the team is proud of and that the users welcome as an improvement.
If it's not rare enough, the team has a problem to solve. They can improve their example-creation skill, improve on exploration (so that problems are still discovered within the iteration), increase the amount of after-iteration testing, and - least desirable, because slowest - increase the amount and quality of feedback gotten from the user community. The best team members get excited by opportunites to hone their craft.
It's fine to fix the process, but what about the immediate problems caused by a wrong example? They should be exactly as big a deal as the product owner changing her mind, a new requirement arriving, or an old requirement changing. That is, not a big deal. The whole aim of the Agile methods is to make change a normal and untheatening part of work, and these problems are just one more cause of change. Small glitches can be fixed within the iteration. Greater changes get scheduled as tasks for later iterations.
Exploration jerks the team out of itself
One reason examples go wrong is that the product owner doesn't know enough. Another is that she knows too much - she's been immersed in the product for so long that she knows things about it that no user would know. She cannot help but know things about how the product works internally and how it should be used. Over time, she becomes a worse representative of the users, at least at the detailed level. She joins in the groupthink that inevitably overtakes a small, jelled, colocated team.
How do you get out of a rut? You make a sharp, firm turn. In the software realm that means consciously using the software in a different way than normal. For this reason, I advocate deliberate, focused exploration of the actual use of the software. By doing different things than talking about examples and coding, you start to see different things. That's especially true when you consciously adopt a different persona, or when you pair up with someone not from the team. Making the exploration part of an end-of-iteration ritual emphasizes that the whole team is take a different stance.
Although our team's first example was too complex, they did several things right:
Why is style important? Business processes - all human processes, actually - are full of tacit knowledge and unwritten rules. It's the team's job to make all that explicit enough for a computer. The story of a project is, in part, the story of a bunch of people making sense of a domain. A lot of that is developing a common language in which to talk about the domain. Concise examples that use that language make the learning faster.
Copyright (©) 2004 by Brian Marick. Permission granted to copy for personal use only. If you quote this, please identify it as a draft.
Comments to firstname.lastname@example.org