Technical Debt



If you've been in software for any period of time, you encounter the idea of Technical Debt. It has been expounded upon by a number of luminaries and included in many software development books and blogs. ACCU has a nice write-up. It has been discussed on Ward C's wiki. Tim Ottinger tried to explain why pay-down doesn't happen. Steve McConnel chews the idea thoroughly. Technical debt has been likened to pollution.

We've not met a programmer who didn't believe that Technical Debt exists or that it is not significant. It is certain (or at least felt certainly) that ill-conceived or ill-formed code will impair the developers of any software system.

Well-designed code exhibits a deep and profound simplicity. When code has cleverness and magic in it, it tends to be complex and that complexity decays in the face of future changes. Well-designed code is code that follows the SOLID design principles (check out the audio version or the in-depth articles at Object Mentor). Simplicity and careful design don't exist as an academic study. Simplicity and careful design lead to a more fluid development process. Technical debt leads to a very rocky, uneven development process where very small changes in very bad areas become impossible to estimate. Even those changes that are not slow to write may end up bouncing around in QA for days, weeks, or even months. Any foray into bad code may cause delivery dates to be missed.

Bad code and poor design: that's what we call technical debt. This is not what Ward originally meant. He was referring to code written well to an incomplete understanding. As the word is used these days, it is to describe poor design and messy code. This is a shame, but here we use the term in the common sense, not as Ward intended.

I think there may be confusion in the way the word "quality" is used. If your definition includes opulence (gold-plating), self-indulgent implementation, needless future-proofing, complexity, wars over formatting, or man years of back-end testing with emergency rework, then one might be better off without it. If, on the other hand, your definition of quality is simplicity and well-crafted design then quality is essential and it makes no sense to argue against it.

Technical debt is drag, but quality and simplicity are thrust.

Once one finds that his team is suffering from technical debt what must be done? There are three choices:
  • Do nothing... allow it to accumulate and strangle productivity.
  • Pay it down by investing development dollars in cleaning the code.
  • Declare bankruptcy. Abandon the code and start over.

The bankruptcy option is a dire decision indeed. As mentioned on the AgileOtter blog article:
Rewrites are doomed for the most part. The reasons are well documented and well understood. The risks of gaps and scope creep are legend.
Doing nothing is an option frequently taken, but once the code impairs proper software development, one finds that avoiding ugly areas of code spreads the ugliness. Instead of making a fix where it belongs in the ugly code, a fix is made in all the places where the code is called. This creates duplication, which increases maintenance points, which increases the likelihood that you will get incomplete fixes in the future and which increases the ugliness in the caller code. This code eventually becomes indebted and the ugliness spreads from there as well.

The reasonable person will not take on debt he cannot afford. If the reasonable person takes on debt willingly, he does so with a clear plan for paying it. What kind of a person would borrow with no intention to pay? Such a person would be a fool or a crook.

So the big question is what you are going to do about your technical debt, and do you (as evidenced by your actions) understand and believe that code quality matters?

The most disturbing things about technical debt are that some lack (or have lost) the ability to see it when they're knee-deep in it, and others feel that it is a necessary condition of software development.   This is more common in non-pairing, siloed development shops.   Tim recommends pairing and breaking down silos to help get more eyes on the code.

Getting Un-stuck in TDD

Just like any other writers who are working in a creative medium and against a schedule, Test-Driven developers have writers block from time to time. When I was learning to Test-Drive software, I saw how much more quickly my more experienced colleagues broke through the barrier. People like Dave Chelimsky had a bag of tricks that would keep them working productively. I think he is responsible for transmitting the first three item to me. From there, I needed to develop some simple ice-breakers of my own.

A small variant of something Esther Derby said is responsible for the "most interesting" item on the list. She suggested a retrospective leader asking the team what they have the energy to do. That hit me. There is nothing wrong with picking the test you can most easily pour your energy into.

Writing the assertion and function name first has been greatly effective for me. Sometimes I leave the name as something generic until I can write an assertion that is meaningful, then I revisit the test name. If I have an assertion the ("check"), I know where I want to go. I can perform the setup (build) and the key method call (operate) . The Build/Operate/Check method also gives me more readable tests in addition to helping me maintain some semblance of flow.

Renaming and refactoring are helpful, even if the naming is not all that it could possibly be. This is because your eyes can become "stale": you don't really read the code your eyes pass over. One solution to this is to cause something about the code to be "new". Furthermore, if you increase readability then you may reach a state where wrong code looks wrong.

Reading the code for obvious flaws is another way to make the code new by changing perspectives. This can have a good effect, since a change is as good as a rest.

The best and most reliable way to break your writers' block is to change partners. If neither you nor your pair programming partner is able to easily think of the next test to write, it is possible that you are done or that you have both gone stale. Changing partners will give you a whole new set of eyes and a whole new perspective on the readability of the code.

There is a missing element here which will be considered elsewhere -- "reduce your scope".

Everymember Skills



Source: Tim Ottinger

People are typically worried about starting XP on the basis of personality types. There is typically a very small number of people who just don't "get it", and developers become concerned that they will fall through the cracks, or that their best coworkers will.

There is more that each Agile team member needs beyond technical wizardry. These are really as much attitudes as skills. When the team begins to break down, it tends to be along certain lines. To help adopters, it is good to have a clear statement of some values that members need in order to reduce friction and keep the project moving.

Mottos and slogans are not the answer to real problems among people. If a set of developers have unresolved past conflicts, they will find it difficult to take to this way of thinking. I am not sure how possible it is to coach people out of bad history with each other. I suspect it will be necessary for some of them to find a different team where they can have feelings of equality, humanity, cooperation, etc.

What these attitudes & skills can do is set an expectation. When a team is starting out, they should understand that the normative behavior is to ask questions, look for ways to measure the quality of their input and output (information), to contribute equally with their peers (energy, equality, cooperation), and to have patience when others are struggling (humanity). With such a start, there is some chance of the team being successful together. With a balk at the very ideas espoused, there is a good chance that the team needs a little refactoring.

ABC's of Pair Programming

Source: Jeff Langr and Tim Ottinger

I love the opportunity to sit and program as half of a pair. I'm sure it's not for everyone, but I too was once one of those who resisted the idea. Part of my resistance was my fear that people might realize I didn't know as much as they thought I did. I got over that. Many people who have given an honest effort to pairing (done by the rules) have found out that it's actually very enjoyable and effective.


Another common resistance is misunderstanding of what pairing is, and of what benefits you might get from it. To be effective, you can't just sit near someone else and expect magic to happen. The rules are simple, but not obvious. It makes perfect sense to me why someone would hate pairing after doing it poorly.


The least obvious rule is "change pairs frequently." A typical conception is that pairs are married at the hip for days at a time or even weeks. No, I'd slit Tim's wrists and he'd slit mine were that the case. Instead, we switch pairs often. The tedium of dealing with one person all day long aside, one of our goals in switching often is to ensure that not just two, but at least three people contribute to the solution of a task.


The downside of frequent switching is the overhead cost of context switching. It takes time to explain things! But that's where the synergies in the original XP practices come in: If you're doing TDD well, following simple design, coming up to speed on the test at hand isn't a terribly difficult proposition. And in fact, the need to minimize context switching overhead is a subtle force in the direction of improving code quality.

Simple Design

Source: Jeffries, et. al. Extreme Programming Installed, Addison-Wesley, 2000.


My understanding is that the concept of simple design is Kent Beck's invention, but I've not found a definitive answer yet. I reference the Ron Jeffries XP series book as the first published place I could find it (but the material on the C2 wiki predates this). I also wrote about these four rules as a chapter in Uncle Bob's Clean Code.


The notion of "simple design" is often interpreted as YAGNI ("you ain't gonna need it"): Build only what the customer asks for--don't add bells and whistles that they don't need. Or, from a design perspective, don't build complexity into the system where it's not needed. Don't introduce abstractions unless you have a valid need, and don't build the all-encompassing infrastructure or design that will support every possible feature that could come along.


But my definition for "simple design" has always been these four rules that I learned while at one of the Object Mentor XP Immersion classes, way back in 2000-2001. The Immersions were led by Uncle Bob, Ron Jeffries, and Kent Beck, with a few of us fortunate lesser Object Mentors helping out as table coaches. These were some of the most entertaining sessions I've ever attended.


The four rules of simple design speak to specifics--while YAGNI can be understood in a broad context, here we are specifically talking about systems design. The rules are in order of importance, hence the numbering, and you'll note that the last one, i.e. the least important, is the rule that most closely speaks to YAGNI. More important, then, are having as comprehensive tests as possible, minimizing redundancies, and coding clearly.


My contention is that if you knew nothing about classic concepts of good design, such as the single responsibility principle, the dependency inversion principle, design patterns, and other heuristics, you could still get there by following these four rules. When explaining these rules, Beck talked a lot about the notion of emergent behavior--that you can get a holistically positive result just from applying a very small set of simple rules at the individual level.


I've done that experiment a couple times in reasonably-sized subsystems (a few dozen classes): I've followed TDD (test, code, refactor), and during the refactor step only considered rules two through four, trying to pretend that I didn't have a good background in OO design. Then I've gone back and sketched a model of the design in UML. Both times, I've been pleasantly surprised, having produced a design that looked elegant but not complex.


You don't have to throw away your exhaustive knowledge of design principles when using simple design. Instead, reconcile what you produce with the rules, and be willing to change your design principles if simple design suggests there's a problem. Try it!

Lean Principles


Source:
Lean Software Development

Tom and Mary Poppendieck


Addison Wesley, 2003



Agile software development owes quite a debt to The Toyota Way, AKA Lean manufacturing. While Lean principles have lead to tremendous savings in the world of producing material goods, it was uncertain how the principles apply to software development. Furthermore, there seemed to be a bit of a gap regarding how managers relate to Agile teams.

Enter Tom and Marry Poppendieck, and their "An Agile Toolkit for Software Development Managers". In one concise, readable, usable volume they managed to teach the application of lean principles to software development in a way that is useful for managers.

As explained in the book, the main challenge was in translating basic concepts.

In order to reduce waste, one has to learn to see waste in software development. It takes the same basic forms of rework, wait-states, work-in-progress, etc. As we work through Lean Software Development, we learn again to be courageous in simplifying our work lives. We learn to do one thing at a time. We learn to stop half-doing work to pick it up again later.

A surprising bit is "decide as late as possible" -- deferring decision making until the latest responsible moment. It is quite obvious once one has begun to apply it, but goes against the type-A intuition. Rather than deciding more things up front and sticking to our guns, we are told to wait and decide when it is clear which way we should go. This kind of iterative decision-making is at the heart of Agile practices and aids us in making simplifying assumptions. For that matter, we find the same principle at work in well-crafted software in the form of late binding.

Building integrity into the product again echoes Deming.

The final point, seeing the whole, helps us remember to beware local optimizations that tend to decrease the performance of our organization. A favorite teenage lament is "my life would be easier if everyone else would take better care of me." In a similar vein, we find that optimizing for one group (perhaps the developers, perhaps product group, perhaps management or sales) can cause the organization as a whole to suffer. By seeing the whole, we will take steps that may actually make some peoples jobs a bit more difficult in order to improve the ability of the company to compete.

Demings 14 Points and Agile Development



Source: Deming, W. Edwards. Out of the Crisis, The MIT Press, 1982.




If you keep your ears open in any agile discussion, you can hear the echoes of W. Edwards Deming in the various practices that comprise agile development. W. Edwards Deming was a visionary man whose practical reformed wartime America and post-war Japan.

The agile values (to soon be re-presented here) include driving out fear, removing barriers to pride of workmanship, continuation of eduction, sharing knowledge as on-the-job training, and retrospectives to improve constantly and forever. You will also hear the echoes of "institute leadership", "adopt the new philosophy", etc.

When I revisited these values, I was surprised to find "cease dependence on inspection." I suppose fifteen years ago when I read up on Deming originally I must have seen and read that admonition, but I must have blocked it out. Maybe it was because I tended to read it from the point of view of QA professionals who were more comfortable with the other principles.

It is a simple admonition, but not one that is easy to follow. It is certainly easy to simply stop inspecting/testing/reviewing. But that's not quite what it says. It says to eliminate our reliance on inspection by building quality into our products throughout the process. Deming did not recommend piling scrap on crap, but recommended instead that every station in a process would measure and evaluate its input and its products. This is where the idea of stopping the line came from. If we receive only input of the highest quality, produce results only of the highest quality using the simplest process of the highest quality, then post-production inspection becomes useless.

Let's say that again. If we honestly can assess that we are building things well by checking them early and often, then tail-end QA becomes unimportant. If it becomes unimportant, then we can stop doing it. That is an exciting proposition, even if it does require us to take on different procedures than we would normally follow.

While the Agile methods are not typically considered to be a school of Deming's Total Quality Management, it does acknowledge that speed is primarily caused by quality. In this sense, quality is not something you trade off for speed, but something you increase to get speed.

Oblique Strategies

Thanks Tim for reminding me of the Oblique Strategies card decks. I am tempted to try to pick up a set--they are wonderful collections--but it'd probably be a lot easier to simply create my own from the text listings on the site.

Eno and Schmidt used the Oblique Strategy cards in collaborating on Eno's classic 1977 album Before and After Science. (Before and After Science is one of four stupendous albums that Eno made in a row before abandoning--for a while--vocal "pop" music in favor of soundscapes. Before and After Science is my second favorite, behind Taking Tiger Mountain By Strategy).

Some of the cards are strictly constrained to recording an album ("feedback recordings into an acoustic situation") but others are applicable to any circumstance: "Emphasize differences," "emphasize repetitions," and "emphasize the flaws." Or, "listen to the quiet voice."


I can imagine randomly pulling an Oblique Strategies card to help us look at things in a different way on an agile project. They could act as effective tools for keeping retrospectives (and perhaps other events) lively. Some of the cards are quite interesting when you think about both their musical application and adaption in a software development process: "Look closely at the most embarrassing details and amplify them." In a fashion, that is what the lean concept of "stop the line" is about.


What might you do with "Take away the elements in order of apparent non-importance?"

The Magic of Cards


I was exposed to the XP idea of using index cards as a preferred tool back in 1999. For a while, I still preferred whiteboard work to cards, just for the large visibility. But I quickly came to recognize the simple power of things like deletion-by-ripping, rapid ordering, arbitrary grouping, simplicity of shared communication and agreement, and also the power of mobility--they go everywhere, even through an airport metal detector. (Water, often found in washing machines, is a bit of a problem.)


Once a week or so, I run through the dozen or so cards tucked in my jeans or shirt pocket. I scratch out useless or already ingrained information, consolidate the really useful information, and delete the completely used or otherwise useless cards. So much quicker than a BlackBerry!


I keep a small number of reference cards handy; one is a vi card. Despite what you might think, the vi card changes frequently. I'm often seeking better ways to do things, and of course note those on my vi card. But once I do something often enough and thus ingrain it (I now know to rotate my split screens with ctrl-w-r), it doesn't really need to appear on the card. I scratch it off, and after enough scratchings or when there's no room left, I rebuild the card.


Apropos of little: Despite our best attempts otherwise, many of us end up being just like our parents. A few years ago, and by then well addicted to the cards, I caught myself in the mirror. I realized that I was like my father in many ways: political philosophy, appearance, and demeanor. I had to laugh when I noted what made the transformation seem complete: scribbled notes on a stack of index cards stuffed into my shirt pocket, sitting alongside a couple pens. I am my father.

Agile Manifesto

Card for Agile Manifesto

Source: http://agilemanifesto.org

This is where it all started, on February 11-13, 2001, at the lodge at Snowbird ski resort in the Wasatch mountains of Utah. The original signers met to talk, ski, relax, and try to find common ground. These are the original seventeen:
  • Kent Beck
  • Mike Beedle
  • Arie van Bennekum
  • Alistair Cockburn
  • Ward Cunningham
  • Martin Fowler
  • James Grenning
  • Jim Highsmith
  • Andrew Hunt
  • Ron Jeffries
  • Jon Kern
  • Brian Marick
  • Robert C. Martin
  • Steve Mellor
  • Ken Schwaber
  • Jeff Sutherland
  • Dave Thomas

The result wasn't a scathing attack on business-as-usual, nor a rubber-stamp for the eXtreme Programming or Scrum. It was a simple statement of values. The statement of values is important because the practices without the values are empty.

These values are pragmatic and practical, arising from many combined decades of actual software practice. The preamble (not quoted on the card) says:
We are uncovering better ways of developing software by doing it and helping others do it.


If a company is devoted to following a plan, fighting changes to scope or priority, purchasing expensive and opinionated tools, following a rigid process, and producing copious documentation then that company certainly may continue to do so. It may even be successful. But it will not be agile. In fact, such a company should not waste time and money attempting to adopt an agile process. Agile is for companies devoted to simplicity, iterative development, time-to-market, and quality.

Failing to adopt the values is the first and greatest failure mode.