Post: Dealing with Technical Debt
This commit is contained in:
parent
c50e7275b3
commit
0387f1d961
1
Gemfile
1
Gemfile
|
@ -23,6 +23,7 @@ gem 'uglifier'
|
|||
gem 'multi_json', '~> 1.3' # needed by uglifier
|
||||
|
||||
# needed for tasks
|
||||
gem 'stringex'
|
||||
gem 'rake'
|
||||
|
||||
# needed to run nanoc autocompile
|
||||
|
|
|
@ -75,6 +75,7 @@ GEM
|
|||
rubypants (0.2.0)
|
||||
sass (3.2.18)
|
||||
slop (3.5.0)
|
||||
stringex (2.5.0)
|
||||
systemu (2.6.4)
|
||||
thor (0.19.1)
|
||||
tilt (2.0.1)
|
||||
|
@ -111,6 +112,7 @@ DEPENDENCIES
|
|||
rake
|
||||
rdiscount
|
||||
sass
|
||||
stringex
|
||||
systemu
|
||||
typogruby
|
||||
uglifier
|
||||
|
|
27
Rakefile
Normal file
27
Rakefile
Normal 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
|
|
@ -106,7 +106,8 @@ pre
|
|||
color: $focus-color
|
||||
|
||||
#main
|
||||
#welcome
|
||||
#welcome,
|
||||
#note
|
||||
font-weight: normal
|
||||
background-color: #F7F7F7
|
||||
border-radius: 4px
|
||||
|
@ -126,6 +127,7 @@ pre
|
|||
p.meta
|
||||
font-style: italic
|
||||
color: lighten($text-color, 10%)
|
||||
margin-bottom: 0
|
||||
|
||||
#older-posts
|
||||
h2.title
|
||||
|
@ -145,6 +147,9 @@ pre
|
|||
|
||||
.post,
|
||||
.page
|
||||
#note
|
||||
margin-bottom: 1.6em
|
||||
|
||||
h1.title
|
||||
font-size: 3em
|
||||
margin-bottom: 0
|
||||
|
@ -158,6 +163,7 @@ pre
|
|||
|
||||
p
|
||||
text-align: justify
|
||||
margin-bottom: 1.6em
|
||||
|
||||
p.meta
|
||||
margin-top: 0
|
||||
|
@ -168,6 +174,7 @@ pre
|
|||
img
|
||||
border: 0
|
||||
margin: 8px
|
||||
max-width: 80%
|
||||
|
||||
&.right
|
||||
float: right
|
||||
|
|
BIN
content/img/20140404-01.png
Normal file
BIN
content/img/20140404-01.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 MiB |
183
content/posts/2014-04-04-dealing-with-technical-debt.md
Normal file
183
content/posts/2014-04-04-dealing-with-technical-debt.md
Normal 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?"_
|
|
@ -9,6 +9,10 @@
|
|||
.col-sm-12
|
||||
.post
|
||||
.body
|
||||
- if item[:note]
|
||||
#note
|
||||
= item[:note]
|
||||
|
||||
= yield
|
||||
|
||||
#appreciation
|
||||
|
|
Loading…
Reference in New Issue
Block a user