The rails project I’m talking about is over three years old and has seen
commits from 27 developers in that period. These developers were both
co-workers, freelancers, off-shore developers and designers of different
levels of expertise.
Technical Debt Inventory
Needless to say, as most projects of this size and age, this one has plenty of
technical debt. Let’s make an inventory.
The test suite takes approximately eighty minutes to run. These are all
RSpec tests, including features. Luckily we can split the entire suite up
into smaller parts using Travis, but still the entire thing takes about
The main cause for these slow specs is a lack of understanding about how to
write good tests. For example, testing if search and pagination works,
someone thought it fine to create fifty ActiveRecord objects in a before
These big offenders are easily remedied. Others are a bit harder, as
some specs require an ellaborate tree of models to test functionality.
This project has no cucumbers to discuss and review features with
Product Owners. These cucumbers would have been awesome to discuss
features both with product owners and team members. But at the start of the
project cucumber was deemed too much hassle and Rspec feature specs were
The main issue now is that the line between features specs and unit specs
is a thin one and people often mistake one for the other. This is probably
one of the reasons so many specs create many models and make the entire
There are parts of the code that are not well tested – or not at all. This
is a dangerous one. Because, from the start, nobody monitored test coverage or
did proper code reviews, there are patches of code that are not well tested,
and there are some that are not tested at all.
There are various factors to why this happened, but lack of pair
programming, code review and pressure to finish a product have resulted in
Lots of smells and lots of noise. All the points above indicate there
is a certain amount of technical debt in this project. Another pointer are
code smells. To name a few I’ve seen over the past few months:
- Long methods
- Conditional Complexity
- Data Clumps
- Alternative Classes With Different Interfaces
- Indecent Exposure
- Uncommunicative Names
- Divergent Change
- Shotgun Surgery
- Lazy Classes
- Inappropriate Intimacy
- Train Wrecks (or Message Chains)
- Feature Envy
All of these found their way into the project, sneaking in besides our best
efforts to pair program and code review almost religiously.
Why does this matter?
The product we ship works. Although the specs take a long time to run, and
there are some code smells in there, the suite is actually green and we
have confidence the product works as expected.
So why complain about technical debt? In my opinion as a software
craftsman, softare should
- be clean and readable
- allow for change
- be well tested
Well, the code works. But clean, readable, easy to change and well tested are
Responding to change is still possible, but it’s a bit more painful than
it should have been. There are some untested patches of code that we would
really would like to see tested. And of course, code should be readable and
easy to understand. We don’t always have these things and it’s holding back
So, you have some Technical Debt on your hands
Recently two new developers joined this project and they immediately asked
the right question:
What can we do to make this project better?
In my opinion, as a software developer, this is the one magic question.
What can you do, right now, to make this project better.?
Besides the fact that you ask yourself what you yourself can do, there’s
another important component in that question: better.
It’s not about fixing all the things. It’s about improving the things you
touch just a tiny bit. Over the course of a few weeks or months these small
improvements start to add up and really make a difference.
It’s often called the Boy Scout Mentality. Leave things behind in a better
state then how you found them when you arrived.
So, although the projects works fine, we as developers are now constantly
improving the code and specs we touch.
Eliminating Technical Debt
Just like 100% Test Coverage, Low Technical Debt is not and end goal, but
an ongoing mission.
Your application will always have some form of technical debt. Even if you
have the best programmers in the world, it will happen.
What you can do is focus on minimizing technical debt.
The team currently working on this project now has formulated a few
basic guide lines to help us bring down the technical debt of this project.
We are not going to do it over night, but in a few months time we will have
made quite a dent.
The overall objective is this:
Whatever you do, leave it in a better shape than you found it in. This
goes for code, documentation, specs, whatever.
When implemting features or changes, we use a few simple steps to help us
- Is this code I’m about to change well tested?
If not, fix it now. Update those specs to be more efficient, handle
the edge cases you see popping up right now. Write cucumbers.
- With your improved specs green, refactor the existing code
Your new specs suite is fast and elegant. Use it to refeactor the
existing codebase to make change easier.
Congratulations, you have just made your life much easier. Note that you have
not written a single line of code yet for you new feature or change. But the
cleaning up you just did will greatly benefit you and the time it takes to
write this feature.
- Write specs for your change or feature
This is quite easy now, as it should add nicely to the changes you made
in the first step.
- Implement your features or change
Because you refactored most of the code smells out in the second setp, you
should be able to easily change your code.
These are four easy steps to minimize technical debt in your project.
You should not wait until you hit the technical debt limit of your project.
Minimizing technical debt is just as important as writing tests. It should
be a team priority from Day 1.
Minimizing techincal debt is not all too different from doing proper
test driven development. It requires rigorus discipline and skills. And just
like with tests, you will not handle that technical debt after this crunch
Next time you open a project, ask your self, “How can I leave this project
in a better state than I just found it?”