Streets Ahead

Presents

Interesting Stuff

Ten Reasons Every Java Developer Should Learn Groovy (Part 2)

Picking up where we left off last week. Groovy provides immediate benefits over Java - and as stated previously - provides little effort to begin reaping the rewards. Rather than drone on - I'll just jump back into the list ...

5) Meta-Programming

Part of being a dynamic language means that we can dynamically add methods and properties at runtime. Every class that's accessed in Groovy gets wrapped in an ExpandoMetaClass which intercepts all method calls to said class. Using this wrapper we're even able to add methods to Java classes that are final - such as the String class.

We can see it in action with a simple example by adding a method to the String class to turn any string into pig-latin:

String.metaClass.pigLatinIze = { ->
    def vowels = ['a','e','i','o','u']

    def firstVowel
    def newPhrase = []
    delegate.split(' ').each{ word ->
        word.eachWithIndex{ v, i ->
            if(vowels.contains(v) && firstVowel==null){ firstVowel = i;}
        }

        def newWord = "${word.substring(firstVowel)}-${word.substring(0,firstVowel)}ay"
        newPhrase << newWord
    }

        newPhrase.join(' ')
}

//Run it
"Pig latin makes no sense".pigLatinIze()

It's also ridiculously easy to specify behaviour that should happen when a method doesn't exist - something that comes in particularly handy when you're developing your own Builder. By defining the methodMissing method in your class - groovy will know how to handle methods that don't exist.

class MyBuilder{
    def methodMissing(String name, args){
        if(name=="doAwesomeThing"){
            //do Awesome stuff here
        }
        else{
            throw MissingMethodException
        }
    }
}

4) Testing

In many situations it's easier to start building groovy into your test suite than anywhere else in you codebase. Groovy has JUnit built right into the groovy runtime and adds a few more assert methods as well as a few other convenience methods - but I've found groovy particularly useful for Mocking out classes.

Mocking

MockFor & StubFor

MockFor and StubFor are convenient classes for mocking your Collaborators in groovy. They are particularly useful when you're unable to inject the Collaborator into the Caller. The MockFor & StubFor classes were inspired by EasyMock so

MockFor example:

import groovy.mock.interceptor.*

class MovieAnalyzer {
    def isGood(movie){
        if(movie.hasGalifinakis())
            return true;
        else if(movie.hasSparklyVampires())
            return false;

        return (new Date().getTime() /2) ==0 
    }
}


def testTwitlightMovie(){

    def mock = new MockFor(Movie)
    mock.demand.hasGalifinakis { true }
    mock.demand.hasSparklyVampires(0..1) { true }
    mock.use{
       assert true == new MovieAnalyzer().isGood(new Movie())
    }
}

testTwitlightMovie()

StubFor is similar to MockFor except that the expectaion of methods called is order independent ...

Mocking as Maps

One of the great things about groovy is the use of closures. During testing it may be useful to mock an object using a map using a closure as the value.

def mockMath = [sqrIt: {n -> return n*n;}]

assert 4 == mockMath.sqrIt(2)

Spock

Spock is a powerful and expressive test framework for groovy. As with any groovy method - you can declare each test as a string - the difference with spock is that you're really supposed to define your tests in this manner. It provides a nice readable test case that anyone can quickly use to figure out what's going on - and if done right can serve as a nice source of documentation for your applicaton.

And for a simple meaningless example …

import spock.lang.*

class MathTest extends Specification{
    def "square root test"(){
        expect: "the squareroot of perfect square will equal an integer root"
        Math.sqrt(sqr) == root

        where:
        sqr |   root
        1   |   1
        4   |   2
        9   |   3
        15  |   4
    }
}

And because there's an error we get:

MathTest
 - square root test   FAILED

   Condition not satisfied:

   Math.sqrt(sqr) == root
        |    |    |  |
        |    15   |  4
        |         false
        3.872983346207417

   at MathTest.square root test(Script1.groovy:6)

Learn more about Spock here

3) Gradle

One of the pain points in any enterprise Java project seems to be dealing with build automation or dependency management using things like Ant and Maven. Gradle is a tool implemented as a groovy DSL that alleviates some of these pain points. First and foremost gradle build files are written in groovy - instead of XML which, in my most humble opinion, is a pain in the ass. Writing your build script in groovy means there's not a lot of language context switching going on when you move back and forth between adding features and updating your build process. Using a full featured language like groovy also means you have more flexibility while defining your build process and establishing rules and conditions to follow during build and deployment.

Discover more about Gradle here.

2) Functional Programming

While nothing new, it certainly seems that there is a growing affinity towards functional programming paradigms. There are certainly languages designed with a functional model in mind, but Groovy provides a syntactically familiar way to begin to embrace a functional mindset - something that can be difficult to do if you've spent most of your career in an OO world. Then as you get more advanced with your functional programming skills you can step up to more strictly functional languages such as Clojure, or maybe you'll bring some of those functional ideas back to Java. Below are a couple of quick examples of how do use functional techniques with Groovy.

def addN = {x, y -> x + y}
println addN(5, 6) // prints 11

def add5 = addN.curry(5)
println add5(10) //prints 15

// what you might call a reduce or foldLeft in functional terms
def str = ['one', 'two', 'three', 'four'].inject('zero') {acc, val -> acc + ' ' + val}
println str // prints 'zero one two three four'

Learn More

1) You pretty much already know it.

So that brings us to the final, and possibly most important, point. If you know Java you basically already know Groovy. Groovy is almost completely syntax compatible with Java. There are a couple of minor differences, but by and large you could take your .java file rename it .groovy and compile it with groovyc. And this, I think more that any other point is why Java developers should take a look at Groovy. Will it be the only language you use from now on? Is it the holly grail of languages? In reality its likely neither of these things are true, but its so quick and easy to dip your toe into the Groovy water, why not? So the next time you need to quickly process a bunch of rows from a DB, or quickly test out a web service API, consider adding another tool to your utility belt.

All the Java you already know, all the APIs your used to using, the IDEs, build systems, etc will still work when you start adopting Groovy. And as you use the language more and more you'll start learning the tricks that Groovy has up its sleave and you'll start writing cleaner more elegant code, and save time in the process. So the only remaining question is why not?

blog comments powered by Disqus