Groovy – using parameters with default values to separate method configuration from method body
And with that huge title 😀 , I want to talk about a little technique that I like to use in Groovy by taking advantage of the method parameters with default values feature. By method configuration and method body I am refering to two typical parts of a business logic method (for example, a method of a Grails service) that you have probably seen a lot. Imagine a method like the following:
def updateContractAddress(contract, newAddress) { // Method configuration def client = contract.client def country = CountryService.findByPostalCode(newAddress.postalCode) def currentAddress = client.address // Method body client.previousAddresses << currentAddress client.address = new Address client.save() }
As you can see, the method has two different parts:
- In the first one, we just configure some variables that we will use in order to clean up our code, or may to not calling the same method twice (as would happen, for example, with the implicit method Contract.getClient(), that would be called three times in the variable client was inlined).
- In the second one, the actual method business logic is performed.
This is actually the method implementation, the previous stuff is just boiler plate code. In fact, in Java I have seen a lot the pattern of separating the previous code in multiple methods, in order to separate this two parts:
def updateContractAddress(contract, newAddress) { def client = contract.client def country = CountryService.findByPostalCode(newAddress.postalCode) def currentAddress = client.address updateContractAddress(contract, newAddress, client, country, currentAddress) } private updateContractAddress(contract, newAddress, client, country, currentAddress) { client.previousAddresses << currentAddress client.address = new Address client.save() }
Not bad. As I always say when joking, almost every life problem can be solved by applying an extract to method refactoring (yes, I am a funny guy 😆 ). But in Groovy we have another alternative that I find to be more elegant and easy to read.
As you know (and if don't, you should read this 🙂 ), Groovy supports default values for a method arguments. So, you can do the following:
def method(a, b = 3, c = []) { ... }
That is the same as doing:
def method(a) { method(a, 3, [] } def method(a,b) { method(a, b, [] } def method(a,b,c) { ... }
In fact, I think this is what the compiler actually do, making the feature a simple code generator that takes place in preprocessing time (but that is just me guessing 🙂 ). Anyway, what you may not know is that the optional parameters can be assigned with method calls, and that this method calls can use the rest of the parameteres. So, the original code can be as following:
def updateContractAddress(contract, newAddress, client = contract.client, currentAddress = client.address, country = CountryService.findByPostalCode(newAddress.postalCode)) { client.previousAddresses << currentAddress client.address = new Address client.save() }
Now we can focus on the method body without being distracted by all this boilerplate code, but if we want to take a look at it, is just a few lines above, and we don't need to navigate the class as the previous solution. And for free, we obtain a parametrized method: in we need to pass the client as a parameter in the future, we can do it without modifying a single line 🙂 .
What I love about this trick is that it can aslo be used with Closures, so you can do stuff like the following:
[ name: 'diego', lastName: 'toharia', country: 'spain' ].each { factName, factValue, capitalizedFactValue = factValue.capitalize() -> person[factName] = capitalizedFactValue }
Ha 😀 . Love it.
Bonus track
When using this last trick, be careful: if the method that receives your closure checks the number of arguments it receives in order to invoke it with the proper number of arguments, you can see how your method initialization is replaced by an unexpected value! An example of this would be the closure passed to a Grails validator:
class SomeDomainClass { String prop static constraints = { prop(nullable: true, validator: { prop, domainClass, propIsEmpty = prop.trim() != "" -> propIsEmpty || validateProp(prop) } } }
In this example, the custom validator for the property prop init the propIsEmpty parameter in the closure signature, but Grails is smarter: if you pass a closure with one argument, it invokes it with the property. If it can receives two arguments, it passes the property and the object. But if the closure declare three arguments, it passes the current validation errors as well, so you will find that propIsEmpty won't have what you expected 😀 . So use it carefully 🙂 .
Parecidos razonables
-
Grails – Quickly examine a domain class associations
July 30, 2013
0 -
Grails – small and simple method to convert objects to JSON
January 12, 2013
0 -
Grails – Hibernate-safe domain class property editor
July 22, 2014
0 -
Groovy – Simplest way of resolving a nested property
July 24, 2013
4 -
Grails – generic methods for equals and hashCode calculation
December 27, 2012
3
Conversaciones