Archive for the ‘Examining Agile Practices’ Category.

Technical debt: the good, the bad, and the okay

Reviewing the community wisdom on technical debt, I am struck by the variety of definitions of the term, which are not merely variations on a theme—they are entirely contradictory concepts. I’m starting to think that we should abandon the term technical debt altogether in favor of more accurate labels.

The debt metaphor is appealing because it offers a way to explain at the executive level that development may be building up software liabilities along with software assets. However, I worry that the metaphor may also be offering some undeserved normalcy to process problems: Businesses, even profitable ones, are used to taking out lines of credit to support operations. Even more insidiously, arguments in favor of good kinds of “technical debt” are easily misused to defend bad kinds, when they really have little in common.

My point here is not merely to offer a taxonomy of technical debt, as others have attempted already (Martin Fowler; Steve McConnell). I don’t think these should be seen as variations on a common theme, but rather as distinct situations with distinct considerations. One definition leads to something that I think is always good; another leads to something that I think is always bad; and yet another leads to something that I think is okay if you’re careful.

The good: releasing early

As originally coined, technical debt referred to being willing to release software early even with an imperfect understanding of the domain or even with an architecture insufficient for the eventual aims of the product (Ward Cunningham; Bob Martin). We know that we’ll have to refactor the domain model as our understanding matures, or else live with gradually slowing development as our domain model grows increasingly out of sync with reality. But we gain a tremendous advantage in the process: We get feedback earlier, which ultimately means we will better understand both the domain and the actual needs of users.

Ward described this situation using a debt metaphor: The benefit we gain by releasing the software early is like taking out a loan that will have to be repaid by refactoring the domain model later, and we will be paying interest in the form of gradually slowing development until that refactoring happens. Ward’s intention was primarily to explain the refactoring he was doing on a project, not so much to justify releasing early.

The debt metaphor was clever, but I don’t think it actually fits. If we don’t release early, does that mean we’re not going into debt? We still have an imperfect understanding of the domain; we still have only a rudimentary architecture. We still have to refactor as our understanding matures in order to avoid slowing development. We have all the negative aspects of debt—the obligation to repay, the interest until we do—with none of the positive aspect—the up-front benefit of early feedback.

Releasing early mitigates our existing liabilities, it doesn’t add to them, and therefore it should not be described as a kind of technical debt. It’s almost always a good idea, but it does take discipline to make it successful: We have to actually listen to the feedback and be willing to change course based on it, and we have to keep the code clean and well-tested at all times so that we can change course as needed.

The bad: making a mess

Most people seem to define technical debt in terms of messy or poorly-tested code. This seems to be pretty universally acknowledged as bad, but it is often regarded as a necessary evil: In order to release on time (nevermind early!), we have to cut corners, even though we know it will cost us later in slowed development and lots of bug-fixing time. In practice, of course, we all know how this turns out: The cut corners lay in wait as traps for future development and the bugs pile up to an unmanageable degree.

If this is debt, it most resembles credit-card debt. It’s easy to take on lots of debt, and the interest is steep and compounds quickly. A credit card can be safe if you actually pay it off in full every month—in technical terms, refactor your code and make sure your tests are solid after every task or (at most) after every story. Otherwise the balance grows quickly and gets out of hand sooner than many of us would like to admit.

But it’s actually worse than that. Most of us have stories of nasty bugs hidden in messy code that took weeks (or longer) to figure out and fix. Debt can pile up, but at least it’s well-behaved; you know what the interest rate is. The problem we’re talking about now is actually a kind of unbounded risk: Any day, a new requirement can come in or a critical bug can be hit that lands in the middle of a poorly-designed and poorly-tested part of the code, potentially requiring a wide-reaching rewrite. Steve Freeman has argued that this is more like selling an unhedged call option: It can be exercised at any moment, putting you at the mercy of the market.

I would further argue that code that is poorly factored or tested should be considered work in process, and subject to the team’s work-in-process limits. A story simply isn’t done until the code is clean and demonstrably correct. I define a defect as anything short of being done: If the code is messy, doesn’t have tests, or simply doesn’t do what the customer actually wanted, those are all examples of defects.

Ideally we would catch such defects before calling the story done in the first place; if so, we don’t take on additional work until that existing work is done. If we declare a story to be done and then discover later that it really wasn’t done, either by someone reporting a bug or by developers finding messy or untested code, we should effectively add the affected story back into our current work-in-process and fix the defect before taking on additional work. Looked at this way, prioritization is meaningless for defects: The story was already prioritized some time ago; the defect is merely a new task on an old story, which is by definition higher priority than any current or future story. (Just be careful to weed out feature requests masquerading as bug reports!)

When faced with time pressure, cutting corners amounts to taking on debt or risk for the company without accountability. Instead, we have many options for explicitly cutting away pieces of work by splitting stories and prioritizing the pieces independently (Bill Wake). Each piece that actually gets prioritized and implemented needs to have clean code and tests to be considered done; the beauty of splitting stories is that you can have piece #1 done and piece #2 not started, instead of having both #1 and #2 started but not done, with a similar amount of effort.

The okay: running an experiment

William Pietri has offered the only interpretation of technical debt that I think actually fits the debt metaphor, having an actual benefit now and an actual promise to pay the debt at a definite point in the future while avoiding unbounded risk. The idea is that it’s okay to have some messy or untested code running as an experiment as long as it is actively tracked and all stakeholders agree that the code will be deleted at the end of the experiment. If the experiment gave promising results, it will generate new ideas for stories to be prioritized and implemented properly.

The benefit of this approach is very rapid feedback during the experiment. It truly counts as a valid debt because the business agrees to it, and agrees to pay it back by allowing the code to be deleted when the experiment is completed. Since the developers know the experimental code is short-lived, it must naturally be isolated from other code so that it is easy to remove later; there is no chance that some unexpected new requirement or reported bug will incur any risk beyond simply ending the experiment and deleting the experimental code early. An active experiment counts as work in process as well, so the team should agree on a limit for the number of active experiments at any one time.

Conclusion

I’m sure there are other definitions of technical debt out there, but these seem to be the big ones. Releasing early was the original definition, and I don’t think it represents debt at all. It’s simply a good idea. Making a mess is the most common definition, and while it’s a little like a debt, it’s even more like the unbounded risk of an unhedged option. It’s always a bad idea. Running experiments is a new but important definition, and actually fits the meaning of debt. It’s okay as long as you track it properly.

Reviewing a draft of this post, William Pietri offered a refinement of the debt metaphor for messy, untested code: “Instead of thinking of it as an unhedged call, one could also talk of loan sharks. If one has substantial gambling debts to a capricious mobster, then one comes to expect erratic demands for extra payments and menacing threats.” I like it: Imagine your programmers making shady backroom deals to get their work done under schedule pressure, and then being hassled by thugs when it comes time to work with that code again.

What do you think? Are there other metaphors that might work better than debt? Do you agree or disagree with my good/bad/okay evaluations?

Agile’s Second Chasm (and how we fell in)

Some years back, I remember the excitement in the Agile community when the general public started taking us seriously. The common reaction went from “Get away from me, crazy people,” to “That’s interesting; tell me more.” It felt like the car we had been pushing uphill had finally reached the crest.

At the time, it was very exciting. In retrospect, perhaps that was the beginning of our doom: the car passed the crest, picked up speed, and careened out of control. Now the state of the Agile world regularly embarrasses me, and I think I’ve figured out why.

The first chasm

Geoffrey Moore’s seminal book “Crossing the Chasm” is about a gap between a product’s early adopters and the rest of a market. Writing in 1991, he looked at why disruptive technology products fail, and concluded that there was an chasm between the early market for a product and everyone else. Some companies fall in, some cross it to success.

crossing-the-chasm

The essence of this is that the early market, who are circa a sixth of the total market, are different. They are comfortable with changing their behavior, and are eager to do it to get a jump on the competition. In contrast, early mainstream purchaserswant evolution, not revolution. They want technology to enhance, not overthrow, the established ways of doing business.”  Later mainstream purchasers don’t want to change at all; they do it because they have to. For a physical technology product, that mainly shapes marketing and product accessories like support and documentation. But what does that mean for something as ethereal as a development process or a set of values?

The second chasm

You can’t buy an idea. Instead, people buy things like books, talks, classes, and consulting services. By and large, those buyers don’t measure any actual benefit. When wondering whether they got their money’s worth, they go by feeling and appearance.

For early adopters, that can be enough. As people who seek sincerely and vigorously to solve a problem or gain an advantage, they are strongly motivated to find ideas of true value and to make them work. But for the later adopters, their motivation for change isn’t strong. For many, it’s merely to go along with everybody else, or to appear as if they are.

Because those later adopters are numerically greater, they’ll be the majority of the market. And unlike early adopters, who tend to be relatively self-sufficient, they will consume more services, making them an even bigger influence. They’ll also tend to be the least sophisticated consumers, the least able to tell the difference between the product they want and the product they need.

Putting that together, it suggests that when people want an idea, the most money can be made by selling products that mainly serve to make later adopters look or feel like they’re getting somewhere. Any actual work or discomfort beyond that necessary to improve appearances would be a negative. Bad products and bad ideas could drive out the good ones, resulting in a pure fad. The common perception of the idea would come to be defined by the majority’s behavior and results, burying the original notion.

That’s the second chasm: an idea that provides strong benefits to early adopters gets watered down to near-uselessness by mainstream consumers and too-accommodating vendors.

Agile fell in

From what I can see, the Agile movement has fallen in the second chasm. That doesn’t mean that there aren’t bright spots, or people doing good work. You can, after all, find old hippies (and some new ones) running perfectly fine natural food stores and cafes. But like the endless supply of grubby, weed-smoking panhandlers that clutter San Francisco’s Haight-Ashbury district, I think there is a vast army of supposedly Agile teams and companies that have adopted the look and the lingo while totally missing the point.

Originally, I based this notion on the surprising number of people I talked to who were involved in some sort of Agile adoption that was basically bunk: Iterations that weren’t iterating. Testing that wasn’t testing. Top-down power relationships. Cargo cult Agile. Fixed deadlines and fixed scopes. Teams that aren’t teams. Project managers who pretend to be Scrum Masters. Oceans of Scrumbut.

That could have just been me, of course. But over the past year or so I’ve talked to a number of Agilists that I met in the 2000-2003 timeframe. They have similar concerns. “This isn’t what we meant,” is something I’ve heard a few times, and I feel the same way. Few these days get the incredible improvements we early adopters did. Instead, they get little or no benefit. The activity of the Agile adoption provides a smokescreen, and the expected performance gains become a stick to beat employees with.

Honestly, this breaks my heart. These days, every time an acquaintance starts off saying, “So now we’re ‘doing Agile’ at work…” I cringe. I used to be proud to be associated with the Agile movement. But although I still love many of the people involved, I think what happened is a shame. Looking back, I see things I wish I had done differently, things I intend to do differently next time. Which makes me wonder:

  • Have other early Agilists noticed this?
  • If you had it to do over again, what would you do differently?
  • To what extent do you think the problem is solvable?

I’d love to hear what other people think, be that via email, on Twitter, or in the comments below.

Why estimate?

Much has been written on the subject of how to estimate the effort involved in developing software products. Some Agile teams use Story Points as their estimation units. Others estimate in Ideal Days. Still others use one of these plus Task Hours to help refine their estimates. Planning Poker is a popular method for quickly arriving at group consensus on estimates.

My own earliest attempts at estimating predate the Agile era by a couple of decades. In the beginning I used a technique that has probably been tried (with varying degrees of success) by many others:

  1. Break the development effort into as many small tasks as you can think of
  2. Estimate each of the tasks in hours
  3. Add all the estimates together
  4. Apply sufficient “padding” for comfort
  5. Hope the boss buys it

Estimation’s main purpose

There’s no doubt that the more recent Agile estimating techniques are much better than what I started out with, and I’m glad that so much effort has been put into developing these methods. Even so, I believe it’s easy to lose sight of the purpose behind estimating, which can be summarized as follows:

The purpose of estimating is to provide the customer with a predictable development schedule.

Predictable is the operative word here. With a truly predictable schedule, the customer can derive the information that is most important from his or her point of view. Given a predictable schedule, the customer can answer important questions, such as:

  • How much will this development cost?
  • Will we be able to hit the market window?

In other words, the customer is probably not interested in the accuracy or precision of your estimates in and of themselves. The customer is more likely interested in the predictive power of your estimates. Given that, you want to focus your estimating efforts on things that provide predictability.

Duration should be derived, not estimated

I like to encourage teams to focus on estimating User Stories in Story Points, and to discourage them from estimating tasks at all, largely because coming up with Task Hours doesn’t seem to contribute much to the goal of providing the customer with a predictable schedule. Admittedly, estimating Task Hours may help to inform the team about how good or bad it is at estimating duration, but that’s a metric that’s not directly useful to the customer.

What is directly useful is duration that is derived from a team’s demonstrated velocity. Given a velocity in units of Story Points per iteration, plus knowledge of how many Story Points remain in a development effort, the customer can quickly and easily predict the development schedule.

What is “the simplest thing that could possibly work”?

Anyone with even the slightest exposure to eXtreme Programming has heard the phrase “do the simplest thing that could possibly work.” While this precept is typically applied during the process of writing code, I’ve also heard it mentioned during design discussions. I bring it up myself during estimation sessions as a reminder to estimate the simplest implementation of a user story one can imagine.

I’ve also heard it misquoted as “do the easiest thing that could possibly work” and even “do the quickest thing that could possibly work.”

It’s not necessarily the easiest thing

Although the simplest thing that could possibly work might sometimes also be the easiest thing, it often is not. For example, the easiest thing might be to copy and paste a section of code in order to duplicate its functionality in another part of a program. But is that the simplest thing? I believe it is not.

It’s not necessarily the quickest thing

The simplest thing that could possibly work might sometimes also be the quickest thing, but there aren’t any guarantees. The use of short variable and method names might be quicker (because it saves typing time) than the use of longer, more meaningful names, but is it simpler? Again, I don’t think so.

What does simple mean?

Here’s my working definition: Something that is simple is neither complex (meaning having more parts) nor complicated (meaning difficult to understand).

In the first example above, the easiest thing is not the simplest thing because doing the easiest thing (rubber-stamping the code) introduces complexity.

In the second example above, the quickest thing is not the simplest thing because doing the quickest thing (using short names) introduces complication.

Conclusion

If you want to do the simplest thing that could possibly work, look for a solution that is both easy to understand and lacking in unnecessary complexity.

Clicky Web Analytics