By Bill Wake, Joseph Leddy, and Kent Beck
|When you need to break up a big feature, you often have many choices about how to do so.|
One of the basic challenges of software project management is sequencing. You have to do something today and something else tomorrow. Another challenge is the need for accountability and the ability to report progress. You'd like to make progress in a way that everyone appreciates. One way to do this is is to create small increments of business functionality.
On the other hand, a project can feel micro-managed if it has too many too-small pieces. If the pieces are laid out in advance, you reduce the team's ability to respond to discovery and learning. So, we have to slice the system in small pieces, but not too small.
Once you decide to track the development of the system by completing bits of business functionality, you have the problem of which way to slice the system. The same system can be sliced many different ways, depending on the needs and capabilities of the whole team. Sometimes you want to explore the innovative core of an application and you don't need to see the mundane input and output functionality early. Sometimes you want to put a minimal system into production quickly. Sometimes a group has fears about a part of the system that can be addressed by implementing it early. Sometimes the team just needs to get going, so a simply-implemented slice is appropriate. Sometimes you need a sizzling demo.
Exploring all the different ways to slice a system has been largely a matter of intuition. This paper presents a graphical technique for exploring different slicings. It builds on examples the first author drew during the first Programming Intensive Workshop at the Three Rivers Institute. The format of the workshop is to spend four days implementing simple games as a way to reconnect to the joy of programming. Because we worked on several different games, the workshop provided ample opportunity for slicing systems in various ways.
Real systems are too big to describe in one story. So, you have to split them into a series of stories. But how do you make that split?
Two questions can help you decide:
- What slice represents the essence of the system?
- What slice will help me learn the most?
The essence of a system is what it does, reduced to its barest form. For example:
- web sales system: a purchase transaction
- word processor: enter text and see it on-screen
- game: some interaction between player and system
- workflow: a transaction moved from one station to another
The learning side is important as it shows the places where we are most at risk. It's true that you don't always know what you need to learn the most. But the learning by trying something can help keep us out of analysis paralysis.
Games as Design Test-beds
One exercise for thinking about software design is to consider an existing system, and how it might have been designed it in the first place. You can imagine the decisions you might have made and the insights that might have arisen from them. Sometimes this gives you great appreciation for a design move.
It's also helpful to consider systems of moderate size. A real word processor may be way too big for an exercise. But games are often a good size to think about.
We'll show examples of two games as platforms for thinking about how to split stories: TetrisTM and a stacked letter puzzle. The former you probably know. The latter is a type of word puzzle: a quotation is written on multiple lines, then the letters in each column are scrambled. To solve the puzzle, put the right letters in place in the bottom.
Here are sketches for the choices involved in each:
The left side of the diagram shows the key screen, with annotations around it. Around the edges are a number of choices that could make a super-simple version.
- One-tris: have a single column. Each piece comes in the top, and all you can do is press a key to accelerate. This determines whether you die quickly or slowly. Then you could go on to add collapsing, different shapes, etc.
- Two-tris: has two columns. You can move the piece side to side as it falls. The diagram says "collapse row" but that could be a second version.
- Side-tris: has a few columns. This one is a bigger bite to start with. It doesn't have rotation but has more of the whole game.
- Slide-tris: don't have columns, just set up the interaction of moving side to side. Then add height, piling up, etc.
- "Extras": add previews, music, scoring, etc. They're all part of the final game but aren't crucial to it.
While I'm sure there are more ways to start, let's consider what these have in common. The first and most important thing is that they all have the essence of both user action and computer response.
We could imagine a different one-tris, that just had the computer spitting out blocks and dropping them (with no user interaction). This split isn't as good: by omitting the interaction side, it leaves out a key part of the core of the problem. (That's why a simplified domain provides good practice; in a real domain, we might go much further down the path without realizing that we were unbalanced.)
So which is the best path? We haven't implemented Tetris (especially 4+ ways), so we have to speculate. But either a simplified version of "one-tris" (with blocks falling but not stacking), or "slide-tris" (with no blocks at first), seem like good simple starting points for introducing blocks, motion, and interaction.
Stacked Letter Puzzle
Here's a sample stacked-letter puzzle:
You create the puzzle by writing a quotation into a grid, then pulling the letters in any column to the top, and scrambling them.
There are several possible starting places:
- a one-dimensional puzzle. (In the example shown, ONED is the answer, partially filled in.)
- a tool to create puzzles
- a grid with a fixed size
- a variety of interaction possibilities (typing vs. dragging)
In this case, the implementation (DewdropTM, by the first author) started with a one-dimensional puzzle. Looking back, it might have been better to have started with a one-letter puzzle, and then worked toward height before worrying about length. But it seems like either approach should work, and converge toward the same place.
Following are a few approaches that might help you think of different ways to evolve a system.
Ontogeny Recapitulates Phylogeny
There was a theory in evolutionary biology (no longer believed) that said, "Ontogeny recapitulates phylogeny." (Memorable today only because of all the syllables:) It claimed that the stages of growth of an organism correspond to the species' evolutionary history. Thus, for example, a mammal starts out as a single cell, then multiple cells, then adds a skeleton, becomes fish-like, adds mammal features, then fully develops into itself.
It might not be much use as a biological theory, but it can be an inspiration for design choices. Think how your product and its competitors have evolved over time. If you're starting fresh, you can use that as a guideline to what's been most important to the market. So, for a word processor, you might consider basic editing first, then printing, then styles or perhaps spell checking, then drawing tools, grammar checking, kerning, etc.
This isn't a hard and fast rule; if spell checking were going to be the amazing feature that would set a product apart, it should be explored sooner. But this guideline does remind you to consider where other groups have previously found it easiest to get incremental value.
Back when encyclopedias were books printed on paper, there was often an entry on the human body that let you look at the body through a variety of transparent overlays. The basic page had a picture of a skeleton. You could flip the preceding transparent page over the skeleton and see how the organs fit in. Then you could flip another transparent page, and see muscles over both. Finally, you could flip over a page and see the skin.
You can think of building up a system the same way. A basic Tetris game might start with just a single column. The next version could add multiple columns, then a border with scores, then sounds, then another border with previews. At any point, the system makes sense, even though it's not as complete as the final system will be.
Unlike the encyclopedia, you don't have to put the overlays in a fixed order. You can explore which ordering of overlays will be most valuable, and you can change your mind later as you learn more.
What if your system had to live under different constraints? How can you make your system be as valuable as possible in a constrained environment? Consider these possibilities:
- Character-Based User Interface. What if you had no graphics, just a 24-line by 80-column display?
- Voice-Based User Interface. What if your system ran without a screen? Could you make it valuable if used over the phone?
- Cell-Phone Screen: What if you had to put your system on a cell-phone? You get two square inches for the user interface. What's important enough to keep?
Want to give it a shot? Pick a game and try. Or if you'd like to practice with a more realistic system, try the wiki. (See http://www.c2.com/cgi/wiki if you're not familiar with wikis.)
In brief, a wiki is a website that lets people create, edit, and cross-link web pages. Following is a list of features. How would you arrange them to create something quickly that captures the essence of the system, maximizes value as you deliver the pieces, and lets you learn what you need to along the way?
- View a web page
- Edit text on a page
- Create a new page
- Wiki markup (see http://www.c2.com/cgi/wiki?TextFormattingRules)
- WikiWords that link to an existing page
- WikiWords that link to a "create me" page
- EditCopy – retaining a copy of the previous version of a page
- Reverse links (click on a page's title to see pages that refer to it)
- Find page, by searching in title or body
- "Like pages", those with a common word at the beginning or end of the name
- Sister sites: links to other wikis with a page of the same name
- RecentChanges: links to pages that changed in the last few days
- Last edited date
- List of prior versions; history pages (read-only previous versions)
- Anti-spammer "tricks" (e.g., using the same results page URL for all searches)
- Spell checking
- Converting spaces to tabs (to support browsers that can't)
- User names (so RecentChanges can show that)
- Marking "new" pages in RecentChanges
- Deleting pages
Here are things not (now?) in the c2 wiki that other wikis have added:
- Unicode support
- User logins
- SubPages: a hierarchical wiki namespace
- Free links: links not restricted to being a WikiWord
- RSS feeds
- Email notification of changed pages
- Alternate markup, e.g., TeX
- Active content (e.g., calculations)
- File uploads
- Minor edits (flagged so they don't show up in recent changes)
- Piped links: the target of the link doesn't match the displayed name
- WYSIWYG editing
- Merge support (for when changes conflict)
If you try this exercise (with a game, wiki, or something else), we'd be happy to link to your results.
Real systems have complex clusters of functionality, but they benefit from starting as skinny as possible. It's a useful skill to be able to make this split. A graphical approach, identifying a key screen, and breaking it up into "overlays", can help you explore alternatives.
[First draft February, 2005. Drawings were made at at Kent Beck's Programming Intensive Workshop, Feb., 2005. Revised and published, July, 2006.]