Tech debt. It’s a phrase that makes project teams across the world shutter. The dreaded thing that clogs our backlogs, haunts our sprint planning, and crushes developers’ souls.
But is tech debt really as terrible as we make it out to be? Or would changing our mindset around tech debt and how we approach it help us to make wiser decisions? Basically, can we accept tech debt as an essential part of the process?
What Exactly is Tech Debt
A place where tech debt often arises is in a minimum viable product or MVP. If you think about it, the purpose of an MVP is to get the product into the market quickly or to be able to prove value to get additional funding. When time and budget are in short supply, a product team may feel a lot of pressure to deliver within those constraints and rush through development. This can—but doesn’t have to—result in less-than-ideal code that we refer to as tech debt.
Tech debt is often seen as the result of “cutting corners” to get a project into production quickly. By defining tech debt in such a negative way, we end up implying that it is a product of producing low-quality code or designs (perhaps due to unreasonable expectations and time constraints.) It’s seen as something to be ashamed of–work that is poorly done because we were in a hurry. One definition of tech debt from the Enterpriser’s Project reads:
“Tech Debt: making coding or design decisions that are sub-optimal–or that we know will need to be addressed and updated in the future–in order to get what we want or need into production sooner.”
But what if the term “tech debt” didn’t have such a negative connotation? Changing the definition of tech debt can help us approach it differently. Let’s instead think of tech debt as:
“Improvements that can be made to an existing project after it has been released into production. These improvements reflect work that the project team has identified based on what they learned about the product’s users and the technology during the creation and release of the product’s MVP.”
Why It’s OK to Have Tech Debt
MVPs Are a Learning Process
Let’s be honest: sometimes you just don’t know what you don’t know. That’s especially true with an MVP project when we can’t fully anticipate how a user will respond to the product or sometimes we are working with a new or unfamiliar technology. And that’s ok. MVPs are a learning process, and tech debt is a natural part of that process.
That doesn’t mean that we produce a poor-quality product with poor-quality designs and code. It just means that there is room to grow and improve. A good mantra to have with tech debt is the prime directive that is often used in retros:
“Regardless of what we discover, we understand and truly believe that everyone did the best job they could, given what they knew at the time, their skills and abilities, the resources available, and the situation at hand.”
If we think about MVPs as a learning process, then we can view tech debt as the changes to make a better product. While a project should include thorough user research and testing to validate assumptions early on, it’s entirely possible that the MVP release is the first opportunity to gain real user feedback. And if the user finds the feature that you worked on to be less useful than expected, then that feature might change and the tech debt associated with it will also change or in some cases not even exist anymore.
Aiming for Perfection Can Cause a Project to Fail
We all want to produce high-quality code and impress our stakeholders—especially if it’s our first time working with them. And of course, we always write the best code we can given the circumstances. But the circumstances surrounding the creation of an MVP often call for work that is good enough rather than perfect. It can be a hard pill to swallow, but rejecting an imperfect but working MVP can actually get in the way of delivering any product at all.
Early in my career, I experienced a situation where an MVP almost failed because there were developers on the team who couldn’t accept “good.” The project sounded fairly straightforward: a series of forms to capture information and create a log of a user’s medical history. The main goal was to get the MVP into the hands of their users to find out if their concept would even be useful.
We were able to get the first forms ready quickly and expected to be able to release the project in no time. And we would have done just that if perfectionism hadn’t gotten in the way. About a quarter of the way through, one developer found a better library to use. So we stopped, rewrote all the forms, and continued to move forward with the project. Then halfway through, someone decided there was a “better” pattern for handling the data. So we stopped, rewrote everything again, and then continued on with the project. This pattern of refactoring every time we found even a marginally better solution continued until we had put in almost 4x more work than what we had budgeted for.
The better way to have approached this project would have been to have taken the approach we initially planned for. It wasn’t poorly written, and it would have allowed us to release the MVP within the budget we were given. All of the “improvements” would have become tech debt, and we would have gotten a working app into the hands of the users. If the MVP was proven to be successful, the client could have used it to secure funding to continue development and then addressed the improvements if needed in the future.
I thought about that failed MVP during a recent project at Sparkbox. The client wanted an optical character recognition (OCR) solution to allow their users to scan data. When it turned out that the OCR solution they had in mind wouldn’t work in their particular circumstances, we decided to pivot toward an MVP of a manual entry form instead. We made the decision, pivoted, and had a new solution for them within two weeks.
Were these the most incredible, perfect, prize-winning forms ever created? Probably not. Is there room for improvement? Most likely. Is the code clean, clear, and efficient? Yes. And most importantly, does it meet the needs of the client and the user? Absolutely.
It’s also entirely possible that these forms will eventually be replaced with an OCR solution that actually works the way the client wants it to as technology changes. For now, a good solution is a much more valuable solution than a perfect one. And if users happen to love the form solution over the OCR one? Then we have done our job as developers, delivered a useful solution, and ended up with no real tech debt after all.
How to Manage Tech Debt
Once we accept that tech debt is a part of the MVP process, we can make a plan to manage it. Knowing there is a process in place can make you, your team, and your stakeholders feel better about tech debt and help with addressing it later.
It’s useful for developers—especially tech leads—to approach their development process with an MVP mindset. We need to decide on the minimum valuable code that can be written to accomplish the task at hand. Valuable means not poorly written, nor rushed. Overall, you want to be producing the minimum clean, clear, and efficient code that needs to be written in order to get the work out the door.
As Catherine Meade points out in her article Understanding Projects Better with an MVP:
“The hardest part of creating an MVP is identifying what to cut. Similarly, it is often more difficult to limit the scope of an MVP project than it is to identify your initial project plan… Each piece of an MVP is paid for with limited time and resources and therefore the ROI of each feature should be high. If the goal of an MVP is to learn, then each feature should teach. Reduce scope first with things that don’t provide answers to lingering questions.”
Tech leads and other developers should approach their code with this MVP mindset. When prioritizing and organizing your tech debt, you can evaluate the value of the tasks by asking the following questions.
Is it possible that this feature could drastically change in the near future? If yes or if you are still waiting on user feedback, that piece of tech debt should be de-prioritized until you have more information. If not, that task can be prioritized.
Is there anything the team can learn from working on this task? It’s entirely possible that what you learn from tackling tech debt can prepare the team to write better code for future features. That can bring a lot of value and can actually help the team avoid creating more tech debt as the project progresses.
Approaching tech debt in this way helps us to better understand which tasks will help us deliver the best work possible with the resources that we have.
Embrace Tech Debt As Part of the Process
Rather than viewing tech debt as an evil by-product of an MVP, let’s reframe our views. By changing our perspective and instead viewing tech debt as a product of a learning process, we can create a better process for handling it in the future.