AOP Madness and Sanity: A Response

Graham Hamilton has blogged about AOP: Madness and Sanity. The central theme of the blog seems to be based on a notion that any language that runs on the Java platform must follow the JLS and it is okay for a J2EE container, but not for aspects, to affect program semantics.

Yes, J2EE has been using AOP all along!

This is a myth. The reality is that J2EE has been helping with certain crosscutting concerns such as transaction management and security in a rigid, pre-defined way. AOP is a much more general approach, which works not only for J2EE-like applications, but also for Swing/SWT UI applications and real-time applications etc. Aspects are useful even along with J2EE containers, where the container falls short in meeting project’s needs, as witnessed by the success of the Spring Framework using AOP to improve on J2EE.

As far as possible we have tried to follow the principle that “what you get is what you see”.

This might have been a reasonable argument before Java 1.3. With the addition of dynamic proxies, this argument now works against Java. If I see a method call to an object, I cannot say anything unless I know the proxies in which the object is wrapped. On the other hand, aspects along with tools, very directly show you that there is an advice being applied there. See screenshots in New AJDT releases ease AOP development for examples of these.

The code-that-you-write is the code-that-gets-executed is a thing of a distant past. There is so much post-compilation byte code modification that there is a competition among byte code engineering tools! With JVMTI in Java 5, there is even a blessed mechanism to modify the code while being fed to the VM. I don’t think this “what you get…” argument is even worth putting forward anymore.

The container can intercept incoming calls and add additional semantics. An example of this approach is the way that Java EE containers can add transactional semantics to EJB components by intercepting incoming calls.

And how does JLS come into the picture here (your next point)? Why are these containers more blessed than others? What is the difference between (the presumed good) additional semantics and (the presumed evil) changed semantics? What if I don’t have a blessed container that meets my needs? For example, what should I do as a poor Swing application developer, who is trying to write a responsive application using multiple threads and end up with a ton of duplicated boilerplate code to route calls to the event dispatcher thread? Would it be so bad if I can write a few aspects that make me more productive immediately or should I wait for some blessed container (or its third version!) to help me?

Some uses of AOP rely on using runtime mechanisms to modify semantics that are specified by the Java Language Specification (JLS). For example, side files might specify that various modifications are to be made to target classes to invoke additional code when various operations are performed. Some uses of AOP allow extra code to be invoked when fields are accessed or when methods are called.

AOP systems have their own semantics and language specifications. For example, AspectJ has semantics of interaction between classes and aspects. One needs to understand those semantics associated with the aspects to understand the overall system behavior. In an AOP system, aspects are a first-class participant, not a “side file” at all.

Understanding a Java-based AOP system only in terms of Java is similar to understanding C++ in terms of C semantics. You can’t make the required leap if you limit yourself to expressing classes in terms of structures and method dispatch in terms of invoking an array of function pointers. Similarly, thinking about AOP in terms of JLS and code modification won’t help in understanding the real value of AOP. Indeed, thinking about Java semantics by considering machine code instructions is similarly not helpful: the additional abstractions provide software engineering benefits. The use of byte code modification or the use of proxies is simply an implementation mechanism for AOP.

This criticism of AOP is similar to how procedural crowd responded to OOP. Sure, OOP did obscure the program flow, but we ended up liking the “obscurity”. See my response to myth Aspects obscure program flow for more thoughts.

The real value of AOP is in directly expressing design intents in programming constructs. If my security requirement is to check permission before any publicly accessible method in a class in banking or its subpackage, AOP allows me to map this requirement directly in an aspect such the following. I can now review the implementation and check its adherence to the requirements. If any requirements change, I can simply modify the aspect.

public aspect BankingSecurity {
    pointcut bankingOperation() : execution(* banking..*.*(..));

    before() : bankingOperation() {
        AccessController.checkPermission();
    }
}

Whether this aspect modifies byte code of the selected methods, or a proxy is created that implements the advice, or a VM takes care of dispatching the advice is a secondary consideration.

The JLS carefully specifies the precise semantics of the Java language.

And so does <An-AOP-system>LS. It is just different than the JLS. Fortunately for the Java community, Sun has been supporting alternative languages for the Java platform.

To take an extreme example, if a developer has written a statement “a = b;” then they should be able to rely on the value of the field “b” being assigned to the field “a”, with no side effects. Some AOP toolkits allow arbitrary extra code to be executed when this statement runs, so that there can be arbitrary extra side effects as part of this assignment or even so that an arbitrary different value may be assigned to “a”.

The join point models of AOP systems are pretty restrictive on what you can advise, based on writing maintainable code. In fact, that is how it stands apart from generic byte code modification tools and metaprogramming. AOP’s disciplined approach prevents developers from writing hard-to-maintain programs (within reason, of course, since a determined individual can always write bad program in any language or system).

So let’s consider the “a=b;” example. First of all, you can advise such a statement only if it represents an exposed join point. So for AspectJ, “a” or “b” must be a field of a class: local variables won’t do. Second, is it so arbitrary if I have a “side effect” of notifying observers of state-modification implemented through an aspect? Or is it so arbitrary if I mark the object holding “a” as dirty? In each of these cases, I can modularize observer and dirty-tracking functionality into an aspect rather than scattering it in all the places that modify the state of an object.

Yikes! Similarly, some uses of AOP permit extra code to be inserted on a method call from one method to another, even when the JLS clearly specifies that that method call will occur directly. This enables arbitrary extra code to be executed, with potentially arbitrary side effects, in situations where a Java developer should expect there will be no side effects.

So it is okay for a container to invoke extra code to implement security and transaction management (which may very well use byte-code modification as an implementation technique), but it is not okay for an aspect to do the same thing? Once again, what gives a container a special status? Not the JLS.

“Yikes” would be a response of a Java programmer unaware of an AOP system being used, but it would be a perfectly normal behavior to, say, an AspectJ developer.

In J2SE 5.0, the concept of annotations was added to the Java language. In many ways, annotations were designed to meet similar goals to AOP. The concept of annotations is that developers may apply special markers to target method, fields, or classes in order to designate that they should be processed specially by tools and/or runtime libraries.

So will it be okay if that “tools and/or runtime libraries” is an AOP compiler (like AspectJ) or an AOP system (like Spring)?

See discussion of myth Annotations obviate AOP for a quick response. There is a lot to be said here about AOP’s use of metadata. See “AOP and metadata: A perfect match”, Part 1 and Part 2.

The use of container based AOP seems to provide a reasonable mechanism for supporting AOP “cross cutting concerns” within Java environments, without breaking developers’ expectations of how Java source code behaves.

Knowing the JLS is not sufficient to understand the behavior of a class in a container. For example, if I see an EJB with security attributes specified in its deployment descriptor, would a Java developer expect its methods to throw an authorization exception? See my more detailed response to myth Application frameworks obviate AOP.

Java has been a great language and platform. However, it is coming to a point where some serious innovation is needed to ensure that it remains the front runner. AOP is one such innovation that exemplifies the capability of the core Java platform. AOP addresses crosscutting concerns without having to wait for someone to provide a framework and learn each framework and its versions anew. However, exploiting AOP subject to a strict adherence to the limited approaches of the past is unhelpful.

This entry was posted in Technology. Bookmark the permalink.

8 Responses to AOP Madness and Sanity: A Response

  1. Robert says:

    Very well written! Thank you!

  2. iyad says:

    I second what you are saying, you presented very well what i wanted to say..

    on other note.. Reflection can obscure the wokflow and make the program flow difficult to understand

  3. narendra says:

    A long while ago when aspectj was still a project at xerox parc lab in release (until I guess it was relase .5 or .6) I gave it a long and hard look. That time java did not had anything like that. Annotations were not there and proxies had just entered the scene (I am not sure of that either). What I was trying to figure at that time was if aop would revolutionize the programming as much as oop did. That time I reached the conclusion that it would never happen. Reason was simple, it is a solution which can be applied only to a very small set of real world problem. So I decided to forget about it. After several years I suddenly started hearing about AOP again. This time it was thanks to JBOSS. Wow what a difference a company can make. When Microsoft came with xmlhttp control nobody in java world cared. Suddenly there is AJAX when google started using it. Now any java shop will gladly use it. Same is the case with AOP. Now my friend coming back to your blog, you make a strong case for AOP. It is a nice tool if you have a task which needs it. But in last 10 years or so of professional programming I did not came across a single problem which could benefit from AOP. In the end I do agree with your contention that for java to remain front runner (in the race of cutting edge in languages) it needs some serious innovation. Its just that AOP is not the innovation which would do that. You will need to look else where. I will be glad to hear from you (years before people will take you seriously) if you have that innovation in works.

  4. Narendra,

    But in last 10 years or so of professional programming I did not came across a single problem which could benefit from AOP.

    Take a look at TOC of AspectJ in Action or examples in downloadable sources or a list of problems mentioned on this TSS thread. How did you solve those problems while avoiding duplicated code?

    I will be glad to hear from you (years before people will take you seriously) if you have that innovation in works.

    People are already taking me and other AOP proponents seriously! Sure there are a few who don’t. But that is to be expected. Not everyone understands the value proposition of every technology they come across. I, for sure, have failed to recognize value proposition of a few technologies until much later.

    -Ramnivas

  5. jgehtland says:

    Strange. In 5+ years of Java development, I’ve come across literally hundreds of problems that could have, and did, benefit from AOP (in its many guises). Dynamic proxies, transaction maangement, enterprise security, test-harnessing, and on and on and on. If one looks at AOP as a continuum from static proxies to dynamic proxies to woven interceptors, then the history of Java framework development over the last five years IS the story of AOP. Heck, in my world view, Servlet filters are step 0 on this path. I can certainly understand taking the viewpoint that Hamilton did if you are a platform purist (though I don’t agree) but I really don’t understand the blanket argument taht AOP is a solution without a problem. It is a more elegant solution to a lot of problems that people have been trying to solve in Java frameworks for a long time.

    Let’s put it a different way: without AOP, Spring wouldn’t be very useful. And Spring is certainly useful.

  6. Jonas says:

    Thanks Ramnivas.
    Very well written (as usual), right to the point.
    /Jonas

  7. Mohan Radhakrishnan says:

    Narendra’s comment is very interesting. In the past 8 months I have come across so many problems that can be solved by AOP more elegantly and many of those don’t have a proper OO solution. If I had actually tried to find AOP problems for 10 years I could written a couple of AOP books.

  8. Nikhil says:

    I keep reading articles trying to justify and argue against AOP. This seems frankly archaic, the concept is there and relevant. In general, I think the initial adoption for cross-cutting concerns is very obvious. For example, tracing is a good example. Another might be establishing of a robust test harnesses.

    What I do find missing is sufficient information on best practices and anti-patterns for AOP (apart from the myths “article” by Ramnivas, and a small handfull of such articles. I think in this space there is a lot of progress to be made to facilitate adoption.