Wednesday, April 29, 2009

Groovy Categories vs ExpandoMetaClass

I first saw Groovy in Nov 2007 and promptly decided to dive in over my head and write a DSL in it. One thing that I never quite got was why one would want to use a Category versus ExpandoMetaClass. Having to create a class with a bunch of static methods and then surround other classes in it didn't seem very elegant. Directly adding behavior to a class with an ExpandoMetaClass is much more straightforward. I thought that the Category approach must be a hold over from Groovy releases prior to 1.5 when ExpandoMetaClass was added. The only use case I could come up with for them was if you wanted to add the same functionality to a set of classes - sort of an AOP view of things.

But then Groovy 1.6 came out and I saw that the team had added some very cool annotations to make categories even more powerful and easier to use. (See InfoQ for a great write up of the 1.6 features.) Okay - you don't improve a dead feature, so what was I missing?

This past weekend I got a chance to ask the person from whom I first learned about Groovy, Scott Davis. His Blue Pill and Red Pill talks at NFJS were what first got my mind churning about the possibilities that Groovy opened up. Before sitting in on another of his talks at the most recent NFJS conference this past weekend, I asked him why one would use categories in a DSL rather than modifying meta classes? His answer told me that I was asking the wrong question. The strength of categories is in scoping - modifying behavior for a limited period of time. The primary example he gave was for unit tests. A category can short circuit certain behavior (like retrieving info from a DB or from a file) to make it easier to test certain behavior in isolation. This makes a lot of sense. Mocks/stubs have their place; they are useful when you need to work with an object in a very limited sense - just a few calls. Then there are times when you want a real object doing 95% of what it is supposed to do, but you want to take over in just a few situations to be able to insert custom behavior. e.g. in a unit test when you want to short circuit network or file-based activity or you want to purposefully force an error condition.

It so happens that I really need to improve the unit tests for some network-based components in the ETL system that I work with. The primary one is called GetHttpContent, so you can imagine that unit testing it can be a pain. I'll give Categories a closer look to see if they can help me out. Unfortunately, I have to wait until we finish shifting to a our new project structure because right now there are so many dependencies in the primary project that if I work on a groovy file in that project in Eclipse I lose ~20M of memory every time I edit it. But the limitations (and benefits) of the Eclipse groovy plugin can wait for another post.

Originality through Ignorance

You have to admire the restraint some people show when faced with somebody else expounding on the obvious. I was sitting with my friend and coworker, Jeff Erikson, at the recent No Fluff Just Stuff conference explaining that I had decided to come out of my "I have way to much stuff to do" shell and start blogging. I had three reasons:
1. Most of the stuff I learn and then write up for our various projects comes from publicly available sources like other blogs and articles, plus a little bit of my own work gluing it together. So it seemed only fair to publish the results back where it could help others.
2. It was a good way to find out when I really didn't know what I was talking about since any readers would gladly point out (in the nicest of terms) that I was off base and should perhaps find another occupation.
3. It was a good way to create a public record of what I have worked on in case such a thing should ever come in handy for unnamed reasons.

Jeff was nice enough to listen politely without smacking me upside the head and saying, "Read the first entry in my blog." That would be the article where he talks about the keynote speech by Jared Richardson at the Rich Web Experience conference last fall which outlines much the same reasons for starting a blog.

That piece of humble pie tasted really good. Especially with a nice chaser of irony since anyone who works with me knows that I hate reinventing the wheel. Hopefully, my new resolution to do more regular reading (rather than cramming on new techs when I need to use them) will help me avoid thinking I am original when, in fact, I am just ignorant.