What is technical debt?

Technical debt occurs when we choose an easier, quicker or a less optimal solution during software development rather than a more robust one. As developers we do this all the time, take shortcuts in writing code so that you achieve a goal on time but the cost is ugly and hard to maintain code. The shortcuts might be okay in the short term, but they lead to increased complexity and maintenance issues later on. Technical debt is like a financial debt. With borrowed money you can settle a financial issue sooner than otherwise, but you will have to pay back that money with interest. Just like borrowing money to meet a financial need quickly, developers take shortcuts to deliver a feature faster. You may have solved an immediate problem, but you will eventually have to go back to repay that loan by refactoring that code. Otherwise the interest adds up in form of maintenance challenges, bugs and complexity.

Types of technical debt

For years, software developer practitioners have sought ways to classify technical debt. A guy called Martin Fowler published what he calls 'The Technical Debt Quadrant' which categorized technical debt into 4 categories:

  1. Reckless and Deliberate(Intentional)

This occurs when you deliberately take shortcuts when writing code and you have no plans to address the mess anytime soon. A good example is when a team is rushing to meet a tight deadline. They hard-code values, ignore best practices and skip writing tests. The team is aware that this will lead to a messy and a hard to maintain code in the future but they have no plans in place to fix these issues. This creates a reckless debt that will accumulate quickly.

  1. Reckless and Inadvertent debt

This refers to things you should have known as a developer but you didn't. A team of developers should understand their domain well, it's coding standards and best practices. A team that is always learning and eager to develop a sound industry knowledge will avoid accumulating this kind of debt. An example is when a junior developer is unfamiliar with architectural patterns like layering, builds a feature by tightly coupling the UI, business logic and the data access layer. The app works, but it's difficult to make changes or scale without breaking something. The debt is Inadvertent because the developer was not aware of the best practices but it's also reckless since the design choice will cause problems as the system grows.

  1. Prudent and Inadvertent debt

This is the technical debt accrued even though you took time to improve the team skills and implement the best practices. This is the hardest quadrant of technical debt to anticipate.It cannot be avoided and can only be learned by doing things. An example is when a team builds a large scales e-commerce application using the monolith architecture. This is the best practice available at that time. The product has issues with scaling and later on new patterns like the micro service architecture emerges which solves their problem. The team didn't know better at the time, so the debt was Inadvertent, but they now understand the shortcoming of the earlier decisions. This is prudent as the team is planing to address it.

  1. Prudent and Deliberate debt

This is a technical debt that occurs when you want to leverage to ship a feature/product faster. It results from a thoughtful decision making, balancing risks and rewards. An example is when a team prioritize to bring their MVP to the market fast to validate the product and secure funding. They choose to cut corners, such as a simpler but less efficient algorithm for now with the intention of refactoring it after launch. This is prudent because they have a strategy for dealing with the debt after the product gains traction.

Managing Technical debt

While some debt is unavoidable and sometimes even necessary, managing it effectively is crucial to prevent it from hurting the long-term software development process. Below are strategies you should use to manage and reduce tech debt.

  1. Regular code reviews

Teams should conduct regular code reviews to identify and address technical debt early in development. Code reviews catch issues, ensure coding standards compliance and encourages knowledge sharing between members. When developers know their code will be reviewed, they tend to write cleaner code.

  1. Regular refactoring

Refactoring is the process of improving the code without changing it's behavior. By regular refactoring, you can clean up messy code due to rushed implementations or poor design choices. It prevents debt from accumulating where it becomes unmanageable.

  1. Automated Testing

Implement automated testing practices to detect bugs as soon as possible. This ensures that changes in the code base don't introduce bugs or break existing functionality. Comprehensive tests gives developers the confidence that refactoring or adding new features won't break the system.

  1. Document Debt

Keep track of all technical debt and properly document it. For example when making a deliberate trade-off e.g skipping a best practice for the sake of speed, document it in the project wiki, explain why it was done and how it should be resolved in the future.

Conclusion

As a developer, you can't avoid technical debt. However, If managed properly it can impact the long term success of a project. Shortcuts and trade offs are sometimes necessary to meet tight deadlines, but leads to bugs and a high maintenance code. You need to adopt proactive practices such as regular refactoring, code review, automated testing and writing clear documentation to manage the the negative effects of technical debt.


Futher Reading


07Nov 2024

Optimal Asset Allocation

Asset allocation is an approach of spreading investment across different asset classes instead of investing on one, its a strategy to balance risk and potential return over a given time period. This involves a mix of stocks, bonds and cash, or money market securities.

07Nov 2024

Transitioning from TypeScript and Python to C#: Key Takeaways

Transitioning to .NET over the past few months and diving into C# to create web APIs has been an exciting shift from my journey with TypeScript and Python. I’ve been using ASP.NET Core for minimal APIs, specifically leveraging the ICarterModule