Don’t worry, be Groovy (even if your job is boring)

It’s been 5 long years since my adoption of Groovy in my daily work. A long lasting love / hate relationship that entitles me to give advices to Java developers.

This topic came up when I was asked advices for the “modernization of their software” by a large company with a core platform and a number of developers writing business logic. Having worked in such context, one the many things that came into my mind was:

simplify developers’ life when writing lots of boring business logic code

In my head the word “Groovy” was flashing and couldn’t help it.
So ideally, what I’m going to list here are a number of things serving this specific purpose.

What it is

Groovy is a programming language running on the Java Virtual Machine. Contrary to what some others did, Groovy syntax is an evolution of Java, meaning that most of the syntax and concepts you generally use in Java are still there and available. This also means that most of your “legacy” code could benefit from the Groovy features without a rewrite.

The main goals of Groovy in this context are:

  • Simplify your code, automating some tedious, verbose work you would normally have to do in your program
  • Introduce its implementation of closures
  • Decorate default objects with extended functionalities using meta-classes
  • Allow you to decorate objects using meta-classes
  • Introduce loose typecast

Personal opinion alert!
Let me say this: I think Groovy does not belong to the small family of elegant programming languages. I’m not talking about the features, but the feeling it gives me when I read it. It’s not that I don’t like modern languages, but  there are several ways to design one and Groovy can sometimes be a bit too Javascriptish. But let’s face it, we’re hereby talking about the effectiveness of the language. The thing with Groovy is it’s damn quick to use, and in contexts similar to what I previously mentioned (lots and lots of boring code) it’s very very straight forward.

Hack #1 : beans!

Some developers think the concept of “bean” is evil because it has been abused and turned into the root cause of a number of tragic bad behaviors. Fine, I kinda agree with it, but you can’t deny you need them.
Let’s start with the most boring thing about beans:

Getters and setters

class Banana {
   String color
   int quantity
}

Forget about getters and setters. Groovy creates them for you as long as they have the default scope. The rules in getters and setters naming are the usual Enterprise JavaBeans. When you need to access a property exposed like this, you can either invoke the getter/setter or the property itself: in both situations the getter will be invoked instead.

Banana bananaObject = new Banana()
bananaObject.color = "red"
bananaObject.color
bananaObject.getColor()

And you can easily customize the behavior by overriding the default, as In:

class Banana {
   String color
   int quantity
   public String getColor(){
      return "C '+color
   }
}

And guess what, this also works with maps, as in

   HashMap<String,String> stuff = new HashMap<String,String>()
   stuff.put("id","511")
   println(stuff.id)

Constructors

We just annihilated the need of explicit getters and setters, but why writing boring constructors when a bean is just meant to store the variables you just declared? Here’s what Groovy gives us to kill the pain: an implicit constructor that accepts a map (more accurately, a LinkedHashMap) as parameter that will automatically fill the properties. As in:

Banana bananaObject = new Banana(color:"yellow", quantity: 5)

Hack #2: operators

How many times did you == instead of .equals(..)? Yeah, I know the feel. Even if you’ve been doing it right for 10 years, sometimes when your mind is elsewhere, you can waste an entire day on a joke like this. Moreover, in a language where pointers are not explicit, it gets even harder to teach a newbie why it is the way it is.
Groovy overrides a number of operators (and adds some too!) to better meet a slimmer programming style.
I’m going to list some interesting ones here:

  • == now works as .equals(..), and this is true also with collections
  • Access operators ‘.’ and variants. Now that getters and setters are out of scope, you’re going to “dot notate” a lot. What’s worse than chaining a number of dots and get a null right in the middle? Here’s the question mark operator!
    stuff.request?.date
    

    If request is null, it’s going to return null straight away.
    This fact also reflects in ternary operators that acquire the “Elvis operator” as in:

    stuff.request ?: new Request()
    

    If stuff.request exists, then return it, otherwise return a new request

  • The boolean comparison is also getting an interesting new thing that is common to most dynamic languages:
    if (stuff.request) {
     // do stuff
    }
    

    If stuff.request is null (or if it’s a string, it’s empty) then it’s false!

  • +, +=, – and -= work with lists as well, as in:
    ArrayList<String> list = new ArrayList<String>()
    list += "bananas"
    

Hack #3 : loose typecast

Loose typecast everyone? Now, I’m sure this is going to worry some Java purists, me included in many ways. Facing typecast problems at runtime can be a new experience to most of us, nonetheless there are good points in doing it when “it’s good”. You can use it or not, up to you.

def bananas = "123"

Love it, hate it, I’m not blaming any of you, after all you’re not meant to use it if you don’t want to. One thing for sure, if you’re not used to it, you better keep your eyes open.

As you can imagine, if you can declare a variable as “def” you can use that variable even if the compiler is not aware of what an object is made of.

void doStuff(def item){
   item.printMyBananas()
}

If printMyBananas() is part of item, great. If it’s not keep in mind it’s going to blow up at runtime.

Hack #4 : simplified collections

Collections are part of our daily routine. Lists and maps have various implementations of course, but you rarely fine tune what to use unless you really have to.

Groovy provides many ways to simplify your work with collections.

Arrays / Lists

  • As previously mentioned, Groovy overrides operators such as +, +=, -, -= to work with arrays.
    def list = new ArrayList<String>()
    list += "bananas"
    
  • Initialization is also a great great improvement, look at the following snippet and see how the left side of the assignment is actually deciding the type of the list.
    def arraylist = ["a","b"]
    // look how I'm calling simpleName and not getSimpleName() ...
    assert(arraylist.getClass().simpleName=="ArrayList")
    // default implementation is ArrayList
    
    LinkedList linkedlist = ["a","b","c"]
    assert(linkedlist.getClass().simpleName=="LinkedList")
    // becomes a LinkedList
    
    String[] array = ["a","b","c"]
    assert(array.getClass().simpleName=="String[]")
    // becomes an Array
    
    Set set = ["a","b","c"]
    assert(set.getClass().simpleName=="LinkedHashSet")
    // set is an interface, chosen impl. is LinkedHashSet
    
  • You often hope to get filtered and organized data from your dataset, but sometimes you find yourself searching, filtering and sorting in your lists. Groovy injects collections metaclasses with special closure capabilities that will ease your life a lot, especially if you’re dealing with collections of complex objects:
    public void flagUnderage(def people){
        people.each {
            if( it.age < 18 )
                it.underage = true
        }
    }
    public def getUnderage(def people){
        return people.findAll { it.age < 18 } } public def sortByAge(def people){ return people.sort { it1,it2 -> it2.age-it1.age }
    }
    public def getAges(def people){
        return people.collect { it.age }.unique()
    }
    
  • Slicing a list is also a pain, right? So here’s the deal:
    def map = [1,2,3,4]
    def sub = map[0..2]
    assert(sub.equals([1,2,3]))
    

Maps

  • As previously mentioned, accessors for maps are a big deal in Groovy. Look at this snippet:
    HashMap<String> map = new HashMap<String>()
    map["username"] = "Banana"
    assert(map.username=="Banana")
    assert(map["username"]=="Banana")
    
  • And as much as for lists, also maps have easier intialization:
    def defaultMap = ["a":1,"b":2,"c":3]
    assert(defaultMap.getClass().simpleName == "LinkedHashMap")
    
    TreeMap hashmap = ["a":1,"b":2,"c":3]
    assert(hashmap.getClass().simpleName == "TreeMap")
    
  • Groovy also introduces the same metaclass methods you can get for lists, but keep in mind you’ll be dealing with key/value objects, as in:
    def map = ["a":1,"b":2,"c":3,"d":4]
    def greaterThanTwo = map.findAll { it.value>2 }
    assert(greaterThanTwo==["c":3,"d":4])
    //hint... remember the == operator?
    

Hack #5 : Closures

The each, findAll, sort strange backet-wrapped things we wrote before are actually “closures”. If you played a bit with some programming languages like Javascript you very well know what they are.

In Groovy closures are just a weird hybrid of a method object and an anonymous class.

Closures are interesting because they can be used as regular variables, passed as method params, stored in beans etc.

// we declare a clousure accepting 2 parameters
def multiply = { a,b -> return a*b }

// and pass it to a method
assert ( execute(10,15,multiply) == 150 )
//*******//
public static int execute(int a,int b, def op){
    return op(a,b)
}

Hack #6 : Metaclasses

The content of this 6th hack will explain some of the weird things you’ve seen happening in the previous ones.
Every class in Groovy (whether it’s a Groovy class or Java class) has a property named “meta class”, a container of properties and methods that expands the objects capabilities without really extending them.
This technique kills your UML diagrams, so be ready to some drama with purists.
How many times you thought about “Why this stupid library had to return this stupid object without a #£$%& method?”.
In Java, at this point, all you could do is wrapping that object in a decorating object, or creating a static method to call where needed.
The meta class comes in play right here, as you can…

class MyBean {
  int a
  int b
}
/****/
public static void main(def args){
 /*
  * We add the multiply closure to the MyBean meta-class.
  * This is going to be present for each MyBean
  * object instantiated in this program.
  */
  MyBean.metaClass.multiply {
    return delegate.a * delegate.b
  }
  doStuff()
}

public static void doStuff(){
  MyBean bean = new MyBean(a: 10, b: 15)
  assert ( bean.multiply() == 150 )
}

Be very careful!  In the scenario I originally outlined, if all developers writing business logic felt free to edit the meta-class of common classes, clashes would be certain! My advice is the core of the platform should introduce commonly used closures to foundational classes, but that’s it!

Hack #7 : delegation

This is probably one of the most underexposed features of Groovy, but I find it very intriguing and useful, especially once you have mastered what’s shown in Hack #6.

Meta-classes are cool, but they’re far from being good when you need to extend a class functionality in an elegant, robust way, and if -again- you cannot extend a class, then you’re probably back to the old wrapper, right?
In  many cases, your wrapped object is fine as it is, all you wanted was adding some extra functionalities, most of the time just to improve the language of your domain. In your wrapper, you will end up adding your methods and proxying most of the methods your inner object exposes.
In Groovy there’s a quick way to do it: the Delegate annotation.

class Banana {
   @Delegate
   DBObject databaseObject
   
   public Banana(DBObject dbo){
     databaseObject = dbo
   }

   Date loaded
   void peel() { /*...*/ }
   void throwAt(Gorilla g) { /*...*/ }
}

Now if you look at this snippet, we have an object belonging to a class we cannot alter (DBObject), wrapped in a Banana class, that includes a “loaded” property and the peel and throwAt methods.
When you instantiate a Banana object, it will expose the declared methods and properties, plus all method an properties of the object we delegated to (in this case databaseObject).

Hack #8 : JSON serialization

Serialization and deserialization are hell, we all know that.
The reason is pretty simple: if you serialize one object, you want to make sure the agent that is going to deserialize it will reconstruct the very same object, without exception. For these reasons, serial numbers are used and every update of the various software components are going to give you shakes.

Even though I totally understand the reasons of this approach, there is also another, lighter way to look at the problem: simple EJB property matching. And Groovy provides just that out of the box.

Let’s start with JSON serialization:

static class MyBean {
    int a
    int b
    def ops = [:]

    public void go(){
        ops['mul'] = a*b
        ops['diff'] = a-b
    }
}
public static void main(def args){

    MyBean bean = new MyBean(a:15,b:22)
    bean.go()
    println ( JsonOutput.prettyPrint( JsonOutput.toJson(bean) ) )
} 

Is going to print:

{
    "b": 22,
    "ops": {
        "mul": 330,
        "diff": -7
    },
    "a": 15
}

Perfect. Save it, store it, send it. The data is there.
But what happens when you are meant to write some code to consume it? Here’s two options:

JsonSlurper

Just slurp the JSON into a nested structure of maps and lists! After all, in our example, if your consumer has only interest in the stored data, then MyBean is superfluous.

MyBean bean = new MyBean(a:15,b:22)
bean.go()

String data = JsonOutput.prettyPrint( JsonOutput.toJson(bean))
def items = new JsonSlurper().parseText(data)
assert (items['ops']['mul']==330)

Loose deserialization

I would call this no more than a side effect, but it works, so why not. Remember when we said there’s a default constructor with a map as param for all Groovy classes? And remember you could use that constructor to populate the bean properties?

Well why not…

MyBean bean2 = new MyBean(new JsonSlurper().parseText(data))
assert (bean2.ops.mul==330)

Hack #9: be concise!

3 things that will improve the compactness of your code.

x times!

10.times { /* do sometimes */
10.times { i -> println(i) }

Multiple assignments

def (a,b,c) = [1,2]
assert (a==1)
assert (b==2)
assert (c==null)

Optional parenthesis and semicolon

println "banana"

Is perfectly legit.

Hack #10 : string templating

This is probably one of the most appreciated features in Groovy. I left it as last of my list because I wanted to make sure you read all the others before getting here. Hope it worked.
So In Groovy you can use both quotes and single quotes to wrap a String value. They are almost the same, but they’re not really the same thing.
Single quotes work just like the double quotes in Java: they’re inert, they simply state: this is a constant string.
Double quotes do almost the same thing, unless you use the “magic” character $. When you do, a String becomes a GString that works as a string template against the current scope.
Here’s an example that will explain it all:

int quantity = 55
String fruit = 'Banana'
String str1 = 'I want '+quantity+' units of '+fruit
String str2 = "I want $quantity units of $fruit"
assert str1==str2

This is awesome when you have the variables set exactly where you declare the string, but what if I really wanted to use it as a template that gets evaluated when I need it?

int quantity = 55
String fruit = 'Banana'
GString str2 = "I want ${-> quantity} units of ${-> fruit}"

quantity = 55
fruit = 'Apple'
String str1 = 'I want '+quantity+' units of '+fruit

assert str1==str2

Conclusion

You can run but you can’t hide: Java is awesome when you’re building the core of a platform, but when it comes to daily routine such as business logic or view/controller part of a web application, it’s just too tedious.
Groovy saves you in a number of occasions, and the downsides (we’ll talk about them in a future article) are negligible most of the time.

It is true that you might need to train your team to deal with the level of uncertainty of a dynamic language, but I think it’s a price you’ll get back with interest, over time.

I left out a lot of interesting hacks, but I decided to go with context specific article. I will try to talk about the rest later on.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s