Aspect-Oriented Programming

I’ve started looking at Aspect-Oriented Programming (AOP) recently, because of its potential for improving code readability and maintainability. This is mainly provided by the “separations of concerns” goal that AOP aims to achieve. To get started, I decided to jump in using the jQuery AOP plugin. Why jQuery/JavaScript instead of something more mature like AspectJ? Well, for one thing, I have spent quite a bit of personal time developing with JavaScript and it seemed like a logical place to get a good footing before diving deeper with something like AspectJ.

AOP’s goals

The main aims of AOP are to improve program modularity by increasing the “separation of concerns”. What exactly does that mean? To be certain, plain old Object-Oriented Programming (OOP) already drastically increases program modularity; but there is still room for improvement. In particular, AOP seeks to address the issue of crosscutting concerns, that is, functionality which “cuts across” or overlaps multiple areas of a system.

For example, most web applications will have authentication and/or authorization as cross-cutting concerns. Some pseudo-code for showing a user’s personal “Todo” list is shown below:

if (isUserAuthenticated())
{
  items = getUserTodoList(getUserContext());
  foreach (items as item)
  {
    // Output each todo item to the page...
  }
}
else
{
  // Redirect to login page...
}

The act of checking if the user is authenticated has become entangled with the core business logic of showing the items of the “Todo” list. Indeed, this can become cumbersome as the business logic functionality expands; for example, we might have to write such “boilerplate” code to check for authentication for each page that requires it.

Of course, this is just a contrived example. This particular authentication problem has already been nicely solved in many languages such as Java (J2EE) and PHP. In either of these languages, for instance, you’ll find multiple frameworks that take the grunt work out of a common problem like this, but it highlights how cross-cutting concerns can interfere with and decrease the modularity of a system, making it harder to maintain.

Separation of concerns aims to refactor this code to reduce the overlap in functionality, so that core business logic can be separated from the cross-cutting concerns, which then become known as aspects. One area that AOP suffers from is the confusing terminology. Thankfully, the folks behind the great Spring Framework have written an excellent guide to the terms and AOP itself. I suggest you take at least a quick look at it.

Simplicity through Separation

AOP achieves its goals by defining join points where certain advice can be executed before or after the code at the join point. A join point is simply a certain point in the program code and is typically the point where a method begins execution.

Typically, there are three types of “advice” that can be weaved or attached to a join point: Before, After and Around. “Before” advice will execute just prior to the method to which it is attached, but cannot modify the execution of that method. That is, the “Before” advice cannot stop the execution of the method. “After” advice will execute directly proceeding the return from the method to which it is attached, and it can typically get access to the return value from the method.

“Around” advice is called before the method itself, and can alter the behaviour of the method to which it is attached. Typically, this includes deciding whether or not the method should be invoked at all, or even modifying the arguments passed to it. Thus “Around” advice is the most powerful.

It should be noted that for AOP to be truly effective the invocation of the advice attached to a method/join point must be transparent. That is, once the advice has been attached to a target object/method, one should not have to invoke the target method in any special manner in order to get the advice to fire.

One other term to note is the pointcut. A pointcut is simply a predicate/expression that selects a set of join points. Thus, by defining a pointcut, advice can be attached to multiple join points that meet/match the pointcut’s expression. In fact, this is typically how AOP is modeled from a high-level point-of-view. When reaching a join point that matches a certain pointcut predicate, the advice associated with that pointcut is invoked.

AOP with jQuery

But all of these explanations and terms may still be confusing without a concrete example, so for that we’ll take a look at the jQuery AOP plugin. JavaScript (especially with jQuery) is not really a place where AOP is used heavily or needed, since the use of callbacks already provides some level of separation of concerns. Indeed, the Ajax Events available for hooking into using jQuery already provide some sort of AOP-like functionality.

Having said that, the jQuery AOP plugin is quite easy to use. Here’s a quick example that allows you to keep track of the number of event handlers invoked:

Site = new Object();
Site.handlerInvokeCount = 0;
jQuery(function()
{
  // Note: Must apply the advice to the function(s) BEFORE binding as an event
  // handler.
  jQuery.aop.around( {target: window, method: /^handle[A-Z]/}, 
  function(invocation) {
    window.alert("Invoking `"  + invocation.method + "`");
    
    window.alert("Number of event handlers invoked so far: " + ++Site.handlerInvokeCount);
    
    // Note: Can stop the invocation of the target method by *not* calling 
    // proceed().
    return invocation.proceed();
  });
  
  jQuery("form").submit(handleFormSubmission);

});

function handleFormSubmission(e)
{
  e.preventDefault();
  window.alert("Inside handleFormSubmission");
}

Here, we attach advice around any global function whose name starts with “handle” and is followed by a camel-case name, such as handleFormSubmission. We don’t do anything interesting but increment and report the current count for the number of “handle” methods invoked. We then attach the handleFormSubmission to a form submission event.

It’s worthwhile to note that you must attach or “weave” the aspect to the function before binding the function any any events. This is because when you bind a function to an event, it is copied over by reference. The jQuery AOP plugin essentially weaves advice to functions by creating a new function that includes both the advice and an invocation of the original function. However, if you do this after binding the function to an event handler, the event handler will still refer to the original function, that is, the one without any advice attached to it!

Conclusion

AOP may have limited utility in JavaScript, as I’ve found, thanks to excellent JavaScript libraries such as jQuery. jQuery already achieves decent separation of concerns thanks to the many built-in callbacks, mainly for Ajax events. It also supports the use of custom events, which may be used in a similar manner to some AOP advice types.

While a full-fledged AOP solution may not be needed in some situations, it’s worthwhile to note that many frameworks still adopt an AOP-like model. For example, CakePHP’s controllers have an extensive list of callbacks that can be used to control execution of the main controller’s actions. These allow you to separate out your concerns from the main program logic for maintainability and reuse.

One Comment »

  1. […] Chung has an excellent article about Jquery AOP if you’d like to learn […]

Comments are now closed for this entry.