Recently we updated our definition of tech debt tech debt. As a follow on to that article, this post goes into areas that are not tech debt, but often confused or confounded with tech debt in many companies.
Tech Debt is a Conscious and Planned Act of Commission – Not Errors and Mistakes
Specifically, errors, mistakes and application issues resulting from ignorance are NOT deliberate decisions and are NOT tech debt. We would not take on financial debt ‘by mistake’ – accidental financial debt often constitutes fraud! Therefore, the whole metaphor for financial to technical debt breaks down completely if we start lumping in all the other potential mistakes in designing, coding and maintaining a system over time with tech debt – which is the conscious and deliberate decision to delay implementing something in an optimal way.
Calling all our mistakes and errors of omission tech debt also makes it less likely we will learn from them and erodes trust with our key stakeholders in Business, Product, Sales and Service. Calling these types of mistakes what they are – unintentional errors - and being clear about what we learned from them and what we will do different going forward helps us get BETTER and improves trust across our cross functional teams. Trust is engendered when we admit our mistakes, strive for transparency in our interactions with our key stakeholders and focus on continuous improvement as an overall integrated product team.
To help bring clarity, following is a list of examples of items that we do not consider tech debt:
- Errors in design that we didn’t make deliberately as part of trade-off to speed time to market (impacting scalability, resiliency, user experience etc.)
- Errors in coding/defects
- Inadequate documentation
- Ignorance of the right way(s) to do something
- Failure to unit test UNLESS it was a conscious decision to speed time to market TEMPORARILY
Researchers in Brazil published a paper titled Towards an Ontology of Terms and Tech debt which is helpful in further categorizing where errors may occur. Tech debt is a deliberate and willing conscious choice during the design, implementation or ongoing care/feeding and sustaining innovation of an application - most often to improve time to market. However, errors can also happen anywhere in the process or in the system itself, which makes this categorizing of system issues equally useful for tech debt as it is for errors of omission or commission.
Tech debt is a deliberate and willing conscious choice during the design, implementation or ongoing care/feeding and sustaining innovation of an application - most often to improve time to market.
Having a mental model and a common vernacular for errors or tech debt is helpful in an organization so that there is a common understanding of the ledger of items to be fixed. It also helps focus teams when certain areas of an application, team or process that have more chronic or systemic problems and need strategic focus for improvement.
Neglect is Not Tech Debt
One of my favorite quotes regarding inadvertent mistakes in an application is “tech debt is not just a mess – a mess is a mess”. In this case the authors refer to another ‘catch all’ for the evolution or devolution of a software system over time. That is, how should we think about and classify the gradual entropy or ‘bit rot’ when a system is worked on, usually over many years, and with many developers such that it becomes more unwieldly and complex to understand and therefore much harder to add new features to - IF ongoing strategic refactoring is not being done all the time.
Just like your house, if you don’t change the air filters and put salt in the water softener, things will break down and/or become unhealthy. This type of ‘neglect’ debt is also NOT tech debt. Neglect debt (not keeping up on maintenance, software patching, etc.) is an act of omission – Tech debt is an act of commission we knowingly make in favor of faster time-to-market with a plan to address later.
Neglect debt (not keeping up on maintenance, software patching, etc.) is an act of omission – Tech debt is an act of commission we knowingly make in favor of faster time-to-market with a plan to address later.
The need to constantly refactor a system is something teams must plan for and take inventory of using standard code scanning tool, code reviews, etc. The most important point here is to be proactive as a team in understanding and defining these types of issues and attempting to quantify how they impact team velocity such that you balance the time spent keep the system healthy on an ongoing basis.
So what are things we can do in order to ensure we are not drowning in tech debt as well as the mistakes we inevitably make when building or evolving a system?
- We can start by looking for these issues as part of ongoing development pipeline: Tools that are helpful include Sonar, Semmle, embold, codefactor.io, and the list goes on depending on your coding platform and/or language choices. Other tools like Blackduck also identify many issues, security or otherwise.
- Separate mistakes from tech debt: Put in place a simple process and standard vernacular for categorizing and prioritizing tech debt as well as mistakes and track and review often.
- Tag stories, bugs, and tasks: Use a tool like jira to understand the amount of work necessary and allocate resources appropriately
- Perform code reviews for all pull requests according to established standards
- Conduct broader quarterly look back reviews to highlight lessons learned to prevent re-occurrence of the same issues and share learnings across teams and the organization where appropriate.
- Allocate capacity to address debt: Perhaps most importantly, allocate capacity to address on an ongoing basis and prevent a system from decaying over time.
Just the simple act of consistently categorizing debt not only makes it more likely we will plan for it and fix it but also creates a common vernacular and understanding across the team which will help reduce the creation of debt over time - by commonly defining “good” and also having an ongoing dialogue about managing this body of work proactively as part of your standard PDLC.
Tech Debt Through Acquisitions
A related topic is the consideration of tech debt through acquisition. When conducting technical due diligence, AKF Partners pays special attention to how the team has made decisions about their product up to the point of potential acquisition – how did they think through their design options? How did they weigh tradeoffs between optimal architecture and TTM at the point they are at in their evolution?
In conducting due diligence we usually find some opportunities for improvement. An acquiring company should consider those suggested improvements on the existing product (primarily architecture but can be also in process or org/people/culture) as additive tech debt they are now consciously incrementally taking on in addition to any tech debt that was previously known to the team being acquired or merged. So in essence, everything we have knowledge of that we believe should be prioritized to be fixed or improved, should be categorized as tech debt going forward, whether the team being acquired was aware of these gaps previously or not. And of course, as we actually operate the newly acquired platform, we may find new issues that would not be tech debt in almost all cases but should be added to the ledger and prioritized.
- Mistakes, errors and suboptimizations based on ignorance are NOT tech debt and do NOT align to the analogy of deliberate and conscious financial debt accumulation (However, teams should still seek to understand and quantify these non-tech debt application issues)
- Teams must proactively plan capacity to address both tech debt and errors/issues and the reality of software decay
- Be organized about the categorization of issues and errors and learn from them on an ongoing basis
In the next article in this series regarding being a good application steward, we will discuss “all other things maintenance” that are not tech debt and not errors/omissions/mistakes – primarily security fixes, currency upgrades and strategic changes in frameworks or languages based on improved tools/technologies that emerge over time.