Healthy Software Projects Have Strong Immune Systems
Ward Cunningham coined the brilliant metaphor of Technical Debt, He described it as where our code has not "accumulate(d) the learnings we did about the application over time by modifying the program to look as if we had known what we were doing all along." Robert Martin wrote an outstanding description of some project symptoms of "design rot" in both editions of Agile Software Development. Martin Fowler and Kent Beck built a catalog of obvious "design smells" in Refactoring. Lots of metaphors trying to express a very amorphous concept with compounding effects on project health. Every project has some. Some projects die from it, others manage it and thrive in spite of it.
To address this quiet project killer, I suggest that we look at design rot in your project like an infection in your body. Wow, that's dramatic. Why? Well, lets walk through how it spreads.
1) Infection
Roughly structured code is introduced into your system. Maybe we think this is helping us go fast (1). Maybe its just the best we know how to do at this point in time. This code now begins taking a toll on the health of your project as it is measurably more likely to produce bugs as well as be more difficult to maintain, to hand off to new people, and to build on. Still, what's a little inflammation? We're tough enough to muscle on.
2) Localized Spread
Code doesn't live in isolation. Poorly structured code is primarily poorly isolated. So, probably the same day, almost certainly soon, you will need to build code on top of the infection. We build new code that accommodates the existing problem, works around it, extends it or worst of all duplicates it. The poor structure has infected the surrounding code with more poor structure. Our project health is probably still manageable, depending on how many infections we have, so we proceed because the purpose of our jobs and our business is to deliver software.
3) Systemic Spread
Eventually, these pockets of infection leave the local site and entire the bloodstream. For a software project, that is the development culture of the team. We have reached a tipping point where current developers are building habits and justifications around those infection sites (if they didn't have them already), and new developers see the infected areas as examples of how work is done in the shop. New work is being developed with those bad structures as a foundation. Ongoing development gets slower and slower. Releases get more unstable, customer confidence erodes, new development all but halts. Healthy areas in the project are under siege, hard pressed to keep their structure isolated from the morass.
4) The new normal
As anyone suffering from a chronic illness can tell you, there comes a point where you have to embrace the new normal. Life from before becomes a fairy tale, largely disheartening to dwell on and definitely not practical or realistic. Life now is making the best of the situation you live in. We establish routines, take maintenance meds, and carefully pare our goals down to something manageable.
Yeah, that is depressing way to look at it. Sadly, I've watched people in these scenarios abandon the software field entirely because, who wants a career if that is "normal?" So what helps us get back to the creative, thoughtful, satisfying work of building tools that delight users and are sustainable?
Treatment Options
1) Surgery
We make replacing the problem code a special effort and attack it directly. This is the default approach for most teams. Go after the nastiest infections in the code and cut them out. Refactor, rewrite, replace. It is gratifying, it is a technical problem which is the kind we are comfortable tackling, and it is sell-able to programmers and management. The impact on schedules and productivity hurt and do not make anyone happy, but we all, from customers to qa, can make it through the recovery period if we have hope for a better new normal.
Unfortunately, localized solutions rarely fix systemic problems. If this is our only approach, we can play whack-a-mole forever or end up giving up on recovery. We lose years of lessons represented in the old code as we rewrite it, and then spend years trying to catch up to where we were. We transplant in new solutions with the same cultural habits that got us there in the first place. We make new hotspots with ongoing development even as we focus efforts to remove the old. Then, we jump from one to the next until we give up. Worst of all, we can get so buried in addressing infection sites that we fail to keep up with the business needs and kill the project. This is a risky play.
2) Immunize
We need our whole team to have the skills to combat design rot every day, every time they touch the code. Our approach to training software developers as an industry is pretty terrible. If you land and survive a programming job for year or two, you're in. I've met very few programmers who didn't care deeply about what they were building, and wanting to give it their best. As a field, though, we learn largely by self-teaching, trial, and error. We cling to our lessons fiercely and proudly because we worked hard for them and paid for greatly for them. Unfortunately, few of us, even with degrees, have been lucky enough to have someone actually help us learn better structures, approaches, strategies, and techniques that make well structured code the faster, easier, and more effective approach. Often, we don't even know we aren't already doing it. A healthy project need to invest in the skill development of their team, so that they have the skills they need to attack and destroy sick code when they find (or create) it. This does not happen in organizations by accident or by default, but only with intention, planning, and significant effort. It is hard to target the right skills, we lose enormous development progress with our best talent mentoring rather than coding. If we manage all that, we find that mentoring is a high burnout role. However, with those skills, we are ready to....
3) Quarantine and Treat
With people being armed with the skills we need, the language for addressing messy problems in software is old and proven. We have a word that we use to describe what you do with messiness in code. The word is encapsulation. Messes need to be isolated from the rest of the code, wrapped in an abstraction layer to keep the mess from spreading, and hopefully eliminated as soon as is practical. Some messes can stay fairly harmless for a long time, but only if they are isolated from the rest of the code. Some messes are inherent in our problem domain. Same answer, they should be encapsulated and isolated as much as possible. Isolating areas of concern in our code, however, needs to go beyond a surgical effort. It needs to be something we do every day, with every code change. A systemic infection needs a systemic solution that goes everywhere and attacks everything. The battle isn't won in a big bang, but bit by bit, day by day, improving our project health.
4) Strengthen
Every body is attacked every day. We keep it constantly under control with a healthy body and immune system. A healthy project needs an immune system and healthy team to hold design rot at bay.
If we need to isolate areas of the code, we need to do the opposite to the team. Individual programmer skills are necessary, but we need a force multiplier to truly make it effective. We need to take the culture that can be a carrier for the sickness and make it carry the cure. The Manifesto for Software Craftsmanship calls this a community of professionals. We have to go beyond PR reviews and testing. Throughout the team, we need to spread an intense focus on creating the best structured code we can make and keeping it that way every time we touch it. We need to work together, share our tricks, lessons, approaches, as well as our focus, determination, and encouragement to create great solutions. I once heard solutions like that described as code we would want to take home and hang from our refrigerator door.
So would we choose to infect our project intentionally, for a short term goal? I maintain that a skilled programmer can create simple, well structured solutions faster than hacking for short term goals, but in a case where that isn't true, I think that the idea of intentionally infecting our software project brings more appropriate gravity to our decision. It seems important to also consider if the project is healthy enough to bear the burden of it.
Footnotes
(1) It doesn't, but Robert Martin, again, describes it better than I.