Every program has a subject domain. In a shipping system, that domain might involve customers, orders, prices, inventory, shippers and so on. In a medical office, it would be patients, records and procedures. For some special programs, however, the domain is programs. These special programs are called metaprograms, and the language a metaprogram is written in is called the metalanguage.
The most familiar metaprograms are compilers, virtual machines, IDEs and the like; these are commonly written in C, C++, Java or C#. A Perl script to check for naming conventions in your Java code is also a metaprogram, with Perl as the metalanguage. Using grep to look for calls to a certain procedure is also metaprogramming, with grep regular expressions as the metalanguage.
So metaprograms come in a range of sizes and can be written in a range of languages. Metalanguages can be imperative, like C or Perl, or declarative, like grep regular expressions.
The key property that all metaprograms share is that they explicitly manipulate other programs or program representations.
Is AOP Metaprogramming?
First, let's consider method declarations. Nearly 20 years ago, some programmers would look at a method declaration and read it as saying "Add an entry to the method table, with this name and this code body. This was a metaprogramming semantics for object-oriented programming. The method declaration was explicitly manipulating the method table. This was a natural way for early adopters to look at the technology, because they were concerned not only with what OO provided, but with the way it was implemented.
But today, we read method declarations as saying "This is what happens when I call this method on this class of object. This is a direct semantics for objects. (To their credit, OO pioneers like Dahl, Nygaard and Kay almost always used a direct semantics when talking about OO.)
Today, early adopters often discuss AOP using a metaprogramming semantics. For example, they may describe advice as meaning "Insert this code in all these places. The origin of AOP in reflection, combined with the early adoption process, has made this reading seem natural.
But when AOP was developed, it was intended to be a move away from explicit metaprogramming to a direct semantics for some of the kinds of problems metaprogramming could be used for.
The direct semantics for AOP is like the direct semantics for OOP. We read an advice declaration as saying "This is what happens when execution reaches these points. We read an inter-type declaration as saying "This is what happens when I call a method on this class of object.
A direct semantics for AOP has many advantages. It allows more leeway for the implementer of the AOP language. If an AOP language is specified as "inserting calls at these places in the code, that's what the weaver has to do. But if it has a direct semantics, it's legal for the implementation to weave by inserting calls in the code at compile time, or during loading, or even by doing it as an integral part of the virtual machine.
Another advantage of a direct semantics for AOP is that it helps with abstraction. When we look at a complex object model, it's simpler to think of it as describing the behavior of the objects, rather than describing transformations on method tables that implement the behavior of objects. The same is true of AOP—it's simpler to think in terms of aspects of an object's behavior, rather than transformations on classes, which transform method tables, which implement the behavior of objects.
AOP isn't explicit metaprogramming. Instead, it provides a direct semantics for designing and coding crosscutting concerns. AOP language designers and more experienced AOP programmers work with AOP in terms of a direct semantics, because of the increased flexibility and abstraction it offers.
Can Metaprogramming Do AOP?
If AOP isn't metaprogramming, it's still a natural question to ask whether metaprogramming can be used to implement aspects. The answer, of course, is "Yes, but ...
Consider implementing AOP problems using a bytecode manipulation tool like JavaAssist, BCEL, ASM or JMangler. Using these tools, you write a program, in Java, that uses the JavaAssist API to explicitly manipulate other Java code. This is explicit metaprogramming, in which the metalanguage is Java. It's very powerful.
For most applications, however, it's too powerful. Because the metalanguage is so potent, it can transform the code in any way imaginable. AOP mechanisms are more limited, and as a result they preclude many bad ideas. For example, you can use a metaprogramming tool to trap more fine-grained join points than most AOP languages allow. (Of course, AOP languages don't prevent all bad programs—only the power switch does that.)
So you can implement aspects with explicit metaprogramming, but for applications that can be done with AOP, you're more likely to want to use AOP. The AOP program will be shorter, and it'll be easier to recognize what it's doing. The IDE can even show you the crosscutting structure of AOP advice; it can't do that for a general-purpose metaprogramming tool.
Don't get me wrong—I like metaprogramming. Before starting to work on AOP, I worked on metaprogramming, reflection and metaobject protocols. AOP isn't better than metaprogramming tools—just different. For some applications, you need the greater power of metaprogramming; for example, when implementing an AOP language itself. Some applications benefit from the use of both AOP and an explicit metaprogramming tool. The tool can be used to handle the kind of code-generation work that AOP doesn't do, but AOP's direct semantics makes it simpler to use for most of the problems it can handle.
When you're using AOP, remember the difference between metaprogramming semantics and direct semantics. Think in terms of direct semantics as much as possible. This will help you with abstraction, and will push you to think of the aspects as design elements in their own right. In this way, you'll master aspect design and development faster.
Gregor Kiczales led the Xerox PARC teams that developed aspect-oriented programming and AspectJ, and is an AOP researcher, consultant and trainer based in Vancouver.