3 comments

[ 3.4 ms ] story [ 22.7 ms ] thread
The other day I had a "near miss" in traffic because somebody passed a garbage truck at the top of a hill -- they were coming at me in my lane and forced me into the shoulder.

This wasn't an "accident" because we never collided, never called the cops and never made an insurance claim. The situation worked out OK because I did what I was trained to do and because I was lucky. If I was distracted by my phone or if there was a pedestrian in the shoulder, things could have been different.

Things like this happen in coding all the time.

For instance I was looking at some code where frequently there is a list of items and there's also some flag that is set when the list of items is not empty. It does something like

if(listNotEmpty) { startProcess; foreach(element in list NotEmpty) ... endProcess; }

this pattern was used perhaps 15 times in a very large class. This code can be correct when everything is done right, but this kind of code is risky when it comes time to maintain it.

Why? Because now there's an entanglement between two variables. Someday there will be a time when somebody changes things and the list is empty and the flag isn't set or vice versa. The correctness of the code depends on some other code that is far away being correct, so it's brittle.

This kind of muddy thinking also seems to spread. In another part of the code there is list A and list B and in the early development of the system it turned out that A had elements or B had element but not both. So when it came time to do something with list B, it got processed if A was not empty.

Again, this might be correct, but it's still technical debt because in the future A and B might not be mutually exclusive. On top of that, it puts a huge cognitive load on any reader of the program because when they look at the place where B is being processed, they've got to think about the relationship with A.

I don't view technical debt as the possibility that your code may break in the future if changes are introduced. That's a given no matter how careful you are. Technical debt to me is a conscious decision to take a current benefit in exchange for a future cost. "I know this implementation has flaws which we will need to revisit before we go live, but I can implement it in 30 minutes and have it ready for tomorrow's demo vs. spending a week researching and developing something production-ready."

Many people now use the term "technical debt" as a cover for "developer incompetence" though.

To me, technical debt comes in both the intentional and non-intentional form (and more often than not, the latter). In fact, I'm a firm believer that all software tends toward entropy, so feature additions inherently add to technical debt if conscious care and refactoring is not taken.

Technical debt (to me) is measured in "extra time to add the next feature", however in practice this measurement is impossible, as your control is a theoretical application with the debt removed.