Loading...

Tuesday, May 31, 2011

Groovy Goodness: Transforming Reader Input to Writer Output

With Groovy we can immediately transform the input from a Reader object(like a file, URL or other input type) to a Writer object (like a file, URL or other output type). Groovy adds the transformLine(Writer, Closure) and transformChar(Writer, Closure) methods to the Reader class. We need to pass the Writer object that will contain the transformed output as the first argument. The second argument is a closure with the rules for the transformation that needs to be applied.

def reader = new StringReader('''\
Groovy's support
for transforming reader input to writer output.
''')

def writer = new StringWriter()

reader.transformLine(writer) { line ->  
    if (line.matches(~/^Groovy.*/)) {
        line = '>>' + line.replaceAll('Groovy', 'GROOVY') + '<< '
    }
    line
}

def resultTransformLine = writer.toString()

reader = new StringReader(resultTransformLine)
writer = new StringWriter()
reader.transformChar(writer) { ch ->
    ch in ['\n', '\r'] ? '' : ch
}

assert writer.toString() == ">>GROOVY's support<< for transforming reader input to writer output."

Saturday, May 28, 2011

Groovy Goodness: Apply Read and Write Locking

When we write applications with concurrency needs we can use the ReentrantReadWriteLock class to specify a lock on specific methods. Normally we have to add a field to our class of the type ReentrantReadWriteLock and then write code to get a read lock or write lock, do our stuff and finally release the lock again. Since Groovy 1.8 we can use the AST transformation annotations duo WithReadLock and WithWriteLock. Groovy will add a lock field and adds the code to acquire and release the locks again in our compiled class file. We don't have to write this code ourselves anymore.

import groovy.transform.*

class Bucket {
    final def items = []

    @WithWriteLock
    void add(String item) {
        items << item
    }

    @WithReadLock
    List getAllItems() {
        items
    }
}

def bucket = new Bucket()

// Create read/write threads that use the same
// bucket instance.
def allThreads = []
3.times {
    allThreads << Thread.start {
        5.times {
            bucket.add Thread.currentThread().name + ': Groovy rocks'
            println "> ${Thread.currentThread().name} adds item to bucket."
            sleep 100
        }
    }
    
    allThreads << Thread.start {
        3.times {
            int numberOfItems = bucket.allItems.size()
            println "< ${Thread.currentThread().name} says $numberOfItems items are in the bucket."
            sleep 150
        }
    }
}

allThreads.each { it.join() }

assert bucket.items.size() == 15
println bucket.items

The following output shows the results of running the code. This output will be different each time we run the code.

> Thread-482 adds item to bucket.
< Thread-483 says 1 items are in the bucket.
> Thread-484 adds item to bucket.
< Thread-485 says 2 items are in the bucket.
> Thread-486 adds item to bucket.
< Thread-487 says 3 items are in the bucket.
> Thread-482 adds item to bucket.
> Thread-484 adds item to bucket.
> Thread-486 adds item to bucket.
< Thread-483 says 6 items are in the bucket.
< Thread-485 says 6 items are in the bucket.
< Thread-487 says 6 items are in the bucket.
> Thread-482 adds item to bucket.
> Thread-484 adds item to bucket.
> Thread-486 adds item to bucket.
> Thread-482 adds item to bucket.
< Thread-483 says 10 items are in the bucket.
> Thread-484 adds item to bucket.
< Thread-485 says 11 items are in the bucket.
> Thread-486 adds item to bucket.
< Thread-487 says 12 items are in the bucket.
> Thread-482 adds item to bucket.
> Thread-484 adds item to bucket.
> Thread-486 adds item to bucket.
[Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks, Thread-482: Groovy rocks, Thread-484: Groovy rocks, Thread-486: Groovy rocks]

The annotations also accept a name of an explicit lock field we have defined in our class ourselves. So we can use multiple locks within the same class.

Friday, May 27, 2011

Groovy Goodness: Command Chain Expressions for Fluid DSLs

Groovy 1.8 introduces command chain expression to further the support for DSLs. We already could leave out parenthesis when invoking top-level methods. But now we can also leave out punctuation when we chain methods calls, so we don't have to type the dots anymore. This results in a DSL that looks and reads like a natural language.

Let 's see a little sample where we can see how the DSL maps to real methods with arguments:

// DSL:
take 3.apples from basket
// maps to:
take(3.apples).from(basket)

// DSL (odd number of elements):
calculate high risk
// maps to:
calculate(high).risk
// or:
calculate(high).getRisk()

// DSL:
// We must use () for last method call, because method doesn't have arguments.
talk to: 'mrhaki' loudly()  
// maps to:
talk(to: 'mrhaki').loudly()

Implementing the methods to support these kind of DSLs can be done using maps and closures. The following sample is a DSL to record the time spent on a task at different clients:

worked 2.hours on design at GroovyRoom
developed 3.hours at OfficeSpace
developed 1.hour at GroovyRoom
worked 4.hours on testing at GroovyRoom

We see how to implement the methods to support this DSL here:

// Constants for tasks and clients.
enum Task { design, testing, developing }
enum Client { GroovyRoom, OfficeSpace }

// Supporting class to save work item info.
class WorkItem {
    Task task
    Client client
    Integer hours
}

// Support syntax 1.hour, 3.hours and so on.
Integer.metaClass.getHour = { -> delegate }
Integer.metaClass.getHours = { -> delegate }

// Import enum values as constants.
import static Task.*
import static Client.*

// List to save hours spent on tasks at
// different clients.
workList = []
 
def worked(Integer hours) {
    ['on': { Task task ->
        ['at': { Client client ->
            workList << new WorkItem(task: task, client: client, hours: hours)
        }]
    }]
}

def developed(Integer hours) {
    ['at': { Client client ->
        workList << new WorkItem(task: developing, client: client, hours: hours)
    }]
}

// -----------------------------------
// DSL
// -----------------------------------
worked 2.hours on design at GroovyRoom
developed 3.hours at OfficeSpace
developed 1.hour at GroovyRoom
worked 4.hours on testing at GroovyRoom


// Test if workList is filled
// with correct data.
def total(condition) {
    workList.findAll(condition).sum { it.hours }
}

assert total({ it.client == GroovyRoom }).hours == 7
assert total({ it.client == OfficeSpace }).hours == 3
assert total({ it.task == developing }).hours == 4
assert total({ it.task == design }).hours == 2
assert total({ it.task == testing }).hours == 4

Thursday, May 26, 2011

Groovy Goodness: Change XML Structure

We know how easy it is to read XML and to write XML. Recently someone asked during a workshop if it is possible to change the XML structure as easy. I found the answer on the Groovy website. It turns out we can simple use XmlSlurper and we can traverse the structure to change existing node values and attributes. We use appendNode() and replaceNode() to work with nodes using a builder syntax.

@Grapes(
    @Grab(group='xmlunit', module='xmlunit', version='1.3')
)
import org.custommonkey.xmlunit.*
import groovy.xml.*

def xml = '''
<todo>
    <item priority="2">
        <title>Look into GPars</title>
    </item>
    <item priority="1">
        <title>Start developing Griffon App</title>
    </item>
    <item priority="2">
        <title>Grails 1.4 M1</title>
    </item>
    <item priority="3">
        <title>GWT Sample</title>
    </item>
</todo>
'''

def todo = new XmlSlurper().parseText(xml)

// Change node values.
def items = todo.item.findAll { 
   it.@priority.toInteger() < 3 
}
items.each { item -> 
    item.title = "DO: " + item.title 
}

// Change attribute value.
def gpars= todo.item.find { 
    it.title =~ /.*GPars.*/ 
}
gpars.@priority = '1'

// Add extra item node.
todo.appendNode {
    item(priority: 2) {
        title 'Work on blog post'
    }
}

// Change node.
def grailsItem = todo.item.find { 
    it.title.toString().contains('Grails') 
}
grailsItem.replaceNode { node ->
    item(who: 'mrhaki', priority: node.@priority) {
        title 'Download Grails 1.4 M1'       
    }
}

// Remove node. Index value based on result directly after parsing.
// So here we remove the item about GWT.
todo.item[3].replaceNode {}

// Create output.
def newTodo = new StreamingMarkupBuilder().bind { 
    mkp.yield todo 
}.toString()

def expected = '''
<todo>
    <item priority="1">
        <title>DO: Look into GPars</title>
    </item>
    <item priority="1">
        <title>DO: Start developing Griffon App</title>
    </item>
    <item who="mrhaki" priority="2">
        <title>Download Grails 1.4 M1</title>
    </item>
    <item priority="2">
        <title>Work on blog post</title>
    </item>
</todo>
'''

// Check to see expected XML equals new todo XML.
XMLUnit.ignoreWhitespace = true
def difference = new Diff(newTodo, expected)
assert difference.similar()

Wednesday, May 25, 2011

Groovy Goodness: Add Java-style Listener Support with ListenerList Annotation

To implement a bean event pattern in Java a class must be able to register or remove event listeners. Then the list of listeners can be used to fire methods defined by the listeners. Setting up a list of listeners, providing the correct add and remove listener methods, add fire event methods is all boilerplate code we have to write each time. With Groovy we don't have to, we simply apply the @ListenerList annotation to a typed collection field in our class.

Groovy will add the add and remove listener methods, a method to get the assigned listeners and methods to fire event methods defined in the listener interface. All this is done before compilation, so the resulting class file contains all the necessary code and is therefore usable in plain Java code without any Groovy dependencies. Notice the collection field must have generic type, because otherwise the correct code cannot be generated.

// Simple listener interface with spoke() method.
interface TalkListener {
    void spoke(TalkEvent event)
}

// Event to be passed into listener spoke() method.
class TalkEvent {
    String text, origin
}

class Speaker {
    @groovy.beans.ListenerList
    List<TalkListener> talkListeners

    String name

    void sayHello() {
        // fireSpoke is added by @ListenerList.
        fireSpoke(new TalkEvent(origin: name, text: 'Hello Groovy world!'))
    }

    // Methods generated by @ListenerList:
    // void addTalkListener(TalkListener)
    // void removeTalkListener(TalkListener)
    // TalkListener[] getTalkListeners()
    // void fireSpoke(TalkEvent)
}


def s = new Speaker(name: 'mrhaki')
// Add listener interface implementation to simply output
// the data in the event object.
s.addTalkListener([spoke: { event ->
   println "$event.origin says '${event.text.toLowerCase()}'"
}] as TalkListener)
// Second implemenation of listener interface is added.
def shouter = { event -> println "${event.text.toUpperCase()}" } as TalkListener
s.addTalkListener shouter
s.sayHello()

// Output:
// mrhaki says 'hello groovy world!'
// HELLO GROOVY WORLD!

Tuesday, May 24, 2011

Groovy Goodness: Canonical Annotation to Create Mutable Class

With Groovy 1.8 we get a lot of AST transformations. We can combine @ToString, @EqualsAndHashCode and @TupleConstructor with the @Canonical annotation. This annotation will do all the transformations at once. If we want to customize one of the AST transformations, we add the annotation with configuration parameters extra after @Canonical.

import groovy.transform.*

@Canonical
class Building {
    String name
    int floors
    boolean officeSpace
}

// Constructors are added.
def officeSpace = new Building('Initech office', 1, true)

// toString() added.
assert officeSpace.toString() == 'Building(Initech office, 1, true)'

// Default values are used if constructor
// arguments are not assigned.
def theOffice = new Building('Wernham Hogg Paper Company')
assert theOffice.floors == 0
theOffice.officeSpace = true

def anotherOfficeSpace = new Building(name: 'Initech office', floors: 1, officeSpace: true)

// equals() method is added.
assert anotherOfficeSpace == officeSpace

// equals() and hashCode() are added, so duplicate is not in Set.
def offices = [officeSpace, anotherOfficeSpace, theOffice] as Set  
assert offices.size() == 2 
assert offices.name.join(',') == 'Initech office,Wernham Hogg Paper Company'

@Canonical
@ToString(excludes='age')  // Customize one of the transformations.
class Person {
    String name
    int age
}

def mrhaki = new Person('mrhaki', 37)
assert mrhaki.toString() == 'Person(mrhaki)'

Monday, May 23, 2011

Groovy Goodness: Paging Support in Groovy SQL

Groovy has great SQL support. We can easily access databases and execute queries and statements. Since Groovy 1.8 we can even use paging when we query for data. The eachRows() and rows() methods have two new parameters to define the offset and maximum results we want to be returned.

@Grapes([
    @Grab(group='com.h2database', module='h2', version='1.3.154'),
    @GrabConfig(systemClassLoader = true)
])
import groovy.sql.*

def sql = Sql.newInstance('jdbc:h2:./test', 'sa', '', 'org.h2.Driver')
sql.execute 'drop table if exists languages'
sql.execute '''
    create table languages(
        id integer not null auto_increment,
        name varchar(20) not null,
        primary key(id)
    )
'''

['Groovy', 'Java', 'Scala', 'JRuby', 'Clojure', 'Jython'].each {
    sql.execute "insert into languages(name) values($it)"
}

// Use paging to set offset to 1 and maximum results to 2.
sql.eachRow('select * from languages', 1, 2) { row ->
    def expectedName = (row.id == 1 ? 'Groovy' : 'Java')
    assert row.name == expectedName
}

// Offset is 3 for resulting resultset, maximum results is 3.
def result = sql.rows("select * from languages where name like 'J%'", 3, 3)
assert result.size() == 1
assert result[0].id == 6 && result[0].name == 'Jython'

sql.execute "drop table languages"

sql.close()

Friday, May 20, 2011

Gr8Conf 2011 Conference Report: Day 3

The final day of the conference, the last day I could go to informative and inspiring sessions. The whole day there will be parallel sessions, so here is a report of the sessions I have choosen to attend. We can also read the conference reports of day 1 and day 2.

Introducing GContracts presented by Andre Steingress was the first session of the day and it was great. GContracts is a cool product and can really improve the quality of your code. This is really something I want to use in my projects. With GContracts we can add annotation to our classes and method to ensure post-conditions, set required pre-conditions and class invariants. The syntax is simple so it easy to get started.

The next session was about myBalsamiq. This is project colaboration website to work on Balsamiq mockups that will be released later this year. And it is built using Grails! It is cool to see such a site with a lot of interaction and big user base is created with Grails. Also the architecture of the application was very intesting and looked really great. I wish them good luck with the launch of their product and it will be a great new testimonial for Grails applications.

Gaelyk was the subject of the following session presented by Guillaume Laforge the author of Gaelyk. Gaelyk allows us developers to use Groovy on the Google App Engine. First we learned about the way Google App Engine is positioned in the cloud and the payment model.
Also we took a good look at the services Google gives us developers to use, like datastore, memcache, image manipulation, email. Then it was time to see how we can use all this in a Groovy way. All Google services are directly usable in our Groovy code, because the services are added automatically through bindings. Also several DSLs are applied to make using the services easier. With a bit of live coding we could see this in action.
Gaelyk also has a plugin system, so we could write reusable parts as plugins and use them in our code. The presentation is available on SlideShare.

The session about Spock, my favorite test framework, was presented by Peter NiederWiesser who wrote Spock. The first part of the session was an introduction to Spock for those that didn't know Spock before. With small samples we could see how JUnit tests turned into beautiful Spock specifications. With a state machine and interaction sample this was very helpful.
The second half of the presentation was about the more advanced features in Spock for those that already knew Spock. Writing extensions for example is very easy in Spock and Peter showed this with a sample.
The code Peter used is available on GitHub.

Václav Pech gave a session about GPars. And because GPars is now part of Groovy 1.8 we can all use the very usable features of GPars to create concurrent and parallel running application code. Concurrency will play a big role in the future to create performant applications and with GPars we use Groovy to this. Multi-cores are already here and we will get more of them in the future in all our computers and appliances. And the good thing is, the implementation of the code is not difficult. For example to work with collections in parallel we only add two lines of code and we are done. The impact on the code is also small.
We can also choose to use the dataflow variable paradigm to create concurrent code, which will require a code rewrite, but the result is very elegant and will probably be worth it.
Finally Václav showed how actors can be used and how easy it to write the code. GPars is really something for me to get into in the near future and want to implement in my projects.

Testing is very important when we write code and the next session, Testing with Fitnesse, was just about that. Fitnesse is a framework that is used to write test scenarios in a Wiki with a very simple syntax. Erik Pragt and Marcin Erdmann have created a Grails plugin to use Fitnesse in Grails applications. First Erik gave a small introduction on how we can use Fitnesse and how the plugin uses Fitnesse to run tests. Fitnesse is best used for more complex business logic and is addition to unit tests written in for example Spock.
Then Marcin gave an impressive live coding demo to show TDD with Fitnesse and the plugin. Starting from scratch by writing the test scenarios and then implementing the logic in code.
The presentation was very good and gave a good idea about what Fitnesse is about and the power of it.

The final session of the day I attended was about Building Progressive UIs with Grails by Rob Fletcher. Rob explained why it is important to write progressive UIs for the web. Although you might think everybody has Javascript enabled in their browser and that it is fast, that might not be the case. For example in corporate environments IE6 is still used and upgrading is not on option. But computers nowadays are not the only devices to access your website, mobile phones, tablets and more devices can access your site. These devices don't have all the latest and greatest features, so be humble when you design a site.
By separating markup, CSS and Javascript and providing a functional website with the lowest standard, we are ready to enhance the user experience with Javascript for those users that can use it. He showed some real life examples for Grails applications. The samples showed the different user experiences for the browsers with disabled and enabled Javascript. This was really cool to see and very useful to use in projects. The code is on GitHub.
A very nice tip was to first test of a request is a AJAX request before applying a layout. This way the views can be reused in a AJAX and normal request without changing the view.

I had to leave for the airport before the panel discussion, which I couldn't attend unfortunately.

The overall feeling of this conference is that the Groovy community is very social, friendly and open. I learned a lot during these 3 days and just as last year my list-with-things-to-look-into-and-learn-more-about has grown again. Hopefully I will be able to cross most things off, before next year's Gr8Conf. Because Gr8Conf 2012 is already marked in my agenda.

Gr8Conf 2011 Conference Report: Day 2

After already a first great university day it was now time for the official start of the conference days. After Søren's welcome speech it was for time for Guillaume Laforge to present his brand new presentation about Groovy 1.8. He touched on all the interesting new features we can find in Groovy in his presentation.
The new command chain expressions even allows us to leave out dots when we invoke methods so we can write even nicier and more natural language like DSLs. A lot AST transformations have been added in Groovy 1.8, closure methods, JSON supports, compilation customizers and much more. The slides are available on SlideShare.

Next up was the Grails update. Peter Ledbrook showed us all the goodies we can expect in Grails 1.4. For example we get better looking (supporting progressive Javascript/CSS using HTML5) scaffolding templates. Also we get a complete GORM API implementation for testing purposes. This means everything that is available in the GORM API can be used in a testing enviroment. Yes, even Criteria calls will work! This is all implemented as mix-ins, so we can use it in JUnit testcases, but just as easy in Spock specifications. We don't have to extend our test classes from a specific Grails testcase anymore. The new test report UI is very impressive and looks very useful.
Also a lot of libraries are upgraded for the upcoming Grails 1.4 release, like Spring, Hibernate, Groovy. Tomcat 7 will be the default servlet container. Also hot reloading of classes has been improved. A special agent is used for the JVM, that allows class reloading for almost all classes of the application the speed up development even more.
The database migration and resources plugins will become part of Grails. In the not so near future we can expect Grails 1.4 M1 to be released so we can experience a lot of these nice features already and try them.
Also Peter explained they want to get a better insight to see how plugins are used and for example how many times a plugin is used. With this data the usefulness of a plugin should be more clear to developers when they want to download and use a plugin.

Both the Groovy and Grails update session where single track session, but the rest of the Gr8Conf was with 2 tracks. So I had to make choices and cannot cover every session in this report. I attended the Adopting Grails session, about how Grails can be implemented in a real world situation. Even integrated with another Java web application. We learned how we can split up a Grails application using plugins into several parts. For example a plugin to define only the services layer. This way the plugin could be used in a Java and Grails application. Also we learned that still Java developers are a bit scared of Groovy. If they have to fix bugs in parts of Groovy code with for example a bit of dynamic programming then they couldn't get it.

After the lunch I attended the Gradle Update by Peter Niederwieser. He works at Gradleware and did a good job explaining Gradle. First he showed how easy it is to get started with Gradle of you come from an ANT build system. It is basically just a matter of importing the ANT build and you are ready to. He also show how you can re-use your Maven build from Gradle. He created a new task rule to intercept the commands and then invoke Maven through an exec invocation to get the Maven build going. And of course he showed that Gradle doesn't need much code to use it for a Java (or Groovy) project that already uses the Maven standards for directory structure. Gradle of course shines with parallel test execution, the fact tasks are only executed when they need to be by looking at input and output variables and Peter showed how this works.

Next up was my own presentation for CodeNarc & GMetrics. I did a live coding session where we started to take a look at a bit of Groovy code and then see which CodeNarc rules where fired. We learned CodeNarc contains many rules and they are also great for new Groovy developers to learn about how you code can be more Groovier. CodeNarc has for example a lot of rules that will tell you that certain parts of your code are a bit Java-ish and how to turn into something more Groovy-ish. I explained how can use the configuration to change rule priorities or even disabled them completely. We learned how to customize certain rules and I wrote a complete new rule and showed how it could be used in our CodeNarc analysis.
GMetrics is more about calculcation and reporting of code metrics like ABC (Assignment/Branch/Condition) counts and cyclomatic complexity. We finally looked at how we can customize the report from both tools.

The next session I attended was Paul King's Groovy Testing. The focus was on how Groovy can be used for testing with web drivers like HTMLUnit. He explained the many possibilities that are out there to do testing and you probably will need a combination of different techniques to get a satisfying test outcome. There is no one golden solution to cover each testing need. Each project has different characteristics and therefore different testing needs. But Groovy is very powerful to use for testing purpose, because the language is so powerful and dynamic that is easy to express your testing needs.
He also told us to create a testing API or DSL for your own testing to provide an abstract layer between how you express your tests and the real test implementation that can be used.
He ended with showing how you can use Groovy to generate test data for your testing. Different scenario's can be created with combinations of test data, but you can also for an optimal instead of a maximal set of test data to keep your tests running quickly. On SlideShare we can find slides that where used during the presentation.

The last session for the first day I attended was Effective Groovy by Hamlet D'Arcy. Following the guidelines and rules from Effective Java he showed how to implement those rules in Groovy. And of course the power of Groovy really shines when we only have to one-liners or add annotations to implement the Effective Java rules.
He also added new "Effective Groovy" rules which are not in Effective Java but apply to Groovy applications. A lot of the rules were already implemented with the new Groovy 1.8 features, so it was great to see these features already mentioned and shown. The presentation was a lot of fun and just showed again how powerful Groovy really is. Hamlet also posted the slides.

To end this beautiful and great first conference day we were treated by snacks and beer for a social gathering between all conference attendees. Thank you Gennemtaenkt for organizing this tasty and fun meeting.

Read more about day 3.

Gr8Conf 2011 Conference Report: Day 1

For the first time this year Gr8Conf organized a university day. On this day 3 hour sessions where given about Groovy (in the morning) and Grails (in the afternoon). In the morning I did the session about Getting Groovy together with Søren Berg Glasius (one of the organizers of Gr8Conf). We had a lot of topics to cover and didn't make it to cover it all during the session. Luckily we created a big document with all the topics and a lot of sample code (also from the Groovy Goodness blog series) for the attendees. So hopefully people will look into the document to learn more about the topics we couldn't cover.

Also in the morning was a more advanced Groovy session about AST transformations by Hamlet D'Arcy. I couldn't attend this session, but after 3 days of Gr8Conf I can say AST is now at the top of my agenda to look into further. AST is powerful and provides many benefits for developing Groovy applications.

The afternoon sessions where about Grails. The Grails Kickstart session was a beginner's session on how to create Grails applications. I attended the session about How to write a Grails plugin presented by Burt Beckwith. Burt is of course a famous Grails plugin developer and he has a lot of plugins he contributed to or developed. We learned that writing a Grails plugin is not that different from writing a Grails application. He explained the small difference and also the little pitfalls. During the session he wrote a calendar plugin that was able to communicate via the Google Data API to get and save the data. The source code is on GitHub. The session was very useful and provided enough insight to get me started on writing a Grails plugin myself.

And then after the session it was time for Hackergarten hosted by the guys from Canoo. At Hackergarten people get together and work in small teams on (open source) projects. The goal is to have real contributions to a project at the end of the evening. This is of course a great way to get involved into an open source project and become one of the contributors. I joined the team developing new rules or fixing bug on rules for CodeNarc. Hamlet D'Arcy took the lead and give some outstanding issues that needed to be fixed or new rules that needed to be written. We paired up and wrote an extra addition to the ConfusingMethodName rule. It is great that I now contributed a small part to CodeNarc and the evening was really inspiring.

Read more about day 2 and day 3.

Monday, May 2, 2011

Groovy Goodness: Cache Closure Results with Memoization

Closures are very powerful in Groovy. Groovy 1.8 introduces closure memoization. This means we can cache the result of a closure, so the next time we invoke the closure the result is returned immediately. This is very useful for time consuming computations in a closure.

To use this feature we invoke the memoize() method on a closure. Now the results from calls to the closure are cached. We can use three other methods to define for example the maximum number of calls to cache, or the least number of calls with memoizeAtMost(), memoizeAtLeast() and memoizeBetween().

// Closure simple increments parameter.
// Also script variable incrementChange is 
// changed so we can check if the result is
// from a cached call or not.
def incrementChange = false
def increment = { 
    incrementChange = true
    it + 1 
}
// Just invoke the closure 5 times with different parameters.
(0..5).each {
    incrementChange  = false
    assert increment(it) == it + 1
    assert incrementChange
}
incrementChange = false
assert increment(1) == 2  // Call is not cached.
assert incrementChange  

// Use memoize() so all calls are cached.
incrementChange = false
def incrementMemoize = increment.memoize()
// Just invoke the closure 5 times with different parameters.
(0..5).each {
    incrementChange = false
    assert incrementMemoize(it) == it + 1
    assert incrementChange
}
incrementChange = false
assert incrementMemoize(2) == 3  // Cached call.
assert !incrementChange  

// Use memoizeAtMost().
incrementChange = false
def memoizeAtMostOnce = increment.memoizeAtMost(1)
// Just invoke the closure 5 times with different parameters.
(0..5).each {
    incrementChange = false
    assert memoizeAtMostOnce(it) == it + 1
    assert incrementChange
}
incrementChange = false
assert memoizeAtMostOnce(1) == 2  // 2nd call is not cached.
assert incrementChange