Tuesday, September 19, 2006

What about AOP?

I have read a lot of stuff on AOP recently. In the past couple years both the CACM and IEEE Software dedicated entire issues to AOP. However, after reading both of these and a host of other stuff I remained largely unconvinced.

However, when coding tricky projects we have been faced with times when we wished that we could inject code compiler at compile time - a typical thing that AOP will allow. In addition, I can see the utility of AOP for a lot of developer tools, for example, TypeMock - a C# mock object framework, uses AOP extensively. This brought me back to AOP.

I decided I would try (again) to do something with AspectJ. It seems to be one of the big guns of the AOP world (in CACM and IEEE Software, there were articles that originated with this project). In addition, there are very good AspectJ tools for Eclipse. This time, to help me I bought the Addison Wesley book on AspectJ with Eclipse (I forget the name just now). And decided I would try to read it over the summer holidays.

To my surprise, the book offered a new picture of AspectJ. In its introductory chapter it actually solved a real problem (serialization of objects) with something that seemed to be an AOP application (not a just a developer tool) that was useful. Much of the authors claims made sense. That is, use aspects to modualize objects that are in different inheritance hierachies. The serialization example was very convincing.

The idea is that a lot of busness objects should not mix thier busness logic with there "book keeping" code (for example how the object is stored). The result was similar code that cut across a number of unrelated objects could be treated in a unified way.

The more I looked at the examples presented by the author and the more I thought of it, the less excited I became. I am, however convinced that if used as another programming tool, AOP can be useful, but if you abuse the AOP hammer, I think you will end of with a big, complex, distributed mess. Here are my main beefs,

  1. In Holub's Pattern book he makes a convincing pitch that objects should be able to save themselves in context. According to Holub, getter and setter (or properties if you come from C# land) are evil. I believe Holub in this case. The serialization aspect can not just save everyone by looking set and get methods and use them to serialize the object. Object serialization is a task the object must participate in. This is made clear in Holub's book. Otherwise, we trade modularity of the serialization code for a tangle of aspect and object code, with the guts of the objects exposed in the wild, rather than carefully concealed.
  2. I note that in AspectJ you can write point cuts on private join points. For example, we could execute a bit of code every time the program accessed a private field. Is this really a good idea. Is it not really fragile to use a private point cut? The implementing private method has made no contract to exist and may be changed at anytime. This type of aspects might be good to hack to do something like unit testing with mocks, but we can not write application code like this.
  3. Aspect interpretation is hard... too hard. When I read my first paper on AspectJ the authors emphasized that tool support would be required if the framework was to be adopted. I think that tool support is good, but tool requirement is bad. That is, if when I write a point cut I need a tool to show me which objects (might be affected), then I am in trouble. I think that writing point cuts is like writing regular expression. Seems easy until you have to do something really hard. Sometimes you ge more hits tht you think you will and it is very difficult to see the difference. With this, the advantage of AOP (localized code for dispersed object) becomes a disadvantage. You never know which objects will be hid by an AOP bug and the object and aspect code are dispersed, so you might have a hard time locating the bad line of code.
  4. Your object can not count on aspects (usually). Here is a philosphical point. Should the object know there will be an aspect attached to it. If not, why does it not implement all the code required to do its business (rather that stuffing some code in a aspect). If it does know, why is it not more specific about its contract with the aspect. I think this is where I am now. I would like to use aspects, but I would like my objects to expose a public point cut interface that could be used by the aspect for stuff the object would have had to do. Then and only then can the object remove "non-business" code. Otherwise, the only thing we have done is created a dependance between the object and the aspect that is implicit, required but very weak (can you ship the object without the aspect - AspectJ say - go ahead).

So there is my 2 cents worth on AOP. I think when we do AOP the objects would do well to define a set of exposed point cuts. I don't think we should bend over backwards looking for aspects - aspects are suppose to deal with cross-cutting issues. If there are no cross-cutting issues using an aspect (or inventing an abstract cross-cutting issue) is just making things more difficult than it needs to be (I had the impression to read an article like this in IEEE Software). Finally, I don't think that an aspect should ever point cut a private or protected or package join point. Maybe for a developer tool, but not for a application. An OO programmer would not use reflection to execute a private method just because he could after all, so an aspect should not do the same thing.

No comments: