Aspect-oriented programming (AOP) has emerged as a promising technology for solving a number of software structuring problems. Several industry leaders are taking public steps toward AOP: IBM is supporting AspectJ on Eclipse, BEA has released its WebLogic Aspects Framework, and JBoss is using its own AOP tool. Other supported tools include AspectWerkz and Nanning. In the face of AOP’s rising popularity, this new column, Crosscut, will explore a range of technical and process issues concerning this still-evolving technology.
The history of object-oriented programming (OOP) provides some clear lessons about the adoption of new programming technologies. Early adopters were the first to really think objects throughout the software lifecycle, and as such, got more of the benefits—more flexible architectures, easier maintenance and faster prototyping. These pioneers also helped develop, in large part, the practices and platforms we now use. But, with any new technology, you must carefully risk-manage such adoption to avoid damaging critical efforts. You must move incrementally, from one developer to one project, and then to multiple projects. Finally, you must ground your evaluation in real systems and real projects; otherwise, you might miss the technology’s promise and costs.
These lessons apply to AOP: BEA has catalyzed a discussion of initial aspect libraries, with their J2EE pointcuts. These libraries, like the class libraries of OOP, will ultimately be of great business value and will stand at the core of standard practice; companies that contribute to these libraries will have an advantage over later adopters. The AspectJ support in Eclipse is now defining the initial outlines of IDE support for AOP. So there is every reason for companies that want to be leaders in AOP to begin working with it. At the same time, it’s wise to get into AOP in a well thought-out way.
1. Careful Exploration
Fortunately, early adopters can follow a well-established process that builds on two key properties of existing AOP tools: They’re compatible with any Java virtual machine and with many development environments. Therefore, you can use aspects in your own work in a way that’s invisible to other members of your project team. After you’ve evaluated AOP privately for a few months, you’ll be in an excellent position to discuss its benefits and costs with your colleagues.
The first step? Select which AOP tool you want to evaluate. In later columns, I’ll provide a detailed comparison; but for now, I’ll assume you’ve chosen AspectJ, simply because it’s currently the most mature offering, in terms of technical development, documentation and IDE support. Much of the knowledge you’ll obtain by following this approach applies for all AOP tools. (AspectJ is available at http://eclipse.org/aspectj .)
Once you have an AOP tool installed, you can begin using it on your own copy of the project sources. The key is to restrict yourself to writing aspects used only during development, not as part of the production code base (in other words, don’t check the aspects into the common code repository). By contrast, production aspects are part of the shipping product.
2. Probing and Debugging
Start by using development aspects for probing or debugging your code base. For example, a simple bit of aspect code can show the various different calls to a method, with caller-specific information, to help find a faulty execution path.
<FONT COLOR="#FF0000"> before(): call(* MyResourcePool.allocate(..)) { System.out.println("allocate called from " + thisJoinPoint); }</FONT>
You’ll probably end up developing your own library of tracing aspects for your project’s code base. When the time comes, that library can serve as an excellent starting point for other project members to begin using AOP—or not. I’ve seen consultants whose clients aren’t yet ready to use AOP in production code use it to help quickly diagnose problems. There are also specialized tools that can do this kind of tracing for you. The AOP tools are general-purpose—whether you rely on a small number of general-purpose tools or a large number of special-purpose tools is your choice, though I prefer the former.
3. Enforcing Contracts
A good next step is to use aspects to enforce design contracts. If you’re familiar with Bertrand Meyer’s Design by Contract, you’ll be pleased to know that AOP can gather your contracts into clear modular units—each aspect is a collection of related contracts. For example, this aspect implements the setter contracts for the methods of a simple Point class:
aspect PointContracts { /* the ways x gets set */ pointcut setX(int x): (call(void Point.setX(int)) && args(x)) || (call(void Point.setXY(int, int)) && args(x)); <similarly for y> /* the pre-conditions */ before(int x): setX(x) { assert((MIN_X <= x) && (x <= MAX_X)); } <similarly for Y> /* the post conditions */ after(Point p, int x) returning: setX(x) && target(p) { assert(x == p.getX()); } <similarly fory> }
AOP tools can also enforce static contracts—that is, design contracts that are checked at compile time. Many of us follow the design rule that all accesses to a class’s fields must be through getter and setter methods, even within the class itself. The following aspect enforces this rule at compile time:
declare error: get(* MyClass.*) && !withincode(* MyClass.get*()): "Must use getter method to get fields.";
If your project follows this design rule, try this aspect on your code—you may be surprised at the number of violations you find. Again, as you work, you can develop a library that enforces such standards.
4. Prototyping with Production Aspects
Now that you’ve played with development aspects, it’s time to take the next exploratory step: writing production aspects as you develop new functionality. AOP can help you quickly develop designs for crosscutting functionality. For example, you might be developing a new exception-logging policy for your product. Working with AOP, you could write code like:
after() throwing(Exception e): execution (public * com.acme.product..*.*(..)) { log(thisJoinPointStaticPart.getShortSignature(), e); }
This code says that exceptions thrown by all public methods in your product are logged, with information about the exception and the method throwing it. Once you know this is the right functionality, you can manually insert the required code at each public method—in other words, revert to pre-AOP technology. You can comment each of those sites with a reference to this cleaner piece of aspect code.
Even though you must manually insert code in all those methods, you now have clear documentation of what the scattered code does. And there’s another benefit: You’ve built a set of concrete examples of ways that your project could benefit from using aspects in production code.
Remember, however: AOP doesn’t replace OOP; it simply solves problems
with crosscutting functionality that OOP can’t handle cleanly. If a given
problem doesn’t require AOP, don’t
use it.
Eyes Open; Small Steps
AOP may be a young technology whose tools are still evolving, but it isn’t too soon for individuals and companies to begin working with it. In the programming world, the early bird gets much of the worm. But explore carefully—the landscape is littered with projects that jumped into new technologies too fast. Fortunately, those who follow an incremental, concrete and risk-managed path often find that they’re the first to reap the benefits.
Next month: How does the history of programming language technology help us evaluate AOP tools?
Gregor Kiczales founded the PARC AOP and AspectJ
projects, and is an AOP leading expert and evangelist.