Better Practices (7 Part Series)
After this article was posted, Matt Eland wrote a remarkable article with additional information that goes well beyond this one ...
"Something every software engineering team needs to remember about technical debt - it's almost always hidden. And, hidden debt is so dangerous because it compounds silently." - Unknown
As a development project moves forward and evolves, what are the hidden costs?
Technical debt, while it sounds important, can get lost ... the running joke is that once it gets put into the backlog, it's there; permanently. Unfortunately, this joke more real than we want to admit.
How do we as developers keep Technical Debt from getting lost in the background?
"Shipping first-time code is like going into debt. A little debt speeds development so long as it is paid back promptly with refactoring."
"The danger occurs when the debt is not repaid. Every minute spent on code that is not quite right for the programming task of the moment counts as interest on that debt."
"Entire engineering organizations can be brought to a stand- still under the debt load of unfactored implementation, object-oriented or otherwise." -- Ward Cunningham
TECHNICAL DEBT is a term given to the costs associated with defects and other unresolved issues during or at the end of a development project. This concept reflects the implied cost of corrective work that results from selecting a quick and easy solution (often, to meet a time deadline), instead of implementing a more complete solution.
In other words, "Get it done and out the door." On a project timeline this looks good, but in the long term, may require more maintenance costs and a higher risk of defects.
Technical debt may have one or more causes, such as:
- Time pressure
- Overly complex technical design
- Poor alignment to standards
- Lack of skill
- Suboptimal code
- Delayed refactoring
- Insufficient testing
- 3rd-Party Code Improvements
Some time is bought by generating Technical Debt, but it is not free. Does this mean technical debt should never be accrued? Yes and no. In an ideal world, The code should always be perfect, and the time should be taken to write all solutions with a mind for the future.
Payment of technical debt can occur immediately or later. A small payment can be made now to meet a deadline, but at what cost later? The costs later can be significant. Consider those potential costs for a moment:
- Rework to analyze and correct the defect later.
- Workarounds that slow productivity.
- Loss of functionality until the issue is corrected.
- Loss of revenue potential.
- Loss of customers due to visible defects.
- Downstream dependencies leading to additional issues and debt.
While creation of technical debt decreases the immediate costs and shortens deadlines, this does not measure the true impact of ongoing debt. Before signing off, be sure there is complete awareness of the ongoing implications. EYES WIDE OPEN is the key mentality to managing technical debt.
Before deciding to take the easy way out:
- Ask if we have to? If time pressure means the non-ideal, expedient solution is the only way out, go on and do it! If there is a little wiggle room, go on to consider ...
- What will the debt cost? How much of a drag will this put on future progress, and is the time being saved now really worth it when looking at the bigger picture?
From the very start, planned debt can be strategic in nature. This may be from a project developing a prototype or pilot. Part of the implementation is that it is completely understood and agreed on that it is a test run from the very beginning.
This type debt is an expected loss, but a loss that should be controlled and accounted for. Good record keeping is key to tracking all expenses and decisions (including rationale).
This debt us purely due to the human factor, otherwise known as "defects." Unintentional debt often exists because of defects because of human error, poor workmanship, or lack of knowledge. System updates will also cause code to fail, changing downstream functionality or adding security risks. Test automation may be used to identify these risks as fast as the code is written, so that they may be addressed immediately.
Unintentional debt is not limited purely to defects.
- Additional sources of unintentional debt may go back as early as poorly defined or heavily changing user requirements.
- Fairly often, a weak system architecture or poor database design can create dramatic increases in technical debt.
Before agreeing to any changes to a project and its deliverables, the potential downstream effects should be discussed prior to gaining approval.
This debt is the result of something unplanned, that cannot be avoided. This could be things like changes in dependencies outside of the project (hardware or operating systems or) or additional mandatory requirements being introduced during project development. When these types of things occur, some negotiation of the time, cost, resources, or features originally agreed upon may be in order.
[from SyntaxSeed (Sherri W)]
[Maintenance Debt] is debt that appears over time [and] no amount of careful planning can avoid it. [Also,] it snowballs if ignored.
This is debt that appears as underlying technologies (such as libraries, tools, and infrastructure) go through normal updates. This can be updates, version releases, or deprecation. These types of updates need to be accounted for due to both performance and security updates.
The key to managing technical debt is authentic and clear communication when it comes up. With this transparency, appropriate negotiations and decisions can then be made about how to address the technical debt.
- Challenge the whole team to think beyond the project to identify the ongoing impact.
- Automate testing, especially with repetitive tasks, to be sure of a solid execution every time.
- Monitor the team’s rate of progress. Investigate any slow-down, that could be an indicator of technical debt presenting itself.
- Monitor complexity: With high complexity, developers are more likely to break something when they are trying to fix something else.
- Manage and monitor defects as well as time to investigate and complete.
- Maintain appropriate test coverage. The target range of well written tests is 75 – 85 percent of code covered.
- Ensure the system architecture and database are designed knowing that the system functionality will grow over time.
Technical debt is not bad or good; It's just the nature of the beast when writing code. The key to managing technical debt effectively is understanding its use and addressing the debt in a timely manner. Acquiring technical debt may help to achieve a short-term goal, but one should have a plan in place to address it moving forward. While it is unrealistic to think technical debt can be avoided, it can be managed and minimized.
Single Responsibility Principle (or SRP) is one of the most important concepts in software development. The main idea of this concept is: all pieces of software must have only a single responsibility.