Post: Dealing with Technical Debt

This commit is contained in:
Ariejan de Vroom 2014-04-04 15:14:42 +02:00
parent c50e7275b3
commit 0387f1d961
7 changed files with 225 additions and 1 deletions

View File

@ -23,6 +23,7 @@ gem 'uglifier'
gem 'multi_json', '~> 1.3' # needed by uglifier gem 'multi_json', '~> 1.3' # needed by uglifier
# needed for tasks # needed for tasks
gem 'stringex'
gem 'rake' gem 'rake'
# needed to run nanoc autocompile # needed to run nanoc autocompile

View File

@ -75,6 +75,7 @@ GEM
rubypants (0.2.0) rubypants (0.2.0)
sass (3.2.18) sass (3.2.18)
slop (3.5.0) slop (3.5.0)
stringex (2.5.0)
systemu (2.6.4) systemu (2.6.4)
thor (0.19.1) thor (0.19.1)
tilt (2.0.1) tilt (2.0.1)
@ -111,6 +112,7 @@ DEPENDENCIES
rake rake
rdiscount rdiscount
sass sass
stringex
systemu systemu
typogruby typogruby
uglifier uglifier

27
Rakefile Normal file
View File

@ -0,0 +1,27 @@
require 'stringex'
desc "Create a new post"
task :new_post, :title do |t, args|
mkdir_p './content/posts'
args.with_defaults(:title => 'New Post')
title = args.title
filename = "./content/posts/#{Time.now.strftime('%Y-%m-%d')}-#{title.to_url}.md"
if File.exist?(filename)
abort('rake aborted!') if ask("#{filename} already exists. Want to overwrite?", ['y','n']) == 'n'
end
puts "Creating new post: #{filename}"
open(filename, 'w') do |post|
post.puts '---'
post.puts "title: \"#{title}\""
post.puts "created_at: #{Time.now}"
post.puts 'kind: article'
post.puts 'published: false'
post.puts 'tags:'
post.puts ' - tag1'
post.puts 'summary: |'
post.puts " Summary for #{title}"
post.puts "---\n\n"
end
end

View File

@ -106,7 +106,8 @@ pre
color: $focus-color color: $focus-color
#main #main
#welcome #welcome,
#note
font-weight: normal font-weight: normal
background-color: #F7F7F7 background-color: #F7F7F7
border-radius: 4px border-radius: 4px
@ -126,6 +127,7 @@ pre
p.meta p.meta
font-style: italic font-style: italic
color: lighten($text-color, 10%) color: lighten($text-color, 10%)
margin-bottom: 0
#older-posts #older-posts
h2.title h2.title
@ -145,6 +147,9 @@ pre
.post, .post,
.page .page
#note
margin-bottom: 1.6em
h1.title h1.title
font-size: 3em font-size: 3em
margin-bottom: 0 margin-bottom: 0
@ -158,6 +163,7 @@ pre
p p
text-align: justify text-align: justify
margin-bottom: 1.6em
p.meta p.meta
margin-top: 0 margin-top: 0
@ -168,6 +174,7 @@ pre
img img
border: 0 border: 0
margin: 8px margin: 8px
max-width: 80%
&.right &.right
float: right float: right

BIN
content/img/20140404-01.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -0,0 +1,183 @@
---
title: "Dealing With Technical Debt"
created_at: 2014-04-04 12:38:41 +0200
kind: article
published: false
tags:
- programming
- craftsmanship
summary: |
Technical debt is not a new phenomenon. I'm working on a Rails project
where there's plenty of technical debt to get in the way. Here's how
the team deals with it.
note: |
This is a cross-post from my original post a <a href='http://blog.kabisa.nl/2014/04/04/dealing-with-technical-debt/'>blog.kabisa.nl</a>.
---
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.
<img src="/img/20140404-01.png" class="center bordered" />
**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
fourty minutes.
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
block.
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
used instead.
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
suite slow.
**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
this.
**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
1. work
2. be clean and readable
3. allow for change
4. be well tested
Well, the code works. But clean, readable, easy to change and well tested are
debatable.
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
progress sometimes
## 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.
## Guidelines
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
along:
* **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
period.
Next time you open a project, ask your self, _"How can I leave this project
in a better state than I just found it?"_

View File

@ -9,6 +9,10 @@
.col-sm-12 .col-sm-12
.post .post
.body .body
- if item[:note]
#note
= item[:note]
= yield = yield
#appreciation #appreciation