Erik and I had lunch yesterday with a cool local entrepreneur, Sunny, who has banked his product on Grails. His company also does Grails consulting on the side, so he has several years perspective on using Grails for both his own stuff and for clients.
I was interested in talking with Sunny to discuss the limits of Grails and what had been his experience on things to watch out for. My current Grails project is winding down, and I would like to use it more in the future, so it is always interesting to talk with someone further down the path. Here are some of the nuggets of wisdom he gave us about Grails:
While Sunny appreciates the dynamic nature of Grails, team size can tip it from a benefit to a liability. With more people on the team, he found he was having to write more tests to compensate for an increase in errors from using dynamic typing. Since the compiler can’t pick up all the dumb stuff, a lot of a testing was needed to ensure the correct output. Sunny uses a distributed development team, so not all the developers are sitting in the same room sharing knowledge.
My own guess is that the sweat spot for a Grails team is 3-4 developers working on-site together. As soon as you get too many developers, or they are geographically distributed, the increased productivity of Grails starts to get offset by the extra testing required for simple things that wouldn’t be needed in a statically-typed language. On the plus side, Grails makes it very easy to write tests, but that is still code that needs to be written.
I would imagine this fits in the same sweat spot as Ruby on Rails, so I would be interested to heard from my RoR friends if they see the same issues.
While GORM makes things easy, at it’s roots, it is using Hibernate. That means all the rabbit holes you can go down with Hibernate are just as dangerous in Grails. In Sunny’s case, he has over 100 domain classes in his product, and managing them becomes a chore. The biggest problem is working with deeply nested object hierarchies and cascading updates.
I’ve seen this same issue with straight Hibernate, so it’s not the fault of Grails. One of my prior applications had several eight-to-ten deep persistent object graphs, and it was a total nightmare for doing updates or creating new objects. There was a lot of compensating code around creating the graphs that ended up causing lots of problems when it came time to update an object in the graph. The optimistic locking would get confused and think you were trying to update an outdated version of the master object.
I would apply the same wisdom to Grails as I would to Hibernate: avoid deeply nested domain models.
I haven’t deployed any Grails applications that handle a high user load, and Sunny’s application is more batch-oriented. What he saw is that Grails got extremely slow in batch operations, mostly due to how Hibernate handled transactions.
He recommended turning on SQL tracing for your hotspots to really see what is going on, and tune appropriately. In his case, he had what he believed was a simple operation, but it resulted in over 20 SQL operations at the Hibernate layer.
This is a danger zone for ORM in general. I’ve seen it on about every Hibernate application I’ve dealt with. Hibernate likes to get chatty, and unless you really pay attention, you can end up with issues that drastically impact your performance under load. If you really care about performance, make sure every SQL operation counts.
I haven’t had to deal with this, but Sunny has worked with applications using about every version of Grails. The big pain is upgrading between Grails versions. Outside the language features that change between versions, plugins are one of the biggest problems. He found that the supported “core” plugins tend to play nicely together in upgrades, but he makes use of a lot of third-party plugins. These plugins end up having version conflicts on transitive dependencies that are painful to sort out.
This is another issue that isn’t specific to Grails, and I’ve run in to on about every large Java project. Java has a rich community, with a billion open source libraries to solve about any need. Unfortunately, you can too easily go into “DLL hell” with your jar files when libraries want to include different versions of the various libraries.
My own preference is to try to stick to the core SDK, be it the JDK, Spring or Grails, and really think hard about what you include. My favorite peeve is including Jakarta Commons just to get a cheap
toString() method. You now end up with a frivolous dependency that will end up biting you in the butt later.
Sunny has been really happy with Grails, in spite of the limitations. He’s looking forward to some of the new Groovy 2.0 features around static typing to eliminate some of the unit testing needs. And it it sounds like Grails is growing. More startups are starting to use it, and it sounds like it is more popular in Europe than here in the states.
Outside the dynamic typing, most the issues he has seen are endemic to any large Java application. Grails still provides a significant productivity boost over any of the other JVM-based options out there.