Not paying down technical debt in a timely fashion can bankrupt your product.
Often during the research phase of medical technology or device development, software is more of an evolved entity than a well-designed one. Later, during commercial development, time and budget may lead to re-use of that software as well as taking shortcuts in the implementation rather than coding "the right way." The accumulation of these compromises is known as technical debt. Technical debt has a tangible financial cost to the product throughout its life cycle. If the technical debt isn't "paid off" judiciously, it can bankrupt a product.
|Learn how to improve your medical device product development process at the BIOMEDevice Boston Conference, May 3-4, 2017.|
The costs of technical debt may first show up when the team must take what was good enough for a proof-of-concept and turn it into a product that has the features, behavior, and performance customers will pay for. If the demo code did not adhere to good design patterns, it may be extremely time consuming to make that transition and perhaps integrate the software with production hardware. Like interest, the costs accumulate, leading to a debugging phase that can dramatically delay a product release. If the product makes it into the market, the technical debt is still there and causes further problems when preparing a follow-on release, including potential incompatibilities for customers using the first version. In this way, the "brittle" software carries the burden forever. Brittle, spaghetti code, unstable, whatever the term, it is evidence of technical debt.
The way to avoid accumulating this debt and pay off or at least reduce some of it is through code refactoring. Code refactoring means converting a body of software to a more well-architected form. When this is done early, it lowers the cost of the technical debt, as the engineering team can work less encumbered and more quickly. In addition to the value of the increased productivity, there are gains due to fewer defects, which are often the result of poorly architected code. As a product manager, it is important to recognize when there is technical debt and make an informed decision to pay the debt by refactoring now or carry it forward. The following can be indicators that it is time to pay the debt:
- Is the rate of defects found worse in certain areas of the software, or unusually high relative to industry norms?
- Do engineers actively avoid working in any parts of the code?
- Are bugs taking much longer to fix or are minor changes requiring significantly more time than expected?
Our company sometimes rescues failing projects, and as a byproduct, we have seen technical debt get the best of engineering teams. The evidence has ranged from functions with thousands of lines of code to Rube Goldberg types of systems. Sometimes the causes are fundamental technology decisions such as when engineers use attractive new technologies that incompatible. In one example, the project relied on the Visualization Toolkit (VTK) and Qt's QML. Qt supports two models for user interface development: traditional widgets and the newer, declarative QML. QML has layout tools that are powerful for quickly creating a stylish look. Unfortunately, VTK and QML don't always get along. The cost and time to work through the incompatibilities and the inconsistent design were considerable. Using traditional Qt widgets with VTK would have avoided these surprises and led to a consistent and predictable design pattern. In other cases, we have seen products that used many programming languages where one or two would have worked. Completing and maintaining the product became a resourcing issue for our client due to the challenges of finding engineers with all the languages necessary.
Cleaner, more well-architected code has another benefit in terms of adding engineers to a project. When an organization follows common design patterns, engineers know what to look for and how code is expected to be written. This makes for greater productivity and fewer defects, as well as reduced ramp-up for the next new engineer.
There are sometimes good reasons to accept technical debt. If there simply isn't time or budget to refactor today, you just have to accept the debt for the present. In that event, maintain a defect list or work list for your product and add refactoring tasks to it. The debt can be resolved when there is additional time or budget or the next time that code will be modified. If you merely ignore the technical debt, it will, like interest, compound and ultimately result in a higher price: a complete system rewrite.
[image courtesy of SIRA ANAMWONG/FREEDIGITALPHOTOS.NET]