Therapeutic refactoring
Technical debt and design stamina
Sometimes you meet some really badly written code, maybe it was written even by yourself. It's easy to blame (check out git blame) or despair, but what we really can do is to make bad things better.
It's definitely much better than complaining and feeling bad about yourself or you team, because you're working on awful code which only get worse... No one wants that. So you should probably include refactoring in your everyday work on software. Taking control over your life and making it better will make you a happier person (which reminds me that I should tidy up my flat ;).
Bad code comes from different sources:
- bad programmers with bad days
- lack of design or bad design decisions
- learning things and developing in suboptimal ways
- natural entropy of software (things get messier with time)
Without enough refactoring you will be on the blue line. Faster at the beginning, but slowing down more and more with time.
[http://martinfowler.com/bliki/images/designStaminaGraph.gif]
Have you been in a project like that? I've been and it's a really frustrating experience. With refactoring you can land on the red path, bringing more functionality faster with time.
It's like building a good library or framework which saves your time over and over when you build things.
Refactoring to the rescue!
I like refactoring. I've just watched a talk by Katrin Owen about Therapeutic Refactoring and it showed an excellent example of refactoring approach. But firstly, what refactoring is and how you should do it.
Essence of refactoring
Refactoring is a way of changing your code without changing its behaviour. It's usually makes code simpler, more DRY, easier to understand and sometimes even improve performance.
It's actually "changing everything without changing everything" - there are even coffee mugs for that.
Kinds of refactoring
Martin Fowler talks about three kinds of refactoring in his Workflows of refactoring talk.
They are:
- litter-picking refactoring - just simple improvements in code you see often
- comprehension refactoring - if you struggle with understanding some piece of code, after final understanding you should simplify it - you will avoid wasting your own and yours team time in the future
- preparation refactoring - when you develop code in evolutionary fashion, you won't know what will happen in weeks or months, but when this time happen, you can just pre-process your code (not changing behaviour) to make including new changes easier
Sounds awesome. But how do you do it?
There are some important phases in refactoring. First you should know exactly what the code does, make sure that you won't change it (tests) and then extract, simplify and improve your code in general.
Refactoring can be intimidating. Just imagine five hundreds line of code function which does some important work for your application, has no tests, misleading comments and 'XXX add next X if you read this method, will refactor when reach 10 X'. Uh...
Testing is a key
Never start refactoring with not working codebase. Make everything green, with automated tests you can free yourself of concern that you'll break something.
If they aren't any tests. Write them for the code you want to refactor. It's a good way of learning what code actually does - which is crucial in refactoring, because outputs should be the same.
Wear hats
Humans are bad at multitasking.
I would recommend performing coding new features and refactoring separately.
Doing both would probably slow you down - because you will both think about the refactoring and making code work in the same time and it adds cognitive load. Another disadvantage can be a premature refactoring.
Code should be working first, clean and beautiful afterwards.
An example of premature refactoring can be
removing code duplicates too early, when you don't know really how you
should generalize them. It often leads to messy util
functions with too many
options, which you still have to refactor later ;).
Wearing hats and focusing on one thing at the time is great. However you should swap hats frequently, smaller tasks are easier.
Learn how to refactor
If you're like most of the developers, you're probably more focused on building things, not refactoring them. Chances are, that you haven't learn all the methods and tricks of rebuilding and improving your code yet. It doesn't mean that you're a bad developer, it means that there is a easy way to improve your code and craft learning those new skills.
There are some good resources on refactoring. It depends on which tools you use - for java and ruby there is a Martin Fowler's Refactoring book, for mainstream languages such as C, C++ and java you can read Working effectively with legacy code by Michael Feathers.
However if you write in another language such as for example python like me, those books should still be fine.
Apart from books I recommend reading refactoring section on sourcemaking.
Incorporate refactoring into your everyday life
Planned refactoring is usually a bad idea. Your manager most likely would like to do something with bigger impact and bigger priority.
Code quality argument isn't evocative enough to convince people.
Try doing refactoring everyday instead. It's easier in small chunks. Red, green, refactor to the greater future ;).
Summary
Refactoring is good for you just like regular exercising and brushing your teeth. It's not the most exciting part of software development, but improving internal structure of your code can be a source of great satisfaction, .
Code will get better with time, well structured, properly tested, enabling you to deliver more features more quickly with time and with much less frustration.