Thursday, July 31, 2008

AOPing and loving it.

I've always thought of AOP in terms of things like AspectJ which manipulate byte code (I don't really love the idea of byte code injection) , and never really as a design pattern that could be implemented in Java.  But lo and behold there are plenty of Java based implementations (I believe based on dynamic proxies).   I've been using Spring's implementation of the AOP Alliance API   http://aopalliance.sourceforge.net/doc/index.html
Using AOP really allows you to cut down on non-model related code in your model.  One of the classic examples is logging, how great would it be to not see any logging code in your model code?  We do lots of reporting on our models and sometimes it's very difficult to hook into the model at certain points to do the reporting.   
We just started adding in AOP hooks to our factories.  Which has been great.  Now we just pass a method interceptor to a factory, and the factory takes care of wrapping the appropriate objects with our interceptor.  On the reporting side we have a reference to our method interceptor.  As our code is running the method interceptor is collecting state that we can report on.  It's like totally non-invasive implementation of the observer pattern.  I love it.  
Suddenly we have a whole new world of reporting and testing that we can do which would have been very difficult previously.  
Seriously, think about testing.  If you're unlucky enough to be stuck with legacy code that's hard to work with, but lucky enough that the developers used factories.  If you can slip in a mechanism for  wrapping objects now suddenly what was difficult to test is easy! You just intercept a method call on an object you care about and verify that it's state is correct, or what ever the heck you want to do.  I'm finding it über powerful.
But with über power comes über responsibility. Yeah an implementation of a method interceptor might look like so:
Object invoke(MethodInvocation i) throws Throwable {
   Foo foo = (Foo) i.getThis();
   if (foo.isAFoo()) {
        System.out.println("yay found a foo");
   }
  Object ret=i.proceed();
  return ret;
}
I just want to point out here you suddenly have access to an instance of foo and also all the arguments that were passed in.  So woe unto thee who changes state whilst intercepting a method.  Because good luck debugging that.  Besides that troubling point, this stuff is awesome.
yeah, "lo and behold", and "woe unto thee", I wonder how many idioms I can slip into into a blog post without running out of steam.

2 comments:

ekerwin said...

When you first started ranting about AOP I was concerned about the byte code thing. But using it as a pattern to wrap things is fine.

I also agree that you really need to watch that state-modifying behavior. I think it allows developers a great opportunity to screw stuff up. "Oh, I can just add that in here..." and two months later, the app is crashing and nobody can figure out why. But isn't that always the way, anyway? Sign. Software is for noobs.

Zachary D. Shaw said...

"it allows great opportunity to screw stuff up"

so yes, a nail gun provides great opportunity to shoot yourself with nails, but I'd sure rather use a nail gun to build a house than pound nails with a hammer all day.

Heck I'd rather even get shot with nails than have to build a house with only a hammer.

I don't know anything about building houses :(

 
Web Statistics