Creating technical debt can be as simple as writing a draft and not refactoring it. That's exactly what I've done here. Now, I want to go through my code and see if it does, in fact, have technical debt.
I wrote a script to show me a quote from a light novel I'm a fan of. The script is called as overlord_quote
, and it prints a random quote made of 6 sentences. First, it matches all sentences with the search_term
, then selects a random sentence from the matches, and then prints it and 5 sentences right after it. It also tells you how many quotes are there for the search_term
. As simple as that.
Here it is, if you'd like to see the whole script.
Bad code
Here's some bad code from the script:
1 2 3 4 5 6 |
def random_quote quote_index = @quotes[rand @quotes.size] @sentences[quote_index...quote_index + TOTAL_SENTENCES_TO_SHOW].map { |quote| prettify quote } .join(" ") end |
So, this part of the code selects a random sentence from the sentences matching search_term
. On line 2, a random quote is selected from @quotes
and it becomes a quote_index
? That's hard to understand without knowing that @quotes
doesn't contain the matching sentences. It actually contains indexes of all the matching sentences. I chose to call the matching sentences quotes, but it's actually a misnomer. @quotes
should be called @matching_sentence_indexes
or something like that.
Line 3 isn't too bad, but #prettify
is a misnomer too. It actually removes all the \n
s from the passed sentence, and doesn't do any formatting or coloring.
Overall, the code suffers from bad naming and it's too low-level.
Is it technical debt?
So, is it technical debt? If it is, why?
Like a financial debt, the technical debt incurs interest payments, which come in the form of the extra effort that we have to do in future development because of the quick and dirty design choice.
From TechnicalDebt by Martin Fowler.
If I will need to fix a bug or add a feature in 3 months time, it will take more time to understand the script than if it was clean code with thoughtful naming. Thus, my quick and dirty code would have incurred extra effort to understand it. And that would happen every time I'd have to read it after a pause in development. If I had other people working on it, they'd have to put extra effort too. So, I can conclude that it is indeed technical debt.
Also, my code doesn't have any tests, so for every change, I would spend extra efforts to test it manually. You might consider this the interest payment on my technical debt.
How would this code look without the debt?
To give you an example of paying off some of the technical debt, I've refactored #random_quote
by extracting some methods:
1 2 3 4 5 |
def random_quote format_quote \ fetch_quote(starting_sentence_index: random_matching_sentence_index) end |
Here it is in full. Please note that I have paid off just a part of the debt, and it's not the best possible code, but it's better.
More examples of technical debt
You can find a list of bad code smells (they are technical debt too) explained, in Martin Fowler's book Refactoring: Ruby edition. The bad code smells are explained in English, without code, but are easy to understand.
How to pay off technical debt
If you're fed up paying interest on your technical debt, would you like to learn how to pay off the principal? My FREE course can help you start. You will learn how to refactor technical debt into clean code and how to keep its amount low in your code.
If you need help paying off technical debt to go faster, I can help.