|Exampler.com||Driving Software Projects with Examples
Consulting, training, and writing from Brian Marick
This is a
Thu Sep 23 16:59:11 CDT 2004
An Introduction, By Way of Example
Here is a story, a fiction, that illustrates the style of project I'm promoting in this book. The next chapter is a commentary on the example. I suggest you make your own commentary by scribbling some notes. How does yours compare to mine?
CFARMS is a project for the Food Animal Reproduction, Medicine, and Surgery department of a major midwestern College of Veterinary Medicine. It aims to automate the operations and recordkeeping of a veterinary clinic, namely the college's teaching hospital.
The project is being run in an Agile style: two-week iterations, heavily test-first, a bullpen (just off the clinic floor), some pair programming, daily standup meetings. Most importantly, there is an on-site customer. Well, sort of. The customer is Dr. Morin, who runs the clinic. She's around most of the time, but she's greatly overworked. So she zooms from place to place and the team catches her when they can.
Note: In final draft, common practices will be explained in an appendix, pointed to by a footnote in the above paragraph.
Because Dr. Morin can't devote the ideal amount of time to the project, the team makes a special effort to learn how the clinic works. Sophie, the tester and project lead, makes a point of bringing donuts to the students in the on-call room every few evenings, and the whole team participates in the end-of-rotation Friday cookout (although half of them skipped out on the yearly Testicle Festival, about which the less said the better).
The team has settled into a habit of doing a bit of planning for the next iteration toward the end of the previous one. At times when Dr. Morin is available, Sophie grabs her and a developer or two to talk about the most likely stories for the next iteration. By doing that, they keep the iteration planning meeting crisp (though it does cause some loss of group understanding).
Planning a Feature
As we begin the story, Dr. Morin, Sophie, and Paul (a programmer) are gathered near the whiteboard in the records room. Dr. Morin says she wants the ability to print out a daily schedule for the students. When Paul asks what she means, she says, "You know that some orders turn into student and caretaker tasks - we already implemented that. But the tasks aren't always done by the student assigned to the case. If there's a 3 a.m. milking, it's the student on call who does it. So what I want is a printable page that shows all the tasks to be done by some student that day. We'll print it at 8 in the morning, when the students do their SOAPs." (Everyone on the team knows that SOAP stands for "subjective/objective assessment and plan"; each student 'soaps' her animal first thing in the morning.)
After Dr. Morin finishes, Sophie steps to the whiteboard and starts sketching a table that seems to capture what the Doctor ordered. After some discussion, it looks like Figure 1.
The snippet of conversation that led up to the "NOT at 6 - caretakers" annotation proves particularly useful to Paul. Sophie had originally written a row that showed the student milking the cow at 6 p.m., but Dr. Morin pointed out that caretakers milk all lactating cows at 6 a.m. and 6 p.m., so the students get those milkings off. Until that moment, Paul had been thinking that the implementation would be completely trivial, but now he realizes there's an interaction between caretaker and student tasks. He drifts off into thoughts of the code while the other two talk, realizes that he isn't quite sure how to connect the two kinds of task, and mentally ups his time estimate for the work.
They've spent seven minutes on the feature. Dr. Morin turns to Paul and says, "I'm thinking this has got to be pretty easy, right?" Her intent isn't to pressure him, but rather to conserve her time. If it now appears this feature will be hard, she'll cut the conversation short because she won't want to pay for this feature in the next iteration.
Even with the caretaker/student interaction, Paul expects that it ought to be straightforward, so he nods. He knows he'll get a chance to make a better estimate later. So they talk a bit more about the feature while Dr. Morin spoons her lunchtime yogurt into her mouth with a tongue depresser. When she's done, she tosses the tongue depresser in the trash and zooms off, mentioning on the way out the door that she'll also want a schedule for the caretakers.
Sophie goes off and conjures up a sample schedule (Figure 2) that looks a lot like the whiteboard sketch. It differs in two ways. First, it's computer-readable, not just human-readable. Second, it's more thorough, because it covers each of the ways orders turn into tasks for students. From past experience, Sophie knows that means four patients: one that requires nothing special, one that's been ordered into intensive care, one for which milking has been ordered, and one for which both intensive care and milking have been ordered. To keep the cows straight, Sophie gives them atypical names: Nothing, Only Care, Only Milk, and Both.
Figure 2: The information in a daily schedule.
At this point, Sophie knows what she means by the four cases, but the computer can't. That means the example as it stands can't check the code against itself. So Sophie next creates a description of the four patients, putting that table (Figure 3) before the one in Figure 2. She uses a notation they developed several weeks ago for another task. It describes the steps a clinician uses to enter a case into the system and give a starting set of orders.
Figure 3: Describing a caseload.
Sophie knows Dr. Morin wants a schedule for caretakers, but she doesn't feel she knows enough even to try creating a descriptive table. So she puts it off.
That's all she does on this new feature before the iteration planning meeting on Monday. She might have liked to have shown her example to Dr. Morin before then, but there wasn't a chance.
When the feature comes up at the meeting, Sophie displays her example on the wall. The team doesn't pay much attention to it - the emphasis of the conversation is on what Dr. Morin wants, not on the table - but Sophie's learned that sometimes having an example to gesture at helps maintain focus. As it happens, Dr. Morin quickly notices that the second table (the one in Figure 2) is wrong. "Students," she explains, "always take the animal's temperature when they SOAP it, so don't put it on the schedule at 8, just at the other three times of the day."
Dr. Morin and the programmers soon agree that they understand the feature. They spend a few minutes talking about what the actual display should look like, but not much: they expect fiddling with layout when the time comes. They also discuss what a caretaker's schedule should look like. As it turns out, they can't think of anything a computer could do that would be better than what the students and clinicians do now, which is to stick instructions like "NO FEED" into the card slot on each stall. So they drop that part of the idea.
Having done all that, the programmers feel pretty confident that they know how much work the feature will require. At the end of the meeting, Dr. Morin decides she's willing to pay for that work, so the feature is scheduled into the iteration.
Paul will be doing most of the implementation for this feature, occasionally working with another programmer, Kendall. There are two parts to the task. The first is getting the business logic right: making sure the program is correct about what happens when. The second is to hook that logic up to the user interface. Paul has a free choice about which to tackle first. Quite often, he interleaves the two. For example, he might do the logic behind a button, then the button itself, then move to the next button. This time, he doesn't want to start the GUI until he can spend some sketching time with Dr. Morin. Since other programmers need her time more, he'll start by working exclusively on the business logic.
He can think about those tasks separately because the system is structured as shown in Figure 4. There are two ways in the system to activate the business logic. In the first way, a chunk of code called "the GUI" translates from the language of screens and button clicks into the language of the business logic. In the second way, code called "a fixture" translates from the language of examples to the language of the business logic. Since examples don't use the GUI, Paul can ignore it as he uses them to guide him as he writes code.
Paul proceeds in a highly iterative style. He starts by asking the computer to tell him how Sophie's example matches the code. It says "not at all" by coloring all the rows of Figure 2's table red. (Because this book is printed in black and white, I can't show you that.) Paul's first goal is to write just enough code to make the first row of the table "go green" next time he asks the computer.
It might seem that it would be just as easy to get the first four rows green as the first one. After all, all four cases have exactly the same 8 a.m. tasks. But not so: four rows is actually a little extra work, work that builds on the work required for the first row. Paul, like many programmers, would rather get feedback on step A before starting even a simple step B. Since it takes him only three keystrokes and a few seconds to get feedback, he codes up the two steps separately.
Paul loves working in small steps, getting feedback every few minutes. Sometimes it's more than a few minutes' worth of code to make a row green. When he sees that happening, he breaks the problem into subproblems, each described by an example. These latter examples are written in a different format (the Java programming language and a tool named JUnit), but they serve the same purpose of making his progress steady and visible.
But midway through making the milking schedule work, Paul finds himself getting annoyed. Things are not going as smoothly as they should. Rather than bulling through the difficulty, he calls over Sophie, who's sitting two chairs away at the moment. "Soph, this example is making me pay attention to too many things at once. Maybe I should leave it aside and just write JUnit tests."
"What kind?" Sophie asks.
"Well, I think I'd just pick the 'Nothing' case to get SOAPs working - actually, that's already working - and then tack on an example of SOAPs plus temperature. Then I'd do the 'only caretaker milking' case - which should be trivial. And then the fourth case, the most complicated one."
Sophie gets a mild Aha! look on her face. "You're right, the example is too complicated, and I should have spotted that earlier. I did a boatload of fiddling with the table to get it right. I remember it was annoying scrolling around getting the values plugged in for each of the cows, because the other ones got in the way. And now they're getting in your way.
"Look," she continues, "one case doesn't have any effect at all on the other, so it makes no sense to bunch them up into one big table. Instead of making four smaller JUnit examples, we should make four tables, one for each relevant situation. Those will be much clearer examples of the way things like SOAP and temperature interact."
When she pauses, Paul fiddles nervously with his Martin Fowler™ Bobblehead Doll, then asks if she wants to throw away the big example. If there's one thing about agile projects he's still not quite comfortable with, it's the carefree way they throw away work.
"Well, probably. It's not bad to have a complicated example. Good, even: if there were interactions, that'd be more likely to flush them out. But now that it hasn't, we can throw it away." She sees the doubt on Paul's face, so continues. "Uh, not just yet - let's wait until you've got the smaller examples working. Then if this one automatically works too, it's served its life's purpose. Rest In Peace."
But then she pauses and screws up her face. "Actually, no. If we do that, we won't have any example that shows you can have a schedule for more than one case at a time. Seems like we want to say that somewhere, especially since Dr. Morin specifically wanted the schedule in stall order." (Sophie means that when students pick up the schedule at some hour, all the tasks for stall 1 come first, then the tasks for stall 2, etc.)
"Yeah," agrees Paul. "But maybe this isn't the example for that. The idea's there, but it's not obvious. You know: 'separate idea; separate table'."
Sophie agrees. She's got a bunch of other things to do, so Mark says he'll boil down the complicated example into one that demonstrates stall order. He'll show it to her before he starts work on it.
The user interface
Paul continues to code away, sometimes with Kendall. As he does, Sophie takes responsibility for choreographing a complicated little dance. It would be perfection if, just as any programmer needed a new example, she, Dr. Morin, and the programmer got together to create one (or maybe several). But Dr. Morin's workday doesn't allow that. So Sophie assembles what collaborations she can. Sometimes she writes examples with programmers but no Dr. Morin, making sure to snatch some of Dr. Morin's time to review at least the questionable cases. Sophie tries to keep ahead of the programmers so that they never finish one task and find there's no example for the next. So when the programmers are taking coding breaks and need a change of focus anyway, Sophie works with them to keep a little ahead of the demand. Sometimes that doesn't work, so the programmers write the next example themselves. They prefer to work with Sophie - she sees things they don't - but it's more important to have examples to work from than to have Sophie involved in each one.
After the business logic is finished, Paul sits down with Dr. Morin to make up a better user interface sketch. It's going to be rather simple: just a big table that people can print out on the records room printer. She's thought of a few additions, like a blank cell on each line so that people can check off what they've done. She also wants the rows in alternating shades so that it's easy to see what cells belong together.
Paul does not start his programming with full-fledged examples that represent what a user would see when looking at the page. The team's found that those examples are fragile and not all that useful for helping people envision what the feature will be like. Instead, Paul guides his programming with small examples that make localized statements. For example, one example just says "rows are alternating grey and white". He's assuming that if all those little statements are true of the program, the big picture will be true as well.
That's not true, not totally, but it's true enough often enough. Since "mostly true" isn't good enough, Paul makes sure to grab people to have them look at and try his interface - especially the interns and last-year veterinary students doing a clinical rotation. They do find some glitches. More importantly, they suggest ways the interface could be better. He relays those ideas to Dr. Morin during one of her cometary orbits through the clinic, and she approves of several.
After Paul thinks he's finished, he has the computer check all the automated examples one last time, nervously has Kendall double-check the user interface, and declares the feature done by drawing a line through it on the big iteration whiteboard.
Exploration - and a shocking discovery
The Friday end-of-rotation cookout for the students also marks the end of the iteration. Immediately afterward, the team starts its end-of-iteration ritual. The first stage is to demonstrate what they accomplished this iteration to every interested passer-by. (This also serves as a little bit of training for the people who'll start using the new and changed features on Monday.)
In the second stage, they try to keep everyone together for 90-minute session of exploration. Dr. Morin's made a brief list of things she wishes she knew more about, such as "how well does this work over a dialup?" and "does the daily schedule need any improvements?" Everyone - programmers, a few students, Dr. Morin, one intern - pairs up, picks one of those charters, and applies some exploration techniques to the system. At the end, they gather to compare notes.
There, Dr. Nagy smiles wickedly. "I was pairing with Kendall and we made up a soap opera where a cattle truck overturned on I-72 at the same time we had a batch of rodeo bulls in for a foot trim. So there were all sorts of emergency cases coming in at the same time as everyone's trying to keep the bulls from killing anyone. I kept throwing crises at Kendall, and he couldn't keep up. Here's the problem: it's too easy for the printout of tasks that's pinned on the notice board to get out of sync with the orders. I won't trust it - I'll want to go to the computer to check."
Discussion ensues. The general consensus is that the printout wasn't the right solution. Instead, people decide that it makes sense for students to check the master computer record (just as they today check the paper record). But that isn't easy enough to do: they should be able to walk up to the ward computer and press a single key to see the schedule. Dr. Morin agrees that sounds like a feature for the next iteration.
The team's habit is to wrap up the last day of the iteration with a small retrospective. During it, they agree that they should do a little more walking through user scenarios while planning the next iteration. Maybe that would have caught the mismatch between the feature and the world of the ward.
Normally the students on the ward and the unmarried chunk of the team would now head off to Murphy's for the end-of-iteration celebration. But suddenly word comes in that a cattle truck has overturned on I-72. All the veterinarians turn as one to glare at Dr. Nagy, and the technical people have to go alone.
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 email@example.com