There are lots of discussions around the metaphor of technical debt. Is it an accurate metaphor? How do you describe technical debt? What do you do about it? There are even whole books written about it. I've been thinking a lot about this lately and I've come up with this new (at least for me) way of thinking about technical debt that I'd like to share. I like it because it doesn't lay blame. It doesn't even try to analyze the original decision. It focuses mostly on the present and the future. In a way, it is kind of freeing.
All Decisions Have Tradeoffs
All technical debt starts off with a decision. We're all engineers (at least I'm assuming most of the readers of this blog are). We know that every decision is a trade-off. In software, we are constantly balancing and trading memory usage, CPU performance, flexibility, readability, expandability, and portability. Every technical decision from what to name a variable or function to what programming language to use is a trade-off. Even non-technical decisions are a trade-off - like where do we place the documentation for our project?
The Ghost Of Trade-offs Past
There are lots of theories of technical debt that say "Oh it's an intentional decision to take some shortcut and we intend to pay it back later." In reality, it doesn't matter. How we got here doesn't really matter. All that matters is now. Technical debt is when the previous trade-offs that were made in the past no longer serve us now. The rationale for originally making the decision or whether the trade-offs actually made sense when we made the decision no longer matters. We are just left with the current consequences of the trade-offs we (or others) have made in the past.
Technical Debt Is a Given
Every project encounters technical debt. Sometimes it is intentional. We know that a decision that we make now is going to cause us problems in the future and we just accept it. We've done the calculation and the perceived value that we get now (whatever that is) justifies what we calculate as the future cost. That is one form of technical debt, but I think most technical debt is taken on unintentionally.
We make what we think are great decisions. We weigh everything and optimize to find the best overall option, yet we still end up with technical debt. Why is that? Every decision has trade-offs. We make the best decision we can, based on our situation at the time. We take into account our knowledge and skill, and the business and technology environments around us in determining what trade-offs to make.
The reason we always end up with technical debt is that we and our environment change over time. We grow. Software Engineering as a craft grows. We learn new and better techniques. The business needs change. New features are needed. The technology we chose becomes obsolete or insecure. All these mean that our original trade-offs are no longer serving us.
What Is? And What Would We Do Today?
What do we do when we realize that our past trade-offs no longer make sense? We have a decision to make. We have "what is" as in how the software is currently written. Then we have "what we would do today". Given everything we know today, how would we write this software? The challenge lies in figuring out how to reconcile these two things.
To Fix or Not to Fix
Remember every decision is a trade-off. Whatever you decide to do, or not do, know that decision has a set of trade-offs associated with it. At some point in the future, those trade-offs will no longer make sense. They will create technical debt. Yes, choosing to fix technical debt now is a decision that will create more technical debt in the future. So will choosing not to fix it. It is inevitable. Might as well embrace it. Don't worry about eliminating technical debt. You can't. Just evaluate all the tradeoffs and make the best decisions you can.