Monthly Archives: April 2014

Refactoring as a Displacement Activity

Refactoring is good right? We constantly read about how we should be writing simple and easy code to do the minimum necessary and refactoring it as we go to improve it and expand what it can do. Unfortunately, this can lead to some really bad habits, especially if it’s used as a displacement activity.

What do I mean by displacement activity? Well lets consider a hideous project that is under specced, under resourced and overdue. Our poor old developer is demotivated and drowning under a sea of requirements that they don’t know how they’re going to implement, but what they have done is written the code that handles the command line arguments. This code works to spec, is even tested and could be considered complete. But, it’s taking user input. It’s not as neat as it could be. In fact it’s quite messy.

So what does our developer do? Do they tackle the next in the long list of requirements and try and get closer to completion, or do they refactor the working code to make it nicer? While we all know they should be doing the former, all to often it’s the latter that happens. Our developer goes off and refactors the working code to make it nicer.

Having seen this happen on a number of occasions it got me to thinking what was going on here. Why mess about with the stuff that works when there is a pile of stuff that doesn’t work to be getting on with. The answer is brutally simple, it’s a psychological trick.

In order to feel that they have had a productive day our developer needs to make progress. By tackling the difficult, as yet unwritten features, the developer is taking a risk. They may not be able to complete the task in the time they’ve allotted. They may run into problems. They may get stuck. They may fail. By refactoring the working code, on the other had, they’re tackling a problem that they know they can solve; after all, they’ve solved it already. What they’re doing now is a refinement.

Of course, once the refinement is completed our developer is still left with the mountain of requirements to complete that they didn’t want to tackle, and they now have less time to complete those requirements, but dealing with that problem has been shifted to something we can deal with tomorrow. In the mean time “progress”, for a given definition of progress, has been made because the existing code is now cleaner. A classic displacement activity.

Taken to its extreme this kind of thinking can lead to making nothing absolutely perfectly. You tend towards, but never actually achieve, the perfect solution for your problem. This is compounded by the fact that as soon as you start dealing with the edges of software development (input and output) things start getting messy. Perfection can’t actually be achieved and you’ll end up swapping one compromise for another ad-infinitum. Annoyingly we know all about this pitfall. the KISS principle and MVPs are all about avoiding this type of displacement and producing something that is important: working code. The irony is that this “perfect code” that we’ve wasted time crafting will no doubt get hacked about later as the system grows and the missing requirements are added. One day we may learn.

OPML to Markdown

I’ve started using mind maps for various things and wanted to use them for taking minutes in meetings. The issue is that we usually record minutes in a markdown text format so I needed to be able to convert from a mind map to markdown. A quick Google gave me an example Gist in python, but it didn’t work on my Mac. On top of that, once I’d fixed those issues, it wasn’t really outputting things in markdown, just plain text.

I fixed up the code so it now goes from OMPL to Markdown using the root node as the document title, and presents the rest of the nodes as a nested list.

For a given example map:

Example

We get the output:

# Example Map

* 1st Level Child
    * 2nd Level Sibling
    * Another 2nd Level Sibling
* Another 1st Level Child
    * Sibling on Level 2
        * Sibling on Level 3

I’ve actually gone one further locally by setting #!/usr/local/bin/python at the top, moving the script to /usr/local/bin/opml2md, setting chmod 755 and putting some basic argument checking in place. I’ll leave those changes as an exercise for the reader as some bits are specific to my OSX install.

It’s always about the money

I was asked an interesting question today regarding which job should someone go for. The options in question were for a “boring” product, but with a good team, and for an “interesting” product, but for rubbish pay and the possibility of a full time job after a period of a few months.

As far as I’m concerned the above scenario really only has one choice, but in the conversation that followed it was pointed out that there are a few students out there who are unsure what path they should take when it comes to accepting Software Engineering job offers out of university. What I’m providing here is an expanded version of the advice I gave today. Caveat Emptor and all that.

Lets look at product first. I’ve worked on a product that, in its original incarnation, was a putrid, rotting corpse that sucked the very life from your soul. This was due to the hideous way it had been barfed into existence and the ridiculous choices that had been made in terms of architecture, language and structure. It quite literally broke two consultants while we were doing the analysis.

That exact same product, rewritten, re-architected and generally done properly was actually quite nice to work on. As a product it was as boring as hell, but as a job I had more fun there than I did on my next job which was, in theory at least, a much more “interesting” product.

As far as product (or service, or whatever you’re being employed to program) goes you really only care if it’s something sensible that’s going to continue making the company money (and therefore allow you to continue being paid), and that it doesn’t do something that you find morally reprehensible. You may also find, as I did when working in London, that your morals become somewhat malleable as the salaries increase.

So product is much less important the technology. Make sure it’s the technology you want to be working with. If the code has been around for any length of time, it’s going to be a steaming pile of crap. Deal with it. If it’s new code you’ll be involved in turning the nice new codebase into the steaming pile of crap that it’s destined to be. Such is the nature of most development houses. Either way you’ll have some days where you get to write little gems of code that make you proud, and others where you’re having to bludgeon some hack into the code just to make the damn thing work. May as well be swearing at a technology stack that you enjoy and doesn’t fight you back.

Team is also very important. You need to work with these people day in, day out. If the team is comprised of people that cause violent thoughts due to their behaviour and nature then walk away. In generally moving jobs every 2 years in IT isn’t going to raise any eyebrows, but can you really tolerate these people for that length of time?

So you’ve narrowed it down to a shortlist of things you are happy to work on, using technology you want to use, with people who won’t cause you to go postal. I’m going to assume you’ve already weeded out places that are too far away, or are otherwise impractical. You’re now left with the final thing: money.

Pro tip: up to a certain value, it’s always about the money.

If you’re stuck, go with the company that will pay you more. Money may not buy you happiness, but it sure as hell helps mitigate a lot of stress. Not having to worry about your next pay check, being able to afford treats, holidays away, shiny new kit, all these things can make life much easier.

Now you’ve made your choice, if you find yourself kind of wishing you hadn’t picked that place, strike it from the shortlist, start again.

Oh, and as an aside, anything that you’ve been promised is worthless unless you’ve got it in writing. Something in writing trumps vague verbal promises every single time.

Improving Google Drive on the Mac

I’ve been a Dropbox user for ages now, although I’ve never really been hugely active in getting referrals or other activities to increase my free space. Currently my account lets me store 3.8Gb of data. Until recently this has been fine, however, I also now have a few shared folders which are beginning to chew up some space. To mitigate this problem I’ve hived off just under a Gig of data to Google Drive, which I’ve recently installed. While Google Drive doesn’t really give me the in-app integration of Dropbox, it is quite a useful place to dump lesser used files and backups.

My problem is that the badges used by Google Drive are hideous and fugly, and that doesn’t appeal to my sense of good style. If you compare the Google Drive folder on the left in the two images below to the Dropbox folder on the right you’ll see what I mean.

dropbox googledrive

Googling to see if there was a way to solve this issue was, initially, fruitless, however, I came across something telling me where the Dropbox badges were within the application. They’re
icns files which got me thinking; did Google Drive use something similar? Turns out it does. The solution was simple, copy the Dropbox icns files over the Google Drive ones, reboot and voila.

As you can see from the two examples below, it’s not quite perfect. Again, Dropbox is on the left and Google Drive is on the right, and the Google Drive badge is offset lower and to the right. Still, it’s a huge improvement.

dropboxgoogledrivenew

The commands I used were simple, and include a step to backup the old Google Drive icns files. Obviously, we’re messing with the internals of an application here so Caveat Emptor and all that, and if you end up breaking it you get to keep both halves – please don’t come running to me.

cd /Applications/Google\ Drive.app/Contents/Resources/FinderExt.bundle/Contents/Resources

cp Blacklisted.icns Blacklisted.icns.bak
cp Shared.icns Shared.icns.bak
cp Synced.icns Synced.icns.bak
cp Syncing.icns Syncing.icns.bak

cp /Applications/Dropbox.app/Contents/Resources/emblem-dropbox-unsyncable.icns Blacklisted.icns
cp /Applications/Dropbox.app/Contents/Resources/emblem-dropbox-uptodate.icns Shared.icns
cp /Applications/Dropbox.app/Contents/Resources/emblem-dropbox-uptodate.icns Synced.icns
cp /Applications/Dropbox.app/Contents/Resources/emblem-dropbox-syncing.icns Syncing.icns