Using Grails Controller Interceptors To Avoid Rampant Testing
Test-driven development and the resulting test coverage it affords are some of the most important benefits of modern development practices. When it comes time to refactor code or make a significant functional change, there’s nothing like the peace of mind afforded by a comprehensive set of well-written unit tests all emitting that wonderful emerald green.
But such peace of mind comes at a cost. I’ve heard estimates from various teams I’ve talked to stating that the cost of writing unit tests for adequate code coverage (usually 50% to 80% on Java projects) can range from equivalent to the production code itself, to five times that. The problem with these estimates, of course, is subjectivity. For example, if you have found a bug using a test and work to fix the test, are you mentally counting that time as test-writing or code-writing?
Estimating factors aside, the plain fact is that testing does amplify the cost of software development – at least in the short term. Which means that a software engineer who really cares about his customer’s bottom line should always be on the lookout for ways to avoid the increased cost of testing.
This line of thinking arose the other day on the project I’m currently working on. It’s a Groovy/Grails web application with some public, customer-facing components and some internal-use components. We’re using Grails scaffolding as much as is practical for the relatively infrequently-used internal-use features to save time and money. In most cases, we have generated and tweaked the UI components (GSP pages) to smooth over some of the uglier bits of scaffolded pages, but we have tried not to generate any of the controller code, instead relying on Grails’ generate-at-runtime approach by including def scaffold = true in these controllers.
Why not generate the source? Because generated code is deceptively expensive! The minute a feature springs into existence in your code base, it needs to be tested – even if that code was generated by a framework like Grails. And Grails controller closures – insert and update, as the case in point here, do a significant amount work for you. Data binding. Optimistic locking exception handling. Routing of validation errors. All things that “just work” in scaffolded code, but which might be broken by someone once the code actually becomes part of your code base.
So when the need arose to customize part of the logic in insert and update closures (to do some custom interpretation of a series of check boxes on a form that couldn’t be made to conform to the default binding mechanism), we began looking for ways to override binding logic without generating and modifying the closures themselves.
As usual, Grails has a solution at the ready – controller interceptors. All we had to do was declare an interceptor that fires before insert and update closures, and in that closure, inspect our list of check boxes and set a params value that would then be assigned to our domain object through the normal binding process.
By using an interceptor, we completely avoided the need to generate (and assume custodianship of) the insert and update closures in this controller – which means we didn’t have to spend valuable time writing unit tests to cover these Grails-supplied features that could be broken once the code actually exists.
I guess I can summarize this little victory this way: Having tested code for an application feature is far better than having untested code. Having no code at all is better than either.
Stay Groovy, my friends.
I’ve looked at clouds from both sides now…
I stumbled across a very cool cloud-based music service called SoundCloud (http://www.soundcloud.com) today. I love it for two very different reasons. First, it’s a great (maybe even killer) application of cloud computing technology, taking advantage of the Great Server Farm In the Sky to solve a real problem. Second, I love the solution itself.
See, technology is my day job. When I’m not working (or walking the dog, or schlepping kids around town), I usually have some sort of musical instrument in my hands. or in front of me. Guitar, mandolin, bass, keyboards, drums and trumpet, for now. Hope to add to the collection soon – I think I need a bouzouki. Or maybe a dobro. But I digress…
When I have a block of free time and a little peace and quite in the house, I like to break out my recording gear and see what I can throw together. And, occasionally, share it with a few friends to see what they think. Or even send a track to a friend who’s a real drummer to lay down a drum track for me to mix in later.
In the past, sharing music online has been inconvenient at best. Oh, there are music sharing sites like SoundClick, or social sites like MySpace that cater to musicians. But they all have some pretty serious limitations (like having to actually log into their service to find and listen to tracks).
SoundCloud is different. It’s a seriously open, cloud-based music storage and publishing service. I just signed up an hour ago, and within minutes I was uploading my first track. (I love, by the way, that you specify the file to upload first, and it automatically starts uploading while you fill in the track info form.)
But the really cool part is the openness of the service. There’s no need for anyone to go to their site to hear my music. I can email it to them, or drop a widget into Facebook or a blog entry (as I’ve done here), and voila. Music. Where I want it. No strings attached.
And now, if you’ll excuse me, I have a recording project to dive into…
