Posted by on Apr 20, 2012 in Programming | 3 comments

I started writing this post a month ago but delayed posting it until now. We are almost all the way through a re-write/re-design of vogogo.com in Django and I must say it has been a pleasure.

The comments below represent my findings after developing and deploying several Grails production applications over the last several years.

Complicated Controllers

Most of the examples you see built in Grails operate on a relatively simple domain model. i.e. Author has Books, a Book belongs to an Author. Creating a BookController with CRUD closures or possibly moving logic into services seems like a good idea and in this case I would agree. Unfortunately most systems are more complicated than that. Initially we had things laid out in a manner that made sense but as time went on, 2 years, the controllers became more and more complicated dealing with problems such as transient errors or having to do a Hibernate.initialize() before re-displaying a form to the user because the Hibernate session was destroyed on error.

Domain Class Constraints

Part of the controller madness was the decision to put constraints in the domain class. This leaves you with a false sense of leaving error checking up to the domain. As we discovered this isn’t the best option. As a result we had lots of controllers with logic translating the domain from how it is displayed to how it is stored and back again. A better approach would be to use a command object for each page and not use domain class constraints at all or as a last minute sanity check before persisting.

Object Oriented

Grails can’t take all the blame here though. I’ve come to the realization that building an object oriented web application is so difficult to get correct and nearly impossible to modify without quickly becoming a hair-ball it shouldn’t be attempted. At the very least classes can be employed as data holders only, maybe in rare cases when a polymorphic relationship could be of benefit. VTX did make use of using Hibernate as a factory. For example:

def transactions = Transaction.findAllByStatusAndDate('PENDING', new Date())
transactions.each {
    it.clear()
}

Where Transaction was extended by different types with a clear() implementation that was specific to that class.

I’ve thought about creating a function based web framework in Groovy akin to Django but decided against it for performance reasons.

Dyanamic Finders

At first Transaction.findAllByStatusAndDate(‘PENDING’, new Date()) looks like a good idea but I get the feeling that it adds substantial complexity and startup overhead to dynamically add the finder methods to your domain classes at runtime and I’m not sure it is worth it. If you are building a feature and add a call to a dynamic finder you have to add mockDomain(MyClass) to every test that directly (or indirectly) makes a call to that finder.

In reality I think Transaction.findAllWhere(status: ‘PENDING’, date: new Date()) that returns a list or findWhere that returns one object is a much better solution. One that could be handled without having to slow things down by dynamically adding things at runtime then working around the increased testing time with things like mockDomain.

Hibernate

I used to enjoy hibernate back when I was a Java frog boiling in water. I got used to reading stack traces, writing complex HQL and mapping .hbm.xml files. Grails hides most of the nasty stuff away from you but it is still there waiting to burn you with a transient, flush or session error. I can appreciate what the Grails and Hibernate guys have done but I just can’t stomach some of the assumptions that have been made anymore. It might seem easier to let the framework persist data changes to the database implicitly at first, but forcing the developer to explicitly manage it isn’t that bad and it avoids most of these issues.

Slow Test Time

We now have 4 systems built entirely in Grails and are approaching 300,000 lines of Groovy code including tests. If you were to run all tests in all four projects one after another you would be looking at close to 40 minutes on high-end hardware. VTX has 2700 unit and 1041 integration tests and it takes approximately 15 minutes for grails test-app to complete. In the past it has taken up to 25 minutes due to since removed features and older hardware. The trade off appears to be, write complicated unit-tests with large test setup and lots of mocking or write simpler to the point integration tests that are slow, even when run individually. We moved to an in memory database and loaded the project up into a RAM disk for a 30 second performance increase out of 15 minutes. Even with the highest end processor you can buy right now I’m guessing it would only shave a minute or so off above what we already have.

We did try groovy++ and it did look promising but after hitting a few roadblocks early on around closures manipulating variables in their parent scope that required re-writing and testing we decided to wait and see if Grails 2.0 helped.

Groovy

Groovy is one of the nicest curly-bracket languages to write and maintain in my experience. Being able to drop a lot of the punctuation noise, the ability to create domain specific languages and generally trying to stay out of your way results in clean easy to read code. Throw in closures and the ability to dynamically modify objects at runtime via MetaClass makes it a real joy to develop in. Unfortunately, from what I’ve read, it suffers from some performance problems rooted in the JVM that affect all dynamic languages running. Apparently JSR 292 and the introduction of invokeDynamic in JDK7 is supposed to help/solve this problem but I’m unsure of an ETA of when it will be available in Groovy, when Grails will upgrade to the associated version of Groovy or what exactly the performance improvements will be.

twitterlinkedin