craigaspinall.com
I’ve moved!

For those of you following me on Tumblr, I’ve moved my blog over to GitHub Pages. For an explanation of why, please see my latest blog post over on the new site. It really boils down to having more control and being able to create and edit posts offline.

In the meantime, I’ll be leaving the Tumblr blog here. As soon as the DNS changes propogate, http://craigaspinall.com will point to the new site, but if you want to come back here for any reason, you will still be able to access it via http://www.tumblr.com/tumblelog/craigaspinall.

Note that there’s a new RSS feed set up at the new site, so if you’re subscribed here and want to continue to subscribe, you’ll need to subscribe to http://feeds.feedburner.com/craigaspinallcom.

Quitting Facebook

After listening to Mark Pesce’s controversial keynote presentation at LinuxConf Australia 2011 (and giving myself a couple of months to think about it), I’ve decided that the time has come to leave Facebook, and to encourage others to do the same. If you want to understand why, I strongly recommend you read Mark’s presentation, but here are the reasons in a nutshell.

The most valuable piece of information about you is your social graph and the communication that occurs across that graph. That reveals more about you, your personal interests, even your secrets, than anything else that you do online. And Facebook is watching and recording it all.

This might not be so disturbing if Facebook had not repeatedly let members down with regards to the privacy of their data. Or if people actually understood what information they are divulging to Facebook. Whilst many have pointed to the likes of Microsoft and Google as potential dystopian “big brother” overlords, Facebook is probably much better poised in reality.

So I’m making my own (sadly insignificant) stand by quitting. I encourage you to do the same. 

Extending classses at runtime with Groovy

I gave an introduction to Groovy at our local JUG this week and didn’t quite manage to make it through all the material I wanted to cover, so I decided to add the missing content here! The part I missed out in the meetup was how to extend a class at runtime via it’s metaClass.

If you add a named closure to the metaClass of an existing class, then it essentially becomes available as a method on that class. In this example, I’ve added a containsOnly(Collection) method to the Collections class, which returns true if two collections have the same content but not necessarily in the same order.

Collection.metaClass.containsOnly = { Collection otherCollection ->
    delegate.containsAll(otherCollection) && delegate.size() == otherCollection.size()
}

a = [1, 2, 3, 4]
b = [2, 4, 3, 1]
c = [2, 4, 3, 5]
assert a.containsOnly(b)
assert !b.containsOnly(c)

‘delegate’ is an implicit argument referring to the object on which the containsOnly() method is being called.

In the following case, I have extended the Collection class again to add a choose(int) method, which selects a supplied number of entries from the collection, chosen at random. Note that the ‘return’ keyword is optional, I’ve used it here for clarity.

Collection.metaClass.choose = { int numberOfEntries ->
    if (delegate.size() <= numberOfEntries) {
        return delegate
    } else {
        List previouslyUsed = []
        List chosen = []
        while (chosen.size() < numberOfEntries) {
            int index = new Random().nextInt(delegate.size())
            if (!previouslyUsed.contains(index)) {
                chosen << delegate[index]
                previouslyUsed << index
            }
        }
        return chosen
    }
}

a = [1,2,3,4,5,6,7,8,9,10]
one = a.choose(1)
assert one.size() == 1
assert a.containsAll(one)
five = a.choose(5)
assert five.size() == 5
assert a.containsAll(five)
twelve = a.choose(12) // should only return 10!
assert twelve.size() == 10
assert a.containsAll(twelve) 

My final example extends the String class so that you can easily cast it to a Date instance using a fixed conversion format. Groovy uses this syntax for casting (which is much nicer than Java):

'08/08/1988' as Date

Under the hood, Groovy calls the asType(Class) method to perform the conversion, and that already supports casting to a number of different types. To add Date casting I had to replace the existing method definition. So that I didn’t lose the original functionality, I captured the original method and delegated to it if we’re not trying to cast to a Date.

def oldAsType = String.metaClass.getMetaMethod("asType", [Class] as Class[])
String.metaClass.asType = { Class targetType ->
    if (targetType == Date.class) {
        Date.parse('dd/MM/yyyy', delegate)
    } else {
        oldAsType.invoke(delegate, targetType)
    }
}
'08/08/1988' as Date
What did I learn from my 30 day challenge?

I missed my goal of 30 posts in 30 days by 5. In the end, working, blogging, podcasting and parenting took it’s toll and I spent most of last weekend sleeping instead of doing anything meaningful or useful! However I did learn a lot in the 25 posts I did manage to get out.

On average it took me about an hour to complete each post. This is much longer than I was hoping to achieve. Some of the shorter opinion pieces were done in less time but all the technical posts took at least that long.

It’s good to get things off your chest but the posts I enjoyed the most were the technical ones. And even then, it wasn’t so much the writing of post as the learning experience. I’ve already referred back to some of the technical posts to look at my own example code for things I am doing at work, so the objective of being a memory jogger has been fulfilled. It’s certainly convinced me to publish all the random experiments I do somewhere, either in free and open source projects or on the blog, just so that I don’t lose them.

There’s been a surprising amount of reaction to the blog in terms of likes and comments. I’ve gained a bunch of Twitter followers as a result. I say it’s surprising because a) that wasn’t a goal b) I didn’t expect anybody to read it and c) I didn’t really expect anybody to enjoy it that much!

If you followed along and have any constructive criticism then please feel free to comment. I’ll probably continue to post the technical content and the odd opinion piece (when something gets me fired up), but don’t expect a post a day from now on!

Fake economy

I’m creating a DVD of my eldest daughter’s school dance concert because it wasn’t professionally recorded and all the parents would like a copy. Being the type of person that I am, I want to make it look reasonably professional, and with iMovie and iDVD that’s fairly simple. But I also wanted to print labels for the DVD, so that the discs themselves look good.

Somewhere between Blighty and Oz I’ve lost my CD label press, so I went into OfficeWorks in Brisbane to get one, and to pick up some ink cartridges because the printer is low on ink. The cheapest CD label press they had was $25 and a pair of ink cartridges (colour and black) were almost $70! When I bought the printer it was less than $95!

I was shocked by how fake the printer economy has become, with the ink costing nearly as much as the printer! In the UK Lexmark in particular had a bad reputation for loss leading on the printer and in some cases charging more for the ink than the cost of the printer! These days all printers are built down to a price and all the manufacturers make it up on the ink. No wonder they go so far out of their way to dissuade you from using third party ink!

I decided not to pay $95 for some ink and a label press. The DVDs I have are printable so I actually spent an extra $20 and bought a printer that can print directly onto the discs. It will look more professional and I get a warranty out of it too. I’m sure that the ink cartridges supplied won’t be completely full, but they’re individual cartridges unlike my old printer, so it should be more economical to run, and I can buy cheaper third party ink for the old printer and not worry about the consequences!

The role of automated testing

Over the last week I’ve had a lot of discussions about the underlying motive of the roles that my colleagues and I are currently performing. We are responsible for improving the quality of software being produced by the teams we are involved with, and the main focus of our recent work has been creating automation tools to assist the testers. There are three possible motives for our roles:

  1. to reduce costs
  2. to increase productivity
  3. to improve quality

For us it’s a simple case of improving quality but that doesn’t necessarily mean that our leaders have the same motives. In fairness they do overlap, but focusing too much on any one of them can be to the detriment of the others.

For example, if you want to reduce costs and automated testing makes the testers four times more productive, then in theory you can remove three quarters of your testers without any loss of quality or productivity. Of course the theory and reality are quite different! Similarly, if you go all out for quality, you may need more people or tools or equipment which will result in increased costs, and progress may be slower.

The catalyst for the discussions was that we just found out that the number of testers is being reduced on one of the projects we’re working on and we were horrified. We were very concerned that the work we have been doing was being used to justify cost reductions but fortunately that isn’t the case (at least this time around).

Since our goal is to improve quality we expect that any cost savings we enable during development are re-investing into improving quality in other ways. This should include freeing up the testers to do more exploratory testing, but could also include things performance, security or usability testing that often get overlooked.

Even with that investment, we expect that there will still be an overall reduction in cost, simply because less defects will get to production. The cost of fixing defects increases exponentially the later in the process they are found, because more and more people become involved in the development, testing and technical support of the fix. Unfortunately the total cost of ownership is not easy to quantify and rarely gets the focus it deserves.

Episode 18 of the Coding By Numbers podcast (which I co-host) has a much more in depth discussion on this subject if you want to hear more!

Is Haskell actually a simple language?

Whilst I was writing the previous post about learning Haskell, I was reminded of a post by Martin Odersky about the complexity or otherwise of Scala. In that post he tries several metaphors to determine what “simple” really means, finally settling on Duplo versus Technics Lego. You can build anything with either (just as you can with turing complete languages) but a solution built with Duplo is unlikely to be as elegant as a solution built with Technics.

I like his comparison because it shows how much “simplicity” is a concept that means different things to different people. I’m starting to think that Haskell is a really simple language, even though I’m finding it difficult to learn!

One of the relative measures of complexity used in the article is the number of keywords in a language. Carlos Quintanilla’s comparison of CLR and JVM languages ranges from 139 to 31 keywords. Haskell has just 20!

And the more I use the language, the more it strikes me as being ruthlessly consistent. Take functions for example:

add :: Int -> Int -> Int
add x y = x + y

Nominally you can read this as a function called “add” that takes two Int parameters and returns an Int. Except it isn’t. It’s a function that takes an Int and returns another function that takes an Int and returns an Int! Which means you can do this:

plusOne :: Int -> Int
plusOne = add 1

I’ve defined a “plusOne” function by fixing the first parameter of “add” to 1, which returns a function that will always add 1 to whatever value is passed to it. By applying the same principle again we have a function that takes no arguments and returns an Int.

two = plusOne 1

This concept is one of the reasons why I’m struggling with Functors. It seems mind numbingly simple to me and yet so mind bogglingly powerful at the same time! And that is the paradox I keep banging my head against!

Haskell’s type system made me cry!

My functional programming with Haskell journey continues and every time I think I understand something, I discover there’s another layer of complexity underneath the one I just peeled off! There are so many metaphors that spring to mind that I’m just going to avoid them all!

What I’ve found so far is that I typically go through three or four stages of learning functional concepts. In the first stage I don’t understand it at all. In the second stage I start learning matched pairs of input and results, so I can start to use the concept but I don’t understand how the input is transformed to the output. In the third stage I start to get that understanding of how it works as well as what it does. And in the fourth stage I realise how much more there is that I don’t understand yet!

This week I really started to understand Type Classes and Monads, only to discover that Monads are just the tip of the iceberg. My brain then started to melt as I went back to stage one and two with Functors and Applicative Functors!

It’s also beginning to dawn on me just how amazing the Haskell type system is. One of my friends once said that Haskell’s type system made him cry. Not tears of pain but tears of joy at how elegant it is!

One of those days!

Do you ever get the feeling it’s going to be one of those days?

Last night I was trying to publish the latest episode of the podcast but the ADSL connection was down. It did come back up but only certain sites were accessible and the podcast file server wasn’t one of them! So I went to bed and got up early this morning to upload the files instead.

Except when I got up I still couldn’t access the server. Thinking it might be some latent state in the router from last night I reset it, only to lose the ADSL connection altogether!

After wasting another ten minutes trying to coax it back into life, I set off for work. For the first time, the bus I catch was so late that I arrived at the train station just as my train was pulling away.

So now I’m sat on the platform feeling sorry for myself and writing this blog post. And it’s just started to rain!

Tackle the technical debt first

In my last post I talked about the large refactoring I am doing. One of the reasons that this is a large refactoring is because I have been putting it off. I wanted to deliver something to the customer. I kept telling myself that if I just went with what I had I’d soon have something to give them and then I would have some breathing room to refactor. Of course thats a complete fallacy!

What I actually did was rack up technical debt. I kept adding more code that was dependent on API that I knew needed to be refactored. That meant the new code would also have to be refactored when the API changed. The net result is that I still wasn’t able to handover what I wanted when I wanted to, and now I am having to take a couple of days to perform this refactoring, which is delaying the delivery even more!

I’ve made this mistake before and I should have known better, but the pressure I was putting myself under (it wasn’t even the customer) to deliver got the better of me this time. Hopefully I learned from my mistake. I think I’ll print the quote by basketball coach John Wooden: “If you don’t have time to do it right, when will you have time to do it over?” and pin it on the wall of my cubicle!