Monday, October 22, 2012

Using Core Groovy AST Transforms

Have you ever used an Abstract Syntax Tree (AST) transform? If you're using groovy or grails, chances are you have, and maybe you just didn't know it. An AST allows code to be modified at compile time. Groovy provides the capability to write both local (annotation driven) and global (globally applied) AST transforms. They have a nice tutorial http://groovy.codehaus.org/Compile-time+Metaprogramming+-+AST+Transformations.

Even if writing AST transforms is not something you are doing, you can benefit from the numerous built in transforms that groovy provides. Many of these help to eliminate the need for boilerplate code that we've all written before. This post does not aim to list all of them, but rather to provide you an overview of some of them. Check out all implementors of the ASTTransformation from the groovy api (http://groovy.codehaus.org/api/org/codehaus/groovy/transform/ASTTransformation.html to see a full list.

Consider a Money class that looks

class Money {
    int amount
    String type // USD, Euro, etc

    boolean equals(Money other) {
        if ( other == this ) {
            return true
        }
        if ( other instanceof Money ) {
            return amount == other.amount && type == other.type
        }
        return false
    }

    int hashCode() {
        return new Integer(amount).hashCode() + type.hashCode()
    }
}

This is fairly verbose at best, and at worst, it's very error prone. What if I add a new field to the Money class and update the equals but forget to update the hash code (yes, tests should catch this). What if I forget to add the field to equals and hash code all together?

In Java, you might use Apache Commons' EqualsBuilder and HashcodeBuilder's reflection methods. This certainly simplifies your code, but the performance can be pretty bad if these methods are called frequently.

Enter the AST transform.

@EqualsAndHashCode
class Money {
    int amount
    String type // USD, Euro, etc

}

The @EqualsAndHashCode annotation adds the code at compile time, so you don't take the runtime hit, but you get the benefit of not having to write the code yourself.

Some other useful transforms include
@ToString - Adds a toString method
@Bindable - Adds property change support
@Mixin - Mixes in code to classes

As you can see, AST transformations can provide a lot of benefit and reduce the amount of boiler plate code you need to write. If you haven't used them before, I encourage you to at least take a look.

Thursday, October 4, 2012

Build quality in from the start

Have you ever joined a large project in progress only to find that the project is a bit on the messy side? There's no testing, no automated builds and really no quality control. Did you wonder how it got that way? Then you try to correct some of these problems only to realize you're only making a minor dent (better than nothing). But if the project is in that state, it's likely going to be an uphill battle.

Even the largest of projects start small, and it is much easier to build the quality control into the product at the beginning of the project. At the start of a project, use "iteration 0" for setting up the test and automation infrastructure. There are a certain set of tools at a minimum that I prefer to use for projects. 

Version control - this one should be obvious, but I'll include it here anyway. Whether you use a traditional VCS or distributed VCS may vary based on your needs, but use something.

Unit testing framework - again here, hopefully this one is obvious also. I typically use JUnit, but other tools such as spock can be useful. Also included here are any of the other unit testing framework, such as DBUnit or XMLUnit.

Acceptance testing framework - have a look at Selenium/Webdriver coupled with Spock or Cucumber. Cucumber is a little more complex but lets you write business requirements in plain language rather than in code.

Automated build/Dependency Management tools - ant/ivy, maven or gradle. Pick your poison. I like maven because it is more standardized than ant and has a rich set of plugins. But the million lifecycle phases with maven and the fact that it downloads the entire internet can be a little unnerving. On my next project, I'll be trying out gradle.

Continuous integration server - I really only have experience with Jenkins, but a variety of others exist. I've been quite happy with Jenkins, so I don't see myself switching any time soon.

Deployment tools - This is an important, but often overlooked category of automation tools. Maybe your deployment is simple, but it should absolutely be scripted, even if you write those scripts yourself. Just as with any of the other tools, your deployment infrastructure will evolve as your project does. 

Infastructure tools - Using virtual machines is a great way to make your infrastructure easier to manage. I've been using Chef for provisioning my VMs, and it makes reconfiguring and standing up new machines much easier. VMs are a great way to standup test environments as well. You may additionally want to look at infrastructure monitoring tools such as Nagios

Code quality control tools - cobertura code coverage, checkstyle, findbugs, pmd, CPD (copy-paste detector), and sonar.

This is just a sampling of the common tools I use. There are a seemingly endless number of solutions available in these areas. This may seem a bit overwhelming, and even if you can't use or don't need all of these tools, that's ok. The important part is to step into automation and quality control. The more you can get in place earlier in the project, the easier it will be in the long run.