Technical Debt may sound like a term that is only relevant to engineers. However, non-technical personnel, such as product managers and other business-oriented specialists, should take Technical Debt into account to improve their product in the long run.
In order to explain what Technical Debt (TD) is, why it is important for the product itself, and how to apply an MVP (design) pattern to it, let’s first define what MVP stands for and learn more about patterns.
What Does MVP Stand For?
MVP, in this case, does not stand for the Most Valuable Player, although basketball parallels can be drawn. Instead, MVP is an abbreviation for a Minimum Viable Product, which is a type of product that has just the right amount and set of features to make early customers satisfied. In other words, the product is not fully developed yet but relies on customer feedback for further development.
Imagine owning a shipbuilding company. The basic use of a ship or a boat is to help people sail across bodies of water — not drown.
As long as you build boats that help your early customers (for the sake of authenticity of this example, let’s say that they are fishermen who only want to fish in shallow water), you have a minimum viable product.
At one point, the fishermen may want to go fishing in the deep blue, which is why they may need their boats upgraded with certain features that would make them feel safer and sail faster. They would probably tell you about that, and you would proceed to the next stage in the product development.
If you do everything right, you might as well start building tankers one day.
So far, several MVP types have been recognized:
- Explainer Video — Instead of making a product, companies sometimes issue an explainer video to gain an insight into how many people would be interested in buying it. One of the most notable examples of this is the Dropbox explainer video, where the team working on Dropbox explained all the features of their product without actually developing it completely.
- Landing Pages — Companies often make landing pages before they commence working on a product and invite potential customers to buy it, only to start the development process if people are interested as expected.
- Wizard of Oz MVP — Inspired by the Mechanical Turk, companies make seemingly perfect products that appear to be AI-driven, scalable, and so on, but are actually manually adjusted to customers.
- Concierge MVP — Instead of making a product that solves people’s problems, companies sometimes manually assist people in their effort to solve the issue at hand, only to analyze the assistance process, scale it, and make a product that offers a solution.
- Piecemeal MVP — In short, this type of MVP uses various bits and pieces from other products and tools to create the basis for a new product.
- Raise Funds from Customers — This is one of the most popular ways to start a business; companies basically present their product blueprint to the public and are crowdfunded to start working on it.
- Singe Feature MVP — This approach is based on making a one-feature product and adding additional ones after the product has been launched.
If you are wondering what approach may be the best one in your case, take a look at the following picture.
What you want to achieve every time is the highest possible solution impact with the lowest effort required to implement it.
Before we proceed to discuss patterns, let’s summarize what MVP is.
MVP is actually not a product but a product development technique that involves finding the most convenient solution to launching your product as soon as possible.
In other words, MVP is all about solving the problem using the most basic solution.
What Is a (Design) Pattern?
Design patterns in software engineering are reusable solutions for some problems that often occur within a particular context.
In other words, if you have a problem and you know a pattern that could help you solve it, you don’t have to start from scratch and come up with a solution yourself. Instead, you can just apply design patterns that will make your life a little easier.
Design patterns are either formalized descriptions or templates that help programmers solve problems when they are working on a project.
When you look at it, patterns are everywhere around you, and we often have patterns that we use to solve everyday problems and overcome recurrent obstacles without thinking too much.
However, let’s stick to software engineering. In OOP, patterns can be creational patterns (e.g. prototype), structural patterns (e.g. proxy), and behavioral patterns (e.g. observer). Moreover, there are concurrency design patterns that deal with the multi-threaded programming paradigm (e.g. blockchain).
Are patterns always a good thing, though?
Patterns vs. Anti-Patterns
Patterns need not always be a good thing since many IT professionals develop bad habits that turn into destructive patterns, sometimes not even being aware of it.
Moreover, patterns evolve through time, especially in the IT industry. In other words, patterns that solve problems nowadays might become anti-patterns in the future.
Although the term anti-pattern mostly applies to code, we can always relate it to some non-technical examples.
Where I come from, priests used to visit villages in order to perform sacred rituals related to religious holidays celebrated by the villages (each village celebrates a different holiday). The priest would usually spend a night or two in every village, just before the festivity, and people got used to that.
However, the church managed to obtain a car, and the priest started visiting all the villages at once, without the need to stay over for a couple of days. Suddenly, his previous pattern became ineffective due to this new type of transport that made it much more convenient for him to visit all the villages in a shorter period.
In other words, he could have retained his previous behavior, but it was ineffective as the technology required him to make a different approach that was better-suited for everyone.
So, What Is an MVP (Design) Pattern Then?
Now that we know what MVP stands for and how design patterns work, we can combine the two into MVP design patterns. For the sake of clarity, let’s look at the design pattern definition once again.
Design patterns in software engineering are reusable solutions for some problems that often occur within a particular context.
The last word in the sentence above is context, and the context, in this case, is MVP development. Simply put, MVP design patterns combine product management and software engineering to create patterns that would launch the minimum viable product as quick as possible.
One of the examples of MVP design patterns is called the “strangler” pattern. The picture below sums it up pretty nicely.
Essentially, we get an outdated code that communicates with the browser via LoadBalancer. Our task is to refactor the code without the user noticing anything odd in the app/site that we are working on.
That is usually done by making minor updates over a period of time, gradually introducing a completely updated product without the user being aware of the fact that things have changed.
This type of pattern is used by Facebook, and one of the examples is Facebook Messenger that used to be a part of the platform until it became a standalone app that you can use without being a member of the Facebook community.
What Is Technical Debt?
When people hear the word debt, they don’t usually have positive feelings about it. In fact, it’s the word debt that evokes frowned looks in every possible situation, unless someone is paying back the debt they owe you.
However, technical debt can have certain positive aspects, which will be discussed later. First, let’s try to define what technical debt actually is.
Technical debt is a concept that programmers use to denote the extra work that turns up when code that was easy to implement is used instead of applying the best possible solution.
In plain English, whenever developers write code that is short-sighted and the easiest to write, instead of writing code that incorporates all the issues that may arise in the future, they are creating technical debt. This type of debt is extra work that they (or somebody else) need to work on in the future in order to refactor the code and make it more suitable for every possible occasion.
Why Does It Happen?
Technical debt can be created due to coders being either ignorant or unreliable, which is a type of unintentional debt.
However, TD is sometimes made intentionally, as coders don’t have enough time or resources to find the best possible solution. In some cases, people write bad code and create TD intentionally because they are aware that the future product is doomed to fail.
Wikipedia came up with an open-ended list of reasons why TD happens — feel free to add suggestions:
- Business pressure
- Lack of process or understanding
- Lack of documentation
- Parallel development
- Lack of alignment to standards
- Last minute specification changes
- Poor technological leadership
- Lack of ownership
- Delayed refactoring
- Lack of knowledge
Apart from being deliberate or inadvertent, attitude can also be reckless or prudent. Let’s take a look at Martin Fowler’s TD quadrant below.
When it comes to MVP, TD could be a good thing if the goal is to make a release as soon as possible. This is also one of the intentional ways to make TD and “pay it off” afterward.
“Technical Debt should be reserved for cases when people have made a considered decision to adopt a design strategy that isn’t sustainable in the longer term but yields a short term benefit, such as making a release.”
— Martin Fowler
What to Do About the Technical Debt?
We can cope with TD in a couple of ways:
- Henrik Kniberg’s way
- Sacrificial architecture
- Technical debt pattern
Let’s examine each of these.
Henrik Kniberg’s Solution
In Henrik Kniberg’s article called “Good and Bad Technical Debt (and how TDD helps)”, he investigates how to use TD to improve your code, making a sharp distinction between the good and the bad TD.
TL;DR — Kniberg believes that TD should always exist up to a certain extent, since writing perfect code is virtually impossible. We should have a habit of rating our code from 1 to 5. A five would mean that we have enough room to speed things up and create some TD. However, if our code rate goes below a three, we should consider paying the debt and improving our code.
Fowler is an optimist with his “couple of years time,” since we live in the world were some pieces of code don’t even get to celebrate their first birthday.
“… often the best code you can write now is code you’ll discard in a couple of years time.”
— Martin Fowler
Therefore, he suggests that we should write code with the notion in our minds that we are going to throw it away one day or, if you will, sacrifice it — hence the name.
Google uses sacrificial architecture because they design systems for 10x their current needs. Once the need becomes greater than the system’s magnitude, the developers at Google throw the code away and start writing everything from scratch.
Can We Make an (MVP) (Design) Pattern out of the Technical Debt?
So far, we’ve covered these four topics:
- What’s technical debt?
- Ideas and solutions regarding TD
- Basic MVP principles
- MVP patterns
Now that we have reached the final frontier of the scope of our knowledge, let’s take a step into the unknown and combine the knowledge gathered from the topics above.
Technical Debt MVP Design Pattern
Engineers, curb your enthusiasm. First of all, non-technical readers should understand a couple of terms that are going to be used in the process of explaining the technical debt MVP design pattern.
Efferent and Afferent Coupling
Sometimes our pieces of code (functions, classes, modules, etc.) are used by other pieces of code that depend on it, and this type of relation is called afferent coupling (Ca).
On the other hand, our code is also dependent on some other pieces of code, and that kind of relation is called efferent coupling (Ce).
Essentially, you should know that the function above can be executed in several different ways, depending on the input. However, some functions can be executed in more ways than others, thus having a greater cyclomatic complexity.
The idea is to make things as simple as possible and minimize the cyclomatic complexity in your code.
The Technical Debt Design Pattern
Now that we know what cyclomatic complexity is, we need to run it through every function in our code and determine the complexity levels in every class and module.
That is one way to understand which pieces of code need to be refactored first. However, classes and modules that have a high number of afferent coupling (Ca) need to go first since other pieces of code depend on them.
In the picture above (credits to the extremely good lecture/course by Neil Ford and Mark Richards), we can see that the first one on the list has the highest Ca number.
However, instead of using cyclomatic complexity, what about using Kniberg’s rating system to rate classes and functions on a scale from 1 to 5? We could use a plug-in (which exists only hypothetically) that would cover all classes and rate modules, as well as determine the number of other modules that depend on it.
In other words, the module that is the most complicated and has the highest number of modules that depend on it is the first part of the technical debt that we must pay off.
Essentially, TD pattern is a mix of Henrik Kniberg’s method and Efferent and Afferent Coupling.
Since patterns are best described via templates, here is a short step-by-step template on how to successfully use the TD pattern.
- Ask people on the team “How do we feel about the quality of our code?”. Pick any scale. That’s your Technical Debt (TD).
- You can use 1–5, where 5 is “beautiful, awesome code with zero technical debt” and 1 is “a debt-riddled pile of crap”.
- Measure efferent (Ce) and afferent (Ca) coupling.
- Chart TD and Ca next to each other.
- Conclude from 3. where your greatest and most relevant debt is.
- Pay it off!
Our team of engineers works day in and day out on developing blockchain products, and we strive to learn more from others. Get in touch with us if you would like to share your experience so that together we can help to grow blockchain community of builders even further.