Saturday, May 17, 2014

The magic of Groovy's with...

In a recent post, this blog examined the meaning of Closures' delegates and how they could be changed. This post will show how the ability to set the closure's delegate allows the language to become quite expressive where other languages remain cumbersome and verbose. For the purpose of example (and some fun) consider there is a groovy object drico, which represents the legendary Irish rugby player, Brian O'Driscoll

In case you don't know, Brian O'Driscoll is the best Rugby player to ever come from Ireland.  He could tackle, break, off load, ruck, jackal, kick you name it. An exceptional skilful athlete and widely regarded as one of the greatest players the game has ever seen.  In case, you don't know what Rugby is think American Football with no helmets, timeouts and a slightly longer shaped oval ball.   It is basically superior in every regard.   Anyway, so we have the drico object in our Groovy code suppose and we want to invoke a bunch of methods on it.  We could find ourselves doing:

RugbyPlayer drico = new RugbyPlayer();
...
drico.youWereAmazing();
drico.seriouslyYouWereAmazing();
drico.sayTotsAmazeBalls();
drico.howManyTriesDidYouScore();
drico.youreTheBest();
...
Wow, that's a lot methods being invoked on Drico.  There must be some Groovy trick we could do to lessen the text here? Remember, it is generally better to be coding than typing

Well we could put all the methods we want to invoke on Drico into a Closure and then set that Closure's delegate to Drico.
RugbyPlayer drico = new RugbyPlayer();
...
def dricoClosure = {
    youWereAmazing();
    seriouslyYouWereAmazing();
    sayTotsAmazeBalls();
    howManyTriesDidYouScore();
    youreTheBest();
    ...
}

dricoClosure.delegate = drico
dricoClosure();
Not bad. We have removed all the drico., and just gone straight to the method invocations but we have also added some code setting up the closure delegate. So one step forward, one step back. We can get rid of the one step back by using Groovy's with method. The with method is applicable to any Groovy object and accepts one closure. The delegate of the closure is the object with is being invoked on. This means we can do this:
RugbyPlayer drico = new RugbyPlayer();
drico.with {
    youWereAmazing();
    seriouslyYouWereAmazing();
    sayTotsAmazeBalls();
    howManyTriesDidYouScore();
    youreTheBest();
    ...
}
Using this approach means we have still removed all the drico. and gone straight to the method invocations. It also means we don't need to set the closure's delegate and we don't need to explicitly invoke the closure. The result is we have code with a much better signal to noise ratio and which is far more expressive. Until the next time take care of yourselves.

2 comments:

  1. Excellent example Alex, it's much more clear when i can see a concrete example rather than a contrived one, so

    Hacker alex = new Hacker()
    alex.with{
    writesGoodStuff()
    knowsHisBiscuits()
    deservesThanx()
    } // :-D

    ReplyDelete