This month, I’m writing about common AOP misconceptions. I don’t want to sound critical—these errors are easy to make. More importantly, they can link together and cause you real problems in understanding and working with AOP.
Different people understand new ideas in different ways. Some seek to develop a general model of the idea. Others think in terms of how it’s used. Still others focus on how it works. Each of these perspectives is valuable, and as a developer, you ultimately want all three perspectives on AOP. I’ve grouped the common misconceptions along these three perspectives.
People often equate AOP with the concept of separation of concerns (SOC). They say things like “AOP promises separation of concerns in source code.” This is a subtle overgeneralization—they’re taking AOP to be equivalent to the more general goal of SOC, but AOP is just one approach to SOC. There are others, including object-oriented programming (OOP), structure programming and so on.
So it’s more correct to say, “AOP helps separate crosscutting concerns in source code.” This difference is subtle, but crucial, suggesting that AOP addresses some separation problems, while other techniques address other separation problems. The more correct statement naturally leads to comparisons among AOP, OOP and other SOC approaches.
It’s also easy to under-generalize by confusing AOP with one specific AOP language. You’ll often read text that mistakes AspectJ or JBoss AOP for the general definition of AOP. This error is like saying OOP is just C++ or just Smalltalk. Of course, if you’re familiar with only a single AOP system, this is an easy mistake to make.
But such generalization errors can spread, and that’s when they cause real problems. For example, a common misconception is that AOP is a preprocessor or code transformation technique. The root of this misconception is an under-generalization error—because some implementations of AOP are preprocessors, it’s possible to incorrectly assume that all of AOP is preprocessor-based. Seeing AOP as a preprocessor precludes understanding its power as a first-class programming language construct.
Current AOP languages differ in many respects, including static typing, IDE support, efficiency and existence of aspect libraries. One notable difference is whether AOP is integrated into the main programming language, as in AspectJ, overlayed over the main language, as in the most recent AspectWerkz, or as a separate framework or language, as in JBoss AOP. Don’t confuse the properties of any one AOP language on these dimensions as defining all AOP languages on these dimensions.
To avoid generalization errors, a good rule of thumb is to think of AOP as being like OOP, and for any statement about AOP, ask yourself whether it makes sense for OOP—not just whether it’s true or false. For example, consider “OOP is a code-transformation technology.” This statement just doesn’t make sense. We know that OOP is too broad a category to make a claim like this about it: Some OO tools are, and some aren’t. The same is true for AOP. Many AOP generalization errors can be avoided with this rule of thumb.
Another kind of misconception has to do with the purpose and use of AOP. The most common of these is that AOP is used only for logging. In fact, three kinds of aspects are in use today.
General-purpose aspects include logging, tracing, failure handling, transaction support and the like. Most AOP programs use such aspects, and in fact, reusable libraries of these aspects are starting to appear.
Domain-specific aspects are common to a domain or product line; say, insurance or automotive. Most applications written in the domain recognize and can make use of such aspects. For example, your product-line architecture might use an aspect to enforce the rule that low-level packages can’t call high-level packages; or you might have a specific set of authentication and authorization aspects to use in your domain.
Application-specific aspects implement crosscutting functionality that pertains to a single application. This can include something as specific as the pre- and post-condition checking for a single class. This is the same breakdown we see with OOP classes today, and as AOP matures, I expect the ratio among these three kinds of aspects will be roughly the same as it is among these three kinds of classes.
Another way to understand AOP is in terms of how it works. A common misconception associated with this perspective is to equate all of AOP with just one part of the supporting mechanisms. This kind of error is analogous to saying that OOP is just abstract data types.
Probably the most common mechanism error is to equate AOP with interceptors. (Lisp hackers have their own version of this error: They say that AOP is just the old advise feature.) This misconception is so common that the response is nearly a perma-thread. Googling for “AOP != interception” gets 588 hits.
It’s true that AOP does use functionality like interceptors and Lisp advise. It also incorporates techniques from reflection, multiple inheritance, multi-methods and others. However, AOP has an explicit focus on crosscutting structure and the modularization of crosscutting concerns.
The rule of thumb to avoid mechanism errors? Remember that AOP is more than any one mechanism—it’s an approach to modularizing crosscutting concerns that’s supported by a variety of mechanisms, including pointcuts, advice and introduction.
No Silver Bullet
Finally, watch out for the most dangerous misconception of all—that AOP is a silver bullet that makes hard problems go away. It may seem surprising that this misconception could exist, but it does.
Watch out for claims like AOP will make tough transactional problems like ensuring ACIDity (atomicity, consistency, isolation and durability) easy. Certainly, AOP makes crosscutting concerns modular, which in turn can make them dramatically easier to understand. So, AOP can clarify the code for your exception policy, but you must still evaluate whether it’s the right policy.
Thus, while AOP can reduce the apparent complexity of your code down to the inherent complexity of your design, complex systems still require careful thought, and, AOP or no, an incorrect design remains incorrect.
AOP is a new idea, and it’s inevitable that certain misconceptions will arise as we seek to learn how to use it. Identifying and talking about those misconceptions will expedite our mastery of AOP, and enable us to reap its benefits.
Next month: IDE support for AOP.
Gregor Kiczales led the Xerox PARC teams that developed aspect-oriented programming
and AspectJ, and is a leading AOP evangelist based in Vancouver.