Archive of articles classified as' "metaprogramming"

Back home

Groovy Each Iterator with Peek-ahead at Next Collection Value

2010/06/15

Groovy closures combined with iterators make it simple to create our own enhanced iterators that let us process a collection how we want to.

I write my own custom iterators all the time and name them something descriptive. This makes the code much more readable. Rather than trying to decipher what a for loop is trying to do, we wrap up all of that iteration logic into a meaningful name and we cleanly separate that iteration from the processing that we’re doing with each element.

This kind of design is a core concept in Uncle Bob’s Clean Code, one of my favorite programming books in the last few years.

This example iterates over a collection and calls the passed in closure until we hit a value greater than 5.

def eachUntilGreaterThanFive = { collection, closure ->
    for ( value in collection ) {
        if ( value  > 5 ) break
        closure(value)
    }
}
 
def a = [1, 2, 3, 4, 5, 6, 7]
 
eachUntilGreaterThanFive(a) {
    println it
}

prints:

1
2
3
4
5

This code makes it obvious what the iterator is doing (looping till we hit a condition) as well as what will happen with each element iterated over (print it out).

For a real life example, I had a need to iterate over a list of values and where I needed both the current object as well as a peek at the next object in the list.

Doing this is Java is a bit of a pain, but groovy makes it easy to write and (hopefully) to read, we can also add it directly onto the Collection metaClass so that it’s available for all of our Collection instances:

Collection.metaClass.eachWithPeek = { closure ->
    def last = null
    delegate?.each { current ->
        if (last) closure(last, current)
        last = current
    }
    if (last) closure(last, null)
}

These test cases show that as we iterate through the collection, we can see the current item and peek at the next one (if any). If the collection is empty, we don’t execute the closure it, and if we’re at the end of the list there isn’t anything to peek at:

[].eachWithPeek { current, peek ->
    assert false // shouldn't get here, nothing to iterate through
}
 
[1].eachWithPeek { current, peek ->
    assert current == 1
    assert peek == null  // only 1 element, nothing to peek at
}
 
def results = []
[1, 2, 3, 4, 5].eachWithPeek { current, peek ->
    results << [current, peek]
}
assert results == [[1, 2], [2, 3], [3, 4], [4, 5], [5, null]]
1 Comment

Grails build-test-data plugin version 1.0 released

2010/03/17

I’ve finally released version 1.0 of the grails build-test-data plugin.

If you’re not familiar with build-test-data, the quick summary is that it puts a build() method on all grails domain objects. Calling that method will automatically construct and save an instance of that domain object that conforms to all of the domain’s constraints. It also allows you to override the values that you want to explicitly set. It makes your tests much cleaner and less fragile as you only need to specify the values that actually matter to a particular test method instead of building a huge graph of objects just to satisfy constraints.

The plugin has been quite stable for the past 6 months or so, and has survived upgrades from grails 1.0.X through grails 1.2.1 with minimal changes. Because of this, I’ve decided to move the version from 0.2.3 to 1.0 to indicate that the plugin is stable and ready to be used. I’ve also added the LICENSE file releasing the plugin under the Apache 2.0 open source license (the same license as grails). It was always open source, but I had neglected to add the official license file in the past.

If you’re not familiar with the build-test-data plugin, the documentation on the wiki is thorough, I’ve also given a presentation on build-test-data that explains why it’s better than other existing data generation technologies.

The biggest changes for this release compared to the last are a number of bugfixes around making sure that both sides of a one-to-many relationship get populated correctly and that there isn’t a need to refresh() from the database.

Previously, if you had an Author that hasMany Books, and each Book belongsTo an Author, you’d need to refresh the Author if you tried to build a new book with an existing author:

Author eap = Author.findByName("Edgar Allan Poe")
Book b = Book.build(author: eap, title: "The Tell-Tale Heart")
 
assertEquals eap.name, b.author.name  // works, linked in OK previously
assertEquals 1, eap.books.size() // FAILED previously WORKS now, previously the book wasn't added properly to the author side of things

The previous workaround was to call eap.refresh() to reload the author from the database, or to have the user manually addToBooks(b). Both solutions were ugly and kludgy and this issue has now been fixed.

3 Comments

Interrogating Arbitrary Groovy Closures for Values

2010/01/24

Inspired by this question on stackoverflow, I decided to create a utility class that allowed me to determine generically what calls a closure makes (without actually letting it make any calls). This lets me see what it’s trying to do before letting it actually do it.
Read the rest of this article »

4 Comments

Modularizing Groovy Config Files With a Dash of Meta-Programming

2009/07/30

This is a continuation of a sporadic set of blog posts about some practical uses for groovy metaprogramming.

Groovy Config DSL Overview

In Java, configuration is normally done with properties files. They’re kind of a pain because they’re inflexible, don’t allow executable code, and don’t easily provide a heirarchy.

Groovy greatly improves on Java by building in support for a simple configuration DSL using the ConfigSlurper. Read the rest of this article »

8 Comments

Grails build-test-data presentation

2009/07/14

I gave a presentation tonight on the build-test-data grails plugin at the Groovy Users of Minnesota (GUM) meeting that was well received.

Lots of good questions from the people in attendance. Thanks to everyone for showing up.

Here’s a version of it on slideshow: Read the rest of this article »

6 Comments

Groovy closures make unit testing with “soft asserts” simple

2009/06/25

A recent blog post, Cedric Beust asks about how to cleanly implement “soft asserts”. Soft asserts are test assertions that don’t “fail fast”. Instead, all of the assertion failures in the test method are collected and reported at the end of the test.

So far, the proposals in the comments look fairly clunky to me and include defining whole sets of new methods like “assertEqualsButContinue(“foo”, “foo”)”, chaning assertions together jQuery-style, or using lists to hold all of our assertions.

Wouldn’t it be a lot nicer if we could continue to use the same methods that we’re already using?

In groovy, enabling soft assertions is easy with a little closure magic. Read the rest of this article »

6 Comments

Groovy MetaClass: Overriding a method whilst using the old implementation

2009/06/1

The need to add some functionality an existing method, but avoiding cutting and pasting the old implementation has come up a few times over the last week.

Sometimes, creating a subclass isn’t feasible, often because you don’t control all of the places where that class gets used. Read the rest of this article »

4 Comments

What methods does my Groovy/Grails class have?

2008/05/7

If you’ve ever wondered what methods a groovy class has available for you to call, all you need to do is ask the metaClass:

"foo".metaClass.methods*.name

Result:

["equals", "getClass", "hashCode", "notify", "notifyAll", "toString", "wait", "wait", 
"wait", "charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo", 
"compareTo", "compareToIgnoreCase", "concat", "contains", "contentEquals", 
"contentEquals", "copyValueOf", "copyValueOf", "endsWith", "equals", 
"equalsIgnoreCase", "format", "format", "getBytes", "getBytes",
 "getBytes", "getChars", "hashCode", "indexOf", "indexOf", "indexOf", 
"indexOf", "intern", "lastIndexOf", "lastIndexOf", "lastIndexOf", "lastIndexOf", 
"length", "matches", "offsetByCodePoints", "regionMatches", "regionMatches", 
"replace", "replace", "replaceAll", "replaceFirst", "split", "split", "startsWith",
 "startsWith", "subSequence", "substring", "substring", "toCharArray", 
"toLowerCase", "toLowerCase", "toString", "toUpperCase", "toUpperCase", 
"trim", "valueOf", "valueOf", "valueOf", "valueOf", "valueOf", "valueOf", 
"valueOf", "valueOf", "valueOf"]

There’s a lot of duplication in there, and the order is random, so I’ll often fix that like this:

"foo".metaClass.methods*.name.sort().unique()

Result:

["charAt", "codePointAt", "codePointBefore", "codePointCount", "compareTo",
 "compareToIgnoreCase", "concat", "contains", "contentEquals", "copyValueOf", 
"endsWith", "equals", "equalsIgnoreCase", "format", "getBytes", "getChars",
 "getClass", "hashCode", "indexOf", "intern", "lastIndexOf", "length", "matches", 
"notify", "notifyAll", "offsetByCodePoints", "regionMatches", "replace", "replaceAll",
 "replaceFirst", "split", "startsWith", "subSequence", "substring", "toCharArray", 
"toLowerCase", "toString", "toUpperCase", "trim", "valueOf", "wait"]

Read the rest of this article »

7 Comments