Friday 5 August 2011

The 7 stages of refactoring

You have wanted to fix that module for ages. Just one look at it and you cringe. The documentation, the weird naming of functions, classes that are just plain weird. The module hobbeles along, but it is just plain dirty. The real programmer in you cringe, and when there finally is some time to refactor the module, you jump at it.

Step 1 - Desperation 
So you start to have a real good look at what you need to. Fix a class here, rename a few functions there, tear out a few functions here. Simple, right? Well, what at first glance seemed like a simple fix, a few tweaks, now envisions itself as a  monster of badly written code, ambigous comments and weird datastructures. You find members that are (seemingly) never used, functions that do the exact opposite of what they are named, etc. You cannot envision how anyone would be able to finish this is in 5 days (the time you have allocated).

Step 2 - Fixing it one line at a time
You acknowledge that this beast cannot be tackled in a single go, so you start with a part of the module and start with the small things - renaming functions, moving code blocks, create constants. You know that if nothing else you will at least not make the code worse.

Step 3 - Desperation (again)
But then, you hit a brick wall. You see the flaw in trying to reach a local minima, and see what you should do is a total rewrite. You do not have time for that, however, so you make a partial rewrite, by trying to reuse as much as you can from the old code. It will not be perfect, but you will at least try.

Step 4 - Optimism
You pound at the problem for a few days, slowly making progress and improving your code. You see how the code should be, the way the classes are bolted together. Yes, you are a few days overtime on your allotted time, but it is worth it.

Step 5 - Scram
You have used way too much time on this by now, and you feel more and more embarrassed for every standup. What should have been a simple refactoring turned into a total rewrite. And just because you wanted the code to be perfect. So you do some shortcuts, skimp on some documentation here, write it fast and dirty there. It will not be perfect, but it will do. You run the tests, and of course they all fail, but you do some quickfixes, and in the end it works fairly well. You pat yourself on the chest and do the commit.

Step 6 - Fixin time
Your rewrite was not perfect. Although it did pass its tests, they were too narrow and did not cover all the edge cases. So during a few weeks after the rewrite you apply more and more quickfixes, making the design more inelegant for each fix. It is no longer as perfect as you wanted it, but at least it is better.

Step 7 - Enlightenment
6 months passes, and you get another bugfix on the module. It has somehow gotten less pretty by the month. You see the inconsistencies and problems with the design that did not show up when you first had a look at it. And you see that what it replaced might not have been that bad in the first place, it did cover some cases that your code had not thought about. Someone on your team pushes for this to be rewritten, and you step back and let him - hoping that he too will in a few months will be enlightened.

Tuesday 31 May 2011

Query the Gnome screensaver using DBUS and Ruby

At my current work place, I need to send a mail every week with the amount of hours I have clocked in that week. Since I am a fairly lazy person, this can be somewhat problematic to remember (and results in annoying monthly mails from my manager). To help this, I have created a script to monitor my hours.

It is a simple script that works on the assumption that the first and last thing I do at work is something involving moving my mouse at the desk (the assumption is fairly correct). The script is a quick thing done in Ruby, with this essential part:


require 'dbus'

bus = DBus::SessionBus.instance
ss_serv = bus.service("org.gnome.ScreenSaver")
ss_obj = ss_serv.object("/org/gnome/ScreenSaver")
ss_obj.introspect
ss_obj.default_iface = "org.gnome.ScreenSaver"
while true:
  if not ss_obj.GetActive then
    on_work
  end
  sleep 10
end


This code basically polls the screensaver every 10 seconds and calls a function to say that I am currently at work. I have not included the on_work - function. This is also a fairly simple thing that uses a PStore to persistently store the first and last time the screen saver is not in use - code not included because of risk of embarrassment. 

1 less angry manager and learning more Ruby in the progress, that is what I call a win-win situation!

Sunday 15 May 2011

My new dev blog

I know this is somewhat last decade, but I finally decided to start a a small dev blog to get some experience with telling others (even if it might be the wall only for the time being).

So, not much planned yet to talk about, but it will probably be around what I work/have worked with, which is image processing, OpenGL ES, mobile computing, Ruby and search engines. So basically a nice potpourri of anything I am interested in :-)