Attribute Oriented Programming != Aspect Oriented Programming

Recently, I have been reading about various implementations of Aspect Oriented Programming, AOP. It is interesting that many in the .Net world equate attributes with aspects. This is disconcerting. Attribute Oriented Programming != Aspect Oriented Programming. I am sure many of the authors out there understand the distinction and are merely talking about a particular implementation of AOP. The issue that I have is that because of these writings many now believe that aspects are a superset of attributes. Or that Attributes + Interception=AOP. Yes, Attributes + Interception is an implementation but there are other implementations as well. If you look at the original work by Gregor Kiczales and team who came up with AOP and AspectJ, you will find that their implementation of an Aspect is quite different then the .Net Attribute. www.aspectj.org provides a great deal of information on AOP and AspectJ as does the following white-paper White Paper.

 

Some have argued that without a Point-Cut composition model (that some interception models fail to employ) it is not AOP (see Ted Neward’s blog entry). Personally, I think this is a bit harsh, but I understand the point that Ted is trying to make and I do believe that without a Point-Cut composition model your implementation is considerably weaker. The key to AOP is to capture and modularize cross-cutting concerns.

 

What is needed is an understanding of AOP. Once people have a general understanding of AOP, then you can discuss various implementation models. To illustrate some of what AOP is meant to solve, take a look at the following class:

 

public class HelloWorld

{

public HelloWorld ()

public GiveGreeting()

{

Console.WriteLine(“Hello World”);

}

}

 

Everything is nice. It does what it is supposed to. Now let’s say you want to implement logging for your class. So let’s add logging code to the class:

 

public class HelloWorld

{

public HelloWorld ()

public GiveGreeting()

{

MyLogger logger=new MyLogger();

try

{

logger.Log(“before in GiveGreeting”);

Console.WriteLine(“Hello World”);

}

catch(Exception ex)

{

logger.Log(“throwing in GiveGreeting.”);

}

finally

{

logger.Log(“after in GiveGreeting”);

}

}

}

 

All the code added for logging is in Red. Even though we have modularized logging (e.g. MyLogger) into a class, the OO paradigm does not let us effectively modularize the implementation of our logging. The logging code we added to the HelloWorld class illustrates what is called Scattering or tangling. Scattering or tangling occurs when the code needed to implement one concern is spread out over and tangled within the code needed to satisfy another concern. Scattering or tangling is the result of OO’s inability to handle what is called a cross-cutting concern. We call this cross-cutting because the modularization we are seeking cross-cuts the hierarchical structure of OO (actually AOP complements procedural languages as well…but that is another topic). The problem tangling and scattering causes are almost self-evident:

  • Creates tangled code
  • Maintenance is more difficult
  • It violates separation of concerns (e.g. HelloWorld is not concerned with logging but has to deal with it).
  • ….

 

There are other terms in the AOP vernacular as well. Much of these terms have come about because of AspectJ. Does this mean that all implementations must implement the terms described below? Some yes and some No. I will discuss this further below.

 

Join Point (from WhitePaper)

“…those elements of the component language semantics that the aspect programs coordinate with.”

 

In other words, the invocation of a method is a Join Point. Or the setting of a property is a join point….Something we can join to in order to add cross-cutting functionality.

 

Pointcut (an article by Vaughn Spurlin.)

A Pointcut is essentially a predicate defined on a set of Join Points. A Pointcut can be named and used throughout an aspect. Join Points are anonymous and are never referred to individually, but only as members of a Pointcut. A particular Pointcut is either true or false at any Join Point throughout the source code base.

 

The term Pointcut does not come up in the original Whitepaper discussed above; however, the whitepaper does discuss the concept of a filter for finding Join Points which is what Pointcut composition is all about. I like to think of Pointcut composition as a meta-language (for lack of a better term) for finding Join Points. In a presentation I gave at the Greenville, SC user group meeting one person in the group said it reminded him of an XPath query. It was a nice analogy.

 

Advice Declaration (an article by Vaughn Spurlin.)

An Advice Declaration consists of an 'advice type' followed by a Pointcut, followed by an executable 'advice body'. When the control flow of a Java program passes through a Join Point for which the Pointcut is true, the advice body is executed. The advice type determines exactly when the execution occurs. For example, if the advice type is "after()" and the Pointcut specifies calls to certain methods, then the advice body is executed after returning from calls to the methods. The advice body is the executable code inserted at the byte level mentioned above.

 

The problem with this definition is it is too AspectJ’ish. However, the concept of Advice is valid. Basically it let’s you marry a Pointcut; when to execute (e.g. before, after, after exception, etc.); and a piece of code to insert/weave/execute (depending upon your implementation).

 

In other words, when you come across a join point defined within a Pointcut, I want you to execute this piece of code “before” you step into the piece of code defined by the Join Point (e.g. a method call or similar).

 

Inter-Type Member Declaration (an article by Vaughn Spurlin.)

An inter-type member declaration is a mechanism for adding members to a class from outside the class without modifying the class source. This makes it possible to add fields and methods that are not related to the primary purpose of a class.

 

This is an interesting concept that AspectJ implemented. You can literally extend the definition of a class without using derivation by adding variables, properties (and even constructors) to another class. The idea is that you should only do so to aid in the implementation of cross-cutting concerns.

 

Aspect (an article by Vaughn Spurlin.)

An aspect is a top-level construct that may contain Point-cuts, advice declarations, inter-type member declarations, and other declarations that would be valid as … class members. Aspects are defined at the same level as classes, and are the basic modular units of aspect-oriented programming.

 

Sample Code

aspect Logger { ß Notice that an aspect is a Pier of class.

    pointcut log():          ß Definition of a Pointcut.

        execution(* *.getGreeting(..)) || execution(* *.setGreeting(..));  

   

    before() : log() { ß Advice typed to a Pointcut (log()) and some code).

        System.out.println("  Logger: " +

            thisJoinPoint.getSignature());

    } 

}

 

 

The above implementation defines an aspect as a pier to a class. In other words, it is an extension to the language. This is a key concept in AspectJ's implementation of AOP. It also presents a very valid argument for why Attribute Oriented Programming is not Aspect Oriented Programming and it removes the false declaration that Attributes + Interception=AOP. Instead it presents the argument that it is merely an implementation and if the implementation does not consider Pointcut composition or Inter-Type declarations, it is a weaker implementation...IMHO....

 

The AspectJ model is also what is called a “Static” model. This means it has its own compiler that allows it to weave “Aspect” code into the underlying compiled byte code (the .Net equivalent of byte code is IL code). The other type of model is what is called a “Dynamic” model and it typically involves some type of interception. I believe that much of the confusion in the .Net world is due to the article on MSDN by Chris Sells, Simon Fell and Dharma Shukla. This article presents an AOP model using Interception and Attributes and it is definitely worth reading. However, the article does not present it within the context of the different features of other AOP models. Nor does it discuss Join Points, Pointcuts and Aspects. So now many people wrongly equate AOP with  Interception+Attributes as opposed to just a simplified implementation. But I digress and this is my own personal opinion of why the current perception of AOP exists in the .Net community....

 

The model presented by Sells, Fells and Shukla is an example of a dynamic model; however, as I pointed out, this model does not have a Pointcut composition model and the concept of Advice is limited to “Pre” invocation and “Post” invocation.  Furthermore, rumor has it that ContextBoundObject will be deprecated with the Whidbey release. This means that you may want to hold-off on rolling it out across your company until after you see the Whidbey release. Now, I do believe this moves us in the right direction of a feature rich implementation of AOP in .Net; however, we as a community need to evolve how we think of AOP and what it promises...and that is so much more then Attributes and Interception.

 

At the end of the day, AOP is the answer to modularizing cross-cutting concerns. An implementation of AOP can either be static or dynamic. Static has the advantages of being faster (e.g. it is compiled) and dynamic has the advantage of not modifying the underlying source code but will have a slower execution time. Both models will work and one that employs a Pointcut composition model is preferred (which I hope to start soon). The Java world is also evolving. Companies like BEA have created Dynamic AOP models and are rolling it out with their product line. I have yet to look at the features they possess but I will do so shortly.

3 Comments

  • Other than the MSDN article you have listed do you know of any other dynamic AOP implementation for dotnet?



    I'm trying to figure out away to intercept the loading of an assembly and then modify particular types dynamically. The only why that I can figure to do that right now is by using the .NET Profiling APIs, which are a pain. Do you know of any other way to do this?



    Thanks,

    Wes

  • There are two other possibilites to intercept the loading of the assembly: you could try to generate dynamically the proxy classes for loaded classes like LOOM.NET (another dotnet AOP Implementation) or you could try to modify the IL of the assembly before loading it like some .NET persistence Tools do. This is called "Code enhancement".

  • alex muninov in a code project provided an approach for code enhancement at the IL level that showed some promise. it wasn't in the realm of AOP but when i read it i instantly saw the potential connection.

    -Mathew Nolton

Comments have been disabled for this content.