Contact us to schedule a demo or ask a question to learn how AdvantageCS can help you.

A topic that you might hear software engineers discussing from time to time is technical debt. From the name, you can already guess it is something undesirable. To hear the developers talk, any software that has been around more than a few months has it. Software that has too much of it can’t survive. It becomes buggy, unmaintainable, and irrelevant.

But just what is technical debt? How does software get into it and how do you get out of it? Or avoid as much of it as you can?

There are many different kinds of technical debt but here is a straightforward example. Software code is often organized into methods or functions that implement some piece of functionality. Simple applications may have hundreds of methods. Sophisticated enterprise-level software may have over a hundred thousand methods. Suppose somewhere you have the following method:

public void DoSomethingInteresting(

     string A,

     string B,

     string C)

{

// Method body: Implementation goes here

}

Parts of the software---other methods---that want to “do something interesting” will call or invoke this method to do it. To do its job, this method needs three inputs or parameters: string A, string B and string C. The code to invoke the method will look something like this:

DoSomethingInteresting(A, B, C);

There could be anywhere from one to a hundred or more of these uses throughout the software’s code. Perhaps it is used by the user interface, in external API methods, an import process, or for generating reports.

Let’s assume that someone decides to modify the software so that the behavior that had been controlled by the third parameter---string C---now instead depends only on a system-wide configuration setting. In other words, the implementation or method body of DoSomethingInteresting can just look up this configuration option. It no longer depends on string C in any way.  What happens if our developer doesn’t remove string C from the method declaration even though it is no longer referenced in the implementation? Does the code still compile? Sure. Does the applications still work as expected? Absolutely. In fact there’s no way the user, or the QA department, can tell anything is wrong.

But the software now has a new bit of technical debt.  

  • The declaration of DoSometingInteresting is more complex than it needs to be. The next developer to look at DoSomethingInteresting has to spend time understanding parameter C until they realize that it does nothing. So we’ve hurt code maintainability.  
  • All of the code that invokes DoSomethingInteresting must still provide some value for parameter C. The next developer might try to implement some new functionality by modifying the code to pass something different; however this won’t have any effect.  So we’ve made it easier to introduce a bug.  
  • Much existing code that invokes DoSomethingInteresting may have to do unnecessary extra work to provide parameter C, such as reading data from a database. So the software runs slower than it could.

So even though the initial change worked fine, that tiny bit of technical debt left behind can cause problems down the road. This is just one little unused parameter on one little method among millions of lines of code. It’s easy to see how many loose ends like this could add up to big problems.

Sometimes you go into financial debt for good reason: to go to college, to buy a house. This is a strategic decision and the same can be done with technical debt. You can take more on in the short term in order to get a big project done more quickly. While this approach could be called “taking shortcuts’” it is occasionally the right thing to do as long as you have a plan for paying back that debt in a reasonable amount of time. Also, like financial debt, technical debt can pile up, and it usually comes with interest. The more you have throughout your code, the harder it becomes to understand it and make changes. It becomes easier to introduce bugs and a lot harder to find and fix them.  

So getting back to our original example, what should the developer have done? Since the implementation of DoSomethingInteresting no longer needs string C, the developer should change the declaration statement to make this clear:

public void DoSomethingInteresting(

     string A,

     string B)

{

// Method body: Implementation goes here

}

The developer should also adjust any code that invokes this method to call it without string C, and clean up any extra code that was needed to find or produce string C.

DoSomethingInteresting(A, B);

Why might our developer not have done this? It could be as simple as not noticing, or perhaps the developer thought it would take too much time 

Fortunately, there are tools that address both of these issues effectively. At AdvantageCS, we use many tools including ReSharper, a code analysis extension for Microsoft Visual Studio.  ReSharper is constantly analyzing our code in the background as we work. Developers can get feedback about many code quality issues in real time. We also employ Microsoft Code Analysis Build, code reviews, and automated testing all geared toward avoiding as much technical debt as possible. These tools also largely automate the process of cleaning up any existing technical debt, like removing an unused parameter from a method and much more.

This vigilance can seem a bit academic at times.  After all, the software might work even if there are a lot of methods with extra parameters. But this attention to detail is an essential practice for crafting software that lasts. Minimizing and managing technical debt at AdvantageCS has helped us provide industry leading software for the past 35+ years and will allow us to continue to provide quality, customizable, and relevant software for years to come.

 



Filed under: Software



Add Your Opinion