It all started with a comment from a client, “I can definitely help work on these reports when we go live.” That single statement caused me to throw away a significant amount of work on a current project that we're planning on shipping this summer. This comment made a huge amount of sense, as reports are the lifeblood of many companies (including this one) and we don't want to be in the way of that company progressing.

When I heard this comment for the first time, I thought to myself “No problem. We can show the client how to create new reports and compile them into our code base.” That was fine, until yesterday! Yesterday I was fighting the report writer component we'd chosen for our application and after an hour of battling this tool, I threw in the towel. I thought to myself, “If I'm fighting this, our client has zero hope of success. It's time to rethink this idea.”

Yesterday I made the decision to throw away the reporting work we'd done to date and moved our reports into SQL Server Reporting Services (SSRS). I proceeded to install SSRS and the requisite Visual Studio tooling so I could begin the migration for the first report we targeted. By the end of the day, I'd migrated the bones of the report over and I finished wiring this report into our application in the early hours of today. I felt a huge burden lifted from my shoulders.

As you may have come to expect, there's an important lesson in this brief tale of changing out reporting solutions. The important lesson here is that we're avoiding the sunk-cost fallacy.

Individuals commit the sunk cost fallacy when they continue a behavior or endeavor as a result of previously invested resources (time, money, or effort) (Arkes & Blumer, 1985). This fallacy, which is related to loss aversion and status quo bias, can also be viewed as bias resulting from an ongoing commitment. Citation:

The world seems hell-bent on fully implementing the sunk-cost fallacy and this axiom is what leads to costly project overruns. In the case of software development, the sunk-cost fallacy has the tendency to cause serious long-term technical debt. In the words of the legendary basketball player Dikembe Mutombo, “Not in my house.” At this stage of development, we decided that the short term sunk-cost we've incurred vastly outweighs the long-term stability and maintainability of our project. After thinking about this a bit more, I decided to think about what types of decisions developers make daily that have the potential for either savings or loss. Here are a few…

In the Interest of Time

Sometimes developers take shortcuts in order to “just get something out the door.” This is known as In the Interest of Time coding. See, that phrase has an accurate acronym–ITIOT. I pinged my “brain trust” to give me ideas and my senior developer Greg said this:

In software development, I often have to make the decision to “just make it work” or make it “work for the next guy.” I've completely changed everything to make the code “make sense” to the next developer that might have to look at the code. That dev might just be me!

There are no quick fixes and that code that you “spiked” will live on much longer than you can ever anticipate. If you ever find yourself doing ITIOT coding, make sure you go back and make the proper fix as soon as possible. Pay off that quick loan ASAP.

Getting Stuck on Features is a Smell

Over 30+ years of writing code, I've learned to recognize a smell when I get stuck on a implementing a feature. This smell tells me that the feature is poorly defined, it's an incorrect solution, or it just can't be implemented as requested. Ignoring this type of smell is a common source of long-term technical debt. If it was difficult to implement, it will likely be difficult to maintain.

In nearly all cases when I encountered this smell, I returned to the client or stakeholder with the issue and, more often than not, a better solution was derived, and we were able to get past the “stuck-ness.” Sometimes a 15-minute phone call can save countless hours of development.

Instrumentation is Key

A few years back, my team was responsible for rewriting a website for a credit card company. When we deployed the website, we had several stability issues that were tough to batten down. Luckily for us–and I mean LUCKY–we discovered a set of telemetry tools that we could “bolt on” to our application to pinpoint bottlenecks and other stability issues. This deployment taught me the importance of having logging and telemetry built into our applications from the beginning. It's amazing how useful a logging system can be when operating an application. Thanks to my bud JVP for reminding me of this important aspect.

No Code Remains Test Code

Sometimes I begin code with the word Test (or Hack or Junk or Spike) in the name of the program, class, or application and often the name sticks with it throughout production. Take a look at this list of function names: getDailyReportFormTest(), getGaugeChecklistFormTest(), getMasonryFormTest(). There are around 30 of these with the word Test() in a code base that's now in its eighth year. Although this is a small technical debt, it's still a debt. Remember: Code lives forever.

I hope that some of these life lessons help you pay down technical debt early or not take the debt on in the first place. These types of decisions may be costly or difficult and or just tough to implement. Be bold and make the call as soon as you can. When it comes to my reporting issue, I've seldom felt better about a development decision. Make the call: You'll feel better when you do.

PS: A big thanks to my brain trust for helping add good ideas to this editorial.