Technical debt is the distance a program is from its ideal form.
When code is not ideal, it takes longer to make changes and fix bugs. What’s ideal will change depending on the individual. To someone first learning how to program, they have no real ideals. They focus on getting a program to work. To an expert, a program must work, not fail, run optimally, have automated tests, be properly structured, be properly commented, use a consistent style and include any necessary documentation. Technical debt can come from programmers who haven’t yet learned these skills.
One source of technical debt is unrealistic deadlines. When faced with unrealistic deadlines, programmers skip steps and hack up the code just to get it working. This creates the illusion of progress, which is why so many non-programmers push unrealistic deadlines on programmers. However after doing that too many times, the code is such a mess that adding new features becomes very slow. Any new changes often introduce bugs in already completed work.
Some design approaches, such as Agile, are more likely to create technical debt. There is plenty of information on this topic already.
For a program to work it must produce the correct output for any valid input. Sometimes programmers forget cases, or sometimes they are so rushed that they only code the most common cases. In some cases the way they solve a problem doesn’t always produce the correct output, which is otherwise known as a logical bug. If this is a solitary file then it can be changed without issue, but most code is used by other code. So when you make changes in one part, every other bit of code that uses it must also be updated. If the design changes too radically then the calling code may have to be rewritten to properly handle it. Incomplete code adds to technical debt.
For a program to not fail, it must produce the correct output if any errors happen. This includes user input is outside of valid range, files that can’t be accessed, disk errors, inability to connect to the database and more. Failure to account for errors is also technical debt.
Code should run quickly. While this may seem obvious, especially to senior developers, there are far too many new developers who write slow code. There are times when slow code is alright, however in applications where performance matters, code needs to be more optimal. Poor performing code is another form of technical debt.
Automated tests should be written to test every piece of code. This starts at low level functions then works its way up to higher level code. Automated tests often take as long to write as the code itself. If you’re doing additional testing, such as Monte Carlo tests, load tests or memory leak tests, then that just adds to the time. Every time you change the code, the automated tests may need to be updated. If they aren’t then this is technical debt. If the structure of the code changes then automated tests definitely need rewriting. This is one of those hidden costs behind scope creep. Some things can’t be done with an automated test, such as some types of visual controls. These require manual tests, which bog down any QA cycle.
The code should be properly organized. This means you follow a set of patterns when coding, such as putting all code for one type of thing into one place. This can change depending on the overall organization of the program. While some would claim this is object-oriented programming, such organization existed well before object-oriented existed. The key is organization. Code must be well organized. Disorganized code increases technical debt.
Code should be well commented. The myth of self-commenting code dies when a programmer looks at one of his ten year old projects. Every programmer looks back on old work and wonders what kind of drugs he was using at the time. Code may seem logical when you’re writing it but to another programmer it can look a complete mess. A simple sentence in a comment block can save a quarter hour of reading through code. A lack of comments contributes to technical debt.
Code should follow the same style. If tabs are used in one area and spaces in another then it becomes annoying. If some spacing is three spaces and others are eight then it’s equally annoying. A style is how you space and indent, how you display lists and literals, how you name classes and functions and more. Code in any project should use the same style. A consistent style shows a well organized mind, and good organization is essential in programming. Inconsistent code contributes to technical debt because it’s harder to read and interpret.
Creating documentation can be annoying to programmers. Most programmers utterly fail at documentation. Creating good documentation is a skill on its own. It’s essential for some projects. If documentation is required and is missing then that is technical debt.
Technical debt affects some projects more than others. Simple projects, with less interdependence, can have some technical debt without too many issues. The more complex a project is, the more strongly it is affected by technical debt. Many projects that are buggy or go over budget do so because of technical debt. Correctly dealing with technical debt is essential for meeting time estimates and client expectations.
Many projects fail because of technical debt. These projects can often reach completion but at far greater cost then expected. Technical debt also increases the cost of bug fixes and new features. For this reason senior programmers are key to developing good software.