Chris Eargle has a great article explaining that the term “technical debt” comprises both strategic debt and reckless debt:
Technical debt accrues interest, and it must be paid back lest the interest payments (lost time) become too high for product maintenance and future development. If immediate business concerns outweigh future business concerns, it makes sense to incur this debt. Debt incurred in this manner is known as strategic debt and is the only kind I find acceptable. […]
There is another form of technical debt that can and should be avoided: reckless debt. Unlike strategic debt, this is suffered without an informed decision. Reckless debt is far more dangerous as it is typically ignored or obfuscated until it presents a more serious problem.
This is right. In software development, even though you do research and discuss and debate, sometimes you cannot make a clear final decision that only has advantages. Ideally you can compromise on what features you have to deliver, but sometimes you have to accommodate the stakeholders on other software attributes. For example, you may choose to go with an older, slower version of a library than a faster version that has not been battle-tested. If you understand the decision you are making, you know you have to fix the problem at a later point in time, and will have to live with the disadvantages in the meantime.
But if you are misinformed, or don’t have the skills, or are prejudiced, then your decision is reckless. I am not sure that “debt” is the right word because people know when they are getting into debt, even with loan sharks. Some terribly wrong decisions made in software development are done without any awareness. People are either ignorant, or they are dismissive of the possibility that the decision could lead to loss. For example, not paying attention to backups.
A quick word about messy code. If your team has a programmer who doesn’t know how to write reasonably good low-level code, it is not worth it. At the end, you will have to read and rewrite every single line of code that they have written. This rewrite is much more time-consuming and cumbersome than just writing the same code in the first place, because now you have to worry that something is not broken, and have to build unit tests around them and need time from testers. Sometimes the old code contains bugs that you discover and cannot fix because fixing them can create problems for existing customers who rely on an unexpected behavior of the software.
There is a hygiene factor in code. Going below that threshold indicates a programmer with poor skills and lack of professionalism. For example, an incorrect or outdated use of naming, formatting, low-level program flow techniques demonstrates a poor programmer. But if you have some programmer who is good at the low-level, but has problems with program structure, such as making good choices of how to split or join methods or classes, or how to manage a programming interface, then a lot of code can be salvaged by re-assembly without worrying about low-level implementation details. Of course, the hygiene factor varies from one project team to another; you don’t want a team of architects making rookie design mistakes. Teams need to set their base threshold for programmer skills and only incur code debt for mistakes above it.