Technology
we use

Blog by
Finiata Team

Software Entropy: A Comprehensive List

Software Entropy: A Comprehensive List

Working hard to avoid technical debt is probably the best solution, but it’s likely inevitable that your organization has some. We’ve compiled a relatively comprehensive list of the different types of Technical Debt, or “Software Entropy” that your organization could have or be accumulating. 

Examples of technical debt

Lack of tests – unit tests, component tests, contract tests, integration tests, end to end tests

Bad design – wrong design decisions initially made (with the information at hand at that point in time). For example, the code is not easily changeable, incidentally complex, high cyclomatic complexity. Mostly due to lack of knowledge and experience, lack of peer review and professional growth mindset, or laziness

Lack of needed documentation – this includes documentation of the code, a setup readme, reasons for changes, the actual product, troubleshooting, and FAQs

Load issues – the system becomes unusable, slow, or requires a lot of memory or computing resources when there are a lot of concurrent users

Performance issues – specific functionality is slow or requires a lot of memory or computing resources

Ignorant management – pressure for features, not allowing quality work or time

Nondeterministic workflows – for example, the order of events is not guaranteed and cannot be relied on

Pending tests – tests that for various reasons are marked to be skipped

Compilation and deprecation warnings – ignoring warnings makes it harder to spot new issues, until things break without notice. There is a reason for these warnings

Manual regression testing as modus operandi – not investing in an automated test suite with reasonable coverage, requires going through slow and expensive manual testing after almost every change we make

Other types of repetitive manual work that could be automated – causing people to do work that a machine could do much at a much lower cost, which would free them to take on higher-level types of work

Bad architecture – not cohesive, too many dependencies, too coupled, not secure enough, doesn’t support required scale, not easily changeable, not reversible, not supporting deferring decisions

Premature optimizations – building things before they are needed, and might not be needed at all, such as scalability or reusability

Immature and unstable libraries – adding immature and unstable libraries, which require frequent mid to large changes as they continue to evolve

Unreadable code – code that is functionally correct and perfectly fine for the machine to execute but is hard for humans to read and change. We read code much more frequently than we write code

Brittleness – certain parts have many bugs, either due to introducing changes or from normal usage of the product

A high number of defects – not enough quality baked in

Outdated workflows  – requiring time-consuming workarounds

Tasks that need to be addressed – this includes things like API key rotation

Neglecting specific areas – such as an internal Admin tool

Code inconsistencies – a lack of or inconsistent coding conventions

Out of date elements – Includes languages / frameworks / libraries

Security issues – in the code, in the infrastructure, or in libraries we use

Lack of mechanisms – specifically for detecting security issues

Build Debt – the build process is either manual, or automated but not deterministic, or slow contractors/employees incentivized only by speed

Hero culture – get things done, no matter how it happens

Infrastructure debt – not enough testing environments, not compatible with the needs, no cost optimization 

Recurring operational issues or reliability – repeating complaints from customers or from internal users forces developers to handle them in an unplanned manner, repeatedly

Process debt – lack of product discovery (validating what we should build for our users), regular development process (including testing, releasing, and monitoring), disaster recovery, incident management

Requirement debt – requirements that contain contradictions, missing business cases, or UI/UX design

Rollout issues – downtime, breaking things on releases, damage to runtime or data, lack of external communication

Slow to release (low velocity) – processes, technology, or lack of knowledge that makes changes slow to release to the market, making the feedback loop very long

Product complexity & dead features – This also includes features that serve a tiny fraction of the users but have a substantial cost of the development maintenance

GDPR and PII violations – for example, exposing employees to real customers data (Personally Identifiable Information) without justification or giving employees permissions to functionality that they do not need

Tooling debt – tools that don’t support needs, out of date


Note: Many organizations use the term “Refactoring” for any technical work, but for precision, it’s worth mentioning that refactoring only refers to changing the code without changing any behavior (usually to make the code more readable or changeable). Bigger initiatives tend to be re-architecture rather than refactoring.

Understanding and managing software entropy

It may seem like software entropy can be found everywhere – and this isn’t entirely false. Avoiding technical debt might sound ideal, but in many cases it is unavoidable. The impacts of technical debt on a company, product, or feature vary greatly.

This is especially true in scenarios where you can gain from implementing something quickly to see how it performs, helping you to decide if it’s something worth putting more time, effort, and resources into. 

It’s crucial you understand how to identify your organization’s software entropy, then examine how to manage it. If it can’t be totally avoided, it’s vital to ensure that you are paying it back sooner than later.