Groovy Closures Create Tidy, Flexible Services

You are probably aware that Groovy is considered to be a more advanced programming language, but why is that?  One reason is because Groovy provides the ability to write anonymous blocks of code called Closures.  A closure is code defined within curly braces that is not part of a class or a method.  A closure can be assigned to a variable and then passed around and used as any other variable is used.  The Groovy website has a detailed discussion about closures.  For those interested in a deeper conceptual understanding, please refer to Wikipedia and its near exhaustive discussion of Lambda Calculus.  Closures have been available in Groovy since 2003 and have been offered in other languages for decades.  With the release of version 1.8, Java has finally joined the party.  It will be interesting to see whether more developers begin using closures to solve problems now that this capability is fully mainstream.

Let’s look at a real-world example where using closures can help us solve a tricky coding problem. Let’s suppose we need to use the API of a legacy inventory system and the connection to it is accessed via a static factory in a jar published by another team within the company.  The original team that wrote and supported the API is long gone and now the code is considered to be “in maintenance mode” which is a euphemism for “untouchable.”   In addition, an outdated form of authentication is required to access the connection lifecycle:

While not verbose, the code has a troublesome mixing of concerns.  The service has to manage the connection lifecycle: open, do something, close.  There is the additional work of having to separately obtain a token from a third-party authentication service and pass it along in order to obtain a valid connection.  Our new PricingService wants to be concerned with looking up price information, but it is stuck managing a connection lifecycle, too. The classic Java Factory pattern could partially solve our problem, but the code using the factory would still be responsible for managing the connection’s lifecycle within PricingService.  Somewhere down the line, someone will forget to call the clean up method since there is no way to enforce it.  If the legacy inventory system is running on older hardware it could end up having its connection limits exhausted by accident.  One solution would be to set up a connection pool.  But let’s say that right now, our team has got to get the work done today and a connection pooling set up involves opening a support ticket with a team whose time is not presently available.  Groovy to the rescue:

Now, the PricingService boils down to:

What we have done is call the withInventoryConnection method and added an anonymous closure as the argument to it.  Back in the factory, withInventoryConnection happily invokes whatever closure is passed to it, while encircling that code with the necessary connection processing.  PricingService uses the connection to call the desired API method, for example, pricingLookup(), supplying it with the necessary parameters.  The connection-related code is properly encapsulated and the all-important call to close(), will now be enforced.

But wait!  There’s more:  The unit test for priceLookup becomes trivial.  Our Groovy implementation makes it a breeze to add connection pooling to InventoryApiConnectionFactory later on and PricingService won’t even have to be touched.  An additional forward-looking benefit is that InventoryApiConnectionFactory could also be easily moved to its own separate project.  Along with a robust test harness, a versioned InventoryApiConnectionFactory jar published to an internal repository provides value across multiple projects.

Mastering closures in Groovy (or any language that offers them) allows you to think about and solve coding problems in a clean, concise manner.  Groovy closures give the developer demonstrable problem solving flexibility while making the product easier to maintain over the long term.

A more complete, running example is available to paste in to your GroovyConsole.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

*