Angie was a project manager, and she managed a lot of projects. These were fast-moving jobs that required a lot of attention to make sure everything went smoothly. While she tried as hard as she could to plan out as many project details as possible, she knew from painful experience that unexpected things happen and that following a static script didn’t work. She had to keep track of things “in real time,” noting action items carefully to make sure everything got done.
Over time, she had become increasingly sophisticated in her ability to manage these action items, even as her business grew and the number of projects for which she was responsible multiplied. Each time she did a good job managing a project, she got even more projects – a good thing, to be sure, except that she ran the risk of being overrun with all of the minutiae that required follow-up and closure. The management techniques she used had to work under the increasing load, or else those techniques, which had originally served her so well, would become her undoing as projects started to falter.
She had started out simply by maintaining a large whiteboard on which she would log action items and status. She simply wrote them down as they came in, one after the other. Because one action item might lead to another, she would actually end up with strings of inter-related action items, but they were all mixed up with unrelated action items, so she had to make notations to indicate which action items were interlinked. And her whiteboard filled up quickly. In fact, she noticed that if she had a bunch of terse action items, and if she simply wrote each one under the prior one, these short lines didn’t fill the whiteboard – she had the entire right side of the whiteboard blank.
So she started filling entire lines to make better use of the space. A new action item wouldn’t go under the prior one – it would go next to the prior one, filling all the usable space. In order to keep track of where things were, she created a grid on the whiteboard, so that when one action item related to another, she could note where that other one started – kind of an action item address that it could point to. This way she could fill the entire whiteboard and still follow threads of action items around.
This all worked great until the board filled up. Early on, when she completed an action item, she would just erase it so she had room to add a new one. But she noticed that because that action item might point to others – or might itself be pointed to by several action items – it became time consuming to check all the relationships before deciding if she could really erase the action item.
Cleaning up the old stuff
So she decided upon a new approach. She would keep a place where each project was noted: action item threads would start from there. When a project was complete, she’d just erase the main project note and move on. But she didn’t actually try to erase all of the action items related to the project; they’d stay on the board for the time being. Then, every so often (especially if she started to run out of room), she’d go back to the project list and trace through all the action items for the live projects, marking each one. This way she could figure out which action items were still active. While she had to scan lots of action item threads, in the end, each action item that was still relevant was marked. Anything that wasn’t marked was essentially garbage from the finished projects that could be erased. She could then sweep through the entire whiteboard and erase every unmarked action item, opening up new space for new action items.
The sweeping action actually took some thought, even though at first blush it sounded really simple. She wanted it to be as straightforward as possible; she didn’t want to have to think about the meaning of the action item when she did it; she wanted to go into a kind of brainless mode where she just swept over the whiteboard and erased stuff. She had a couple of options that turned out not to work well. She tried keeping a list of the live action item addresses and sorting them; then everything between two consecutive live action items could be interpreted as empty and be erased. The problem with this was that sorting took too long.
Then she tried sweeping through letter by letter looking for the “live” marker, erasing everything not marked as live. The problem there was figuring out what kind of unambiguous marker to use. For example, if she picked the word “Valid” as a marker for each live action item and then swept through keeping only those things with the five letters V-a-l-i-d at the beginning, she could successfully keep all valid action items but might miss erasing some dead ones. An action item that read, “Validate credit card for client xyz,” even when complete, would never be erased because it started with the same five letters.
In the end, she found that if she managed the whiteboard carefully, there would really be only three kinds of items on the board: live action items (which were marked), dead action items, and free space. Because she knew where the free space was (that’s how she allocated space for new action items) and had marked the live action items (and noted how long each one was, so she knew where it ended), then anything else had to be a dead action item (whose length she could also figure out, since it hadn’t been erased yet) that could be erased. Problem solved.
This worked well, except it took time and discipline. She specifically had to ignore the phone and other interruptions to complete this task. If she didn’t, she’d lose track of where she was in the middle of cleanup and have to start all over. But she found that there were some interruptions she really couldn’t ignore. So she started keeping better track of her progress – keeping a scan list, for example, of action items she still needed to scan or sweep so that if she did have a high-priority interruption, she could take care of it and then come back to the cleanup, picking up where she left off.
Combining little chunks into big chunks
Using this approach and timing carefully how often she did cleanup (enough to keep free space around, but not too often, since it detracted from the real work), she was able to keep her whiteboard relatively free of dead action items. But she did notice another problem: because she was erasing action items that were located amongst other action items, the free space would show up as various random blank spots in the whiteboard.
For example, if an action item requiring 18 inches was freed up and replaced with one requiring 13 inches of space, there would be a five-inch space that pretty much wasn’t good for anything. Over time, the whiteboard would end up with lots of small spaces available that added up to plenty of room, but she couldn’t really use it because the chunks were too small. (And she didn’t want to have to break up individual action items over several chunks – that would be just too inefficient to track.)
So she realized she was going to have to start compressing the action items. This meant recopying them into fresh space, closing all the little gaps, so that all the available space would come together as one big available chunk of whiteboard rather than tons of tiny spaces. The good news was that, after copying, she now could start putting new action items in. The bad news was that she could use only half the whiteboard – she had to keep the other half empty so that she had room to copy the first half into when it was time for “defragmentation.” She faced having to buy a second whiteboard just so she could do this – a prospect she didn’t relish, given the cost and the fact that she only had so much room on the wall for whiteboards.
Instead of that, she decided to divide the whiteboard into regions, making sure that no action items crossed from one region into another. It was as if each region were a separate whiteboard. Then, when cleaning up action items, she could scan and clear out all of the used regions but would compress only one of the regions at a time. That meant that she had to keep only one region free – enough space to copy from one other region. So if she had four regions, she could use three, keeping one empty for copying, losing only 25% of the space instead of 50%. Or, if she used ten regions, then she would lose only 10% of the space. She found that she could play with this allocation to tune it for a balance of usable whiteboard and copy space that worked best for her.
One other catch with this approach was what happened when the phone rang while she was copying action items over. She really didn’t want to stop mid-copy if she really had to take the call. So she ended up dividing the copy into four steps: finding a new spot for the action item; noting, next to the old location, where the new location was going to be; copying the actual action item; and then eventually correcting all the pointers to the old location so that they pointed to the new location.
This way, if she was interrupted, say, after noting the new location but before actually copying, she could continue the copy later; if she were interrupted after the copy but before correcting all the pointers, she had a way to get from the old location to the new location if she needed to access the action item for any reason during the interruption. Of course, it also meant that reading and changing the action items got more complicated, since she had to check whether to read from or write into the old or new location, but this wasn’t an insurmountable barrier.
If the phone rang while she was actually copying the action item over, then she typically let the phone ring until she finished the copy. That mostly worked; a couple extra rings usually didn’t hurt things; if she thought they might, then she could simply restart the copy after handling the interruption. She realized that occasionally she had a really long action item to copy, and if she tried to let the phone ring until she finished copying, the caller would hang up before she got to the phone. If she tried to restart it instead, the chances were that she’d probably never have enough time to finish the copy, so that wouldn’t work either. This didn’t happen too often, but she knew that she had to figure out a better way to handle such copies so she could stop mid-copy and pick up after an interruption. She created an action item to note that she needed to address this in the future.
Separating the generations
As she was improving her system, she noticed a distinct pattern. There seemed to be specific clumps of action items with different “lifetimes.” At the extremes were, on the one hand, short-term action items that came and went in a day or so; and on the other hand, yearly goals and, perhaps, items being noted for tax time the next year. The latter would stick around for a long time, and, frankly, it was a pain in the butt having to constantly rescan them. It occurred to her that she could actually allocate a separate space for the long-lived stuff and simply not scan it unless absolutely necessary, since the chance of reclaiming any space there was very low. That would make the scan of the short-lived stuff much faster and more productive. She figured that there might be intermediate gradations of age that she could distinguish if she wanted to be even more sophisticated about it.
But she also realized that this would mean that somehow she would have to keep track of ages and, at some point, move older items into the old-folks’ home. It also meant that any young items referred to by an expired old item might not get reclaimed – simply because the old item itself would not be reclaimed, or at least not for a while. In fact, if she ran out of space so that she had to start going through the older stuff in order to cobble together enough room for some new action items, it might take even longer to get that space, since she’d have to try to find it in the younger regions first and, failing that, have to move to the older regions, ending with the oldest one. She put off trying to get this going but kept note of it as something to work out in the future.
Sharing the burden
Things got really challenging for Angie when business took off to the point where she couldn’t do everything herself. She needed more help, and so now several people were handling the various projects. That meant that all those people were now managing action items on the same whiteboard. In fact, sometimes they had to wait for each other as they contended for access to the whiteboard.
But that was only the start of the complication. Who was going to do the whiteboard cleanup? And, worse than that, what would happen to projects if someone started doing the cleanup? For example, if one person was copying someone else’s action items around, then that other person might get totally lost when trying to find an action item. It’s not like everyone had their own space; the action items were all mixed up together. Angie didn’t have enough space to get each person their own personal whiteboard. So she had to figure out how to organize everyone so that they could work harmoniously.
Her first idea was to have one person handle the cleanup; that’s the only thing that person would do. When it was time to clean up, everyone else had to stop and wait. If it took too long, someone might jump in and say, “Hey, I’ve GOT to get this done NOW,” and the cleanup could be paused and restarted. But during the cleanup, everyone else took a break. And while everyone was working their projects, the cleanup person took a break.
The problem was that, when someone working a project got behind or overwhelmed, it was annoying to see the cleanup person sitting around snacking on donuts. And if there were too many project people making changes to the whiteboard, the cleanup person simply couldn’t keep up; changes came too fast.
So instead, Angie decided to keep better track of exactly what needed doing during cleanup and have everyone participate. When cleanup time came around, everyone put their projects aside and helped, and then when the cleanup was done (or had to be paused), everyone went back to project work. No one was ever sitting around. She actually wanted to find a way for some people to continue working projects while others did cleanup, but that had to be done carefully, since one person might be working an action item that someone else was moving to a new location. She hadn’t figured that one out yet but kept it in the back of her mind as yet another way she could make things more efficient.
After a few years of working all this out, Angie was pretty proud of the fact that things were going rather smoothly. Yeah, she had more ideas on how to make things work better, and she figured she’d get those implemented at some point, but she’d come a long way from simply writing action items line-by-line on a board and trying to figure out what to do when the board filled up. Now… if she could only work vacations into the picture…
Special thanks to Kelvin Nilson of Aonix for his patience in describing some of the nuance of mark-and-sweep, full-copy, and generational garbage collection for real-time Java in single- and multicore environments.