Byte Journeys

Join me as I share insights and discoveries from my journey in the world as a software engineering manager by day and tinkerer by night.

Thoughts on Technical Debt

03 August 2023

In short, technical debt is the result of prioritizing rapid development or short-term solutions over long-term maintainability and code quality, leading to additional work and costs in the future. Although this sounds pretty bad at first, this is not always the case. In times where rapid development has to happen to validate product decisions or to move fast into a market this is totally acceptable and can be a valid strategic decision. However, engineering leadership needs to make sure that technical debt is addressed in the future. If not, this debt is paid on in the future by slower development times, buggy products, inefficiencies in the code and hard to understand and complex code leading to more delays in the future.

Technical debt needs to me managed in order to leverage it in the right way. This includes

  • Regularly assessing and prioritizing technical debt through tools like code reviews, static analysis, and backlog grooming
  • Allocating dedicated time for addressing technical debt, such as during “tech debt sprints” or setting aside a percentage of the team’s capacity to address tech debt
  • Ensuring clear communication and documentation to help future developers understand the context and rationale behind debt-inducing decisions
  • Establishing coding standards and best practices to minimize the accumulation of new technical debt
  • Encouraging a culture of shared responsibility for addressing technical debt among team memebers, including the product organization

It is all about balancing technical debt: Recognize that some level of technical debt is inevitable in software development, and focus on striking a balance between short-term needs and long-term sustainability.

How Google tries to measure and mange it

At the end of April, Google has published a paper on how they handle technical debt. In the paper they are describing how they conducted an empirical approach by asking their engineering workforce some specific questions through their quarterly engineering survey. Among the questions they have asked were:

  • To what extent has your team deliberately incurred technical debt in the past three months?
  • How often do you feel that incurring technical debt was the right decision?
  • How much did your team invest in reducing existing technical debt and maintaining your code?
  • How well does your team’s process for managing technical debt work?

The initial goal of this was to identify as set of metrics within each engineering field they have. They hoped that with these metrics they could get proactive about managing technical debt by getting in front of it and being able to predict where technical debt would occur. They failed in doing this, but were able to identify 10 categories of technical debt:

  1. Migration is needed or in progress: This may be motivated by the need to scale, due to mandates, to reduce dependencies, or to avoid deprecated technology.
  2. Documentation on project and application programming interfaces (APIs): Information on how your project works is hard to find, missing or incomplete, or may include documentation on APIs or inherited code.
  3. Testing: Poor test quality or coverage, such as missing tests or poor test data, results in fragility, flaky tests, or lots of rollbacks.
  4. Code quality: Product architecture or code within a project was not well designed. It may have been rushed or a prototype/demo.
  5. Dead and/or abandoned code: Code/features/projects were replaced or superseded but not removed.
  6. Code degradation: The code base has degraded or not kept up with changing standards over time. The code may be in maintenance mode, in need of refactoring or updates.
  7. Team lacks necessary expertise: This may be due to staffing gaps and turnover or inherited orphaned code/projects.
  8. Dependencies: Dependencies are unstable, rapidly changing, or trigger rollbacks.
  9. Migration was poorly executed or abandoned: This may have resulted in maintaining two versions.
  10. Release process: The rollout and monitoring of production needs to be updated, migrated, or maintained.

In the paper they have ranked these categories from most occurrence (number 1) to least occurrence (number 10) and clearly stated that the ordering is probably unique for every organization. Where do you stand with your organization?

You can read the complete paper here

And idea that came to my mind how we could predict where we have technical debt would be to look at our automatic dependency resolving mechanisms (Depfu etc.) and measure how quickly these dependency upgrades can be integrated. In my opinion this could at least give us an indication of how well maintained our codebase is and how easy it is to validate that dependency upgrades cause no harm (good test coverage etc.). What do you think?