Friday, February 22, 2008

AOP rescued me today!!!

Agility has to do with how you can apply programming techniques to solve usual problems that usually takes long time to be developed. If it's not a time constraint, it is code design and this "bad smell" is going to rest there until you use refactoring methods to organize "your home".

During the development of my vOtopus, my personal web server for my Advanced Internet Design and Engineering class, I got the usual requirement of loggin capability, where I should print out the execution path for debug purposes, and about the clients' request information. So I started adding the following Logger information:
import java.util.logging.Logger;
...
private Logger vologger = Logger.getLogger("tracer");
I started smelling the bad code again when I had pasted the same line of code into 3 classes... When you only know OOP, or Object-Oriented Programming, you can do everything using the same old Pojo classes. However, I thought that this would be the best time to rescue myself and put AOP, or Aspect-Oriented Programming, into practice (Check the Wikipedia for a complete introduction to the concepts behind AOP).

Anyway, it had been a long time when I first studied AOP, still in 2004 while taking my Internship at Motorola, and I was just using on simple and small applications by my own using AspectJ, one of the most used implementations and available at the Eclipse IDE as a plug-in. Today, I definitely felt the need to use this paradigm to quickly design and implement a simple and reusable solution, maintaining quality and integrity of my system already designed (VOtopus Architecture). I tried to maintain designed with as loosely coupled as possible (most of them a weak dependency) through the use of the "Program to an Interface, not to an Implementation" idea.
  • Log requirements
I just need to print the execution path, or the access information into my webserver log. Instead of pasting the code snippet above, I created an Aspect whose responsibility, here implemented as pointcuts, were used to intercept all the classes from my already designed system I wanted to log, without adding invasive code, as I was doing while pasting the loggin code snippet.
pointcut vOcotpusPackage() : execution(* edu.sfsu.cs.csc867.msales.voctopus..*(..)) || execution(edu.sfsu.cs.csc867.msales.voctopus..new(..));
It's clear how Aspect-Oriented Programming deal with this cross-cutting concern. The "loggin concern" isn't part of the webserver business logic, but it is a concern that cross-cuts the entire application because each individual class need that functionality.

The next step was to create advices around the join points, or the moment in which we are going to do something related in the pointcut. That means before the execution, after the execution, during the execution... Find out more about it at Aspect-Oriented Programming. For my webserver, I just want to give the advice saying "I'm advising you that my join points are the ones exactly before the execution of any method or constructor from the pointcuts called loggableCalls". It's really clear that this is the only code I needed to implement the "tracer" for method calls (private, default, protected, public).

before() : loggableCalls() {

if (this.vologger.isLoggable(Level.INFO)) {
Signature sig = thisJoinPointStaticPart.getSignature();
this.vologger.logp(Level.INFO, sig.getDeclaringType().getName(), sig.getName(), "Entering");
}
}

There are a lot of discussions on this subject due to the a lot of things you can do with AOP. Check the links about and have fun being agile with AspectJ.

No comments:

StartupCTO - Helping Small Teams Develop Great Software