Introduction to AspectJ from the Adaptive Programming Perspective

Note:
The LoD checkers are now at:
http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/AspectJCheckers/

We introduce AspectJ focussing on its adaptive programming capabilities
and we develop an adaptive AspectJ program that works actively with any
Java program. By working actively we mean that the AspectJ program
is actively influencing the program behavior. The Java program does
not just ignore the aspect.

(Note: AspectJ pointcuts don't impose a constraint on the 
base program in that the compiler will not complain
if a pointcut is empty. Consider pointcut ce1(A a): this(a).
If the base does not have a class A the pointcut ce1
will always be empty but AspectJ will not tell us.
)

Adaptive Programming (AP) got started through the Law of Demeter (LoD),
AP influenced the AspectJ 
work and in this paper we close the loop and express the
Law of Demeter as an AspectJ program. 

We formulate the Object Form of the Law of Demeter as an adaptive program. AspectJ program checking Object and Class Form of the Law of Demeter By David Lorenz: AspectJ program checking Object Form of the Law of Demeter. This program uses a different set of features of AspectJ to check the Law of Demeter. Comparing the two solutions is interesting and teaches a whole lot about AspectJ. AspectJ is a programming language from Xerox PARC developed by Gregor Kiczales and his AspectJ team. AspectJ uses a language feature, called pointcuts, to express interaction between concerns adaptively. The pointcuts select the points where the interaction takes place. A pointcut is formulated in terms of partial information about a Java "base" program. A pointcut selects a set of points related to the base program. A pointcut is adaptive in that it works actively with an entire family of structurally diverse base programs. A pointcut combined with advice qualifies as an adaptive program that enhances an entire family of structurally diverse base programs. We use the following informal definition (AP book 1996): An adaptive program enhances a family of structurally diverse base programs and the adaptive program is expressed using a property-based specification of a crosscutting set of points related to the base program. In AspectJ pointcuts may be formulated with various degrees of adaptiveness. pointcut ce1(A a): this(a); defines the set of points where the currently executing object is of class A. // pce2 pointcut ce2(Object a): this(a); defines the set of points where the currently executing object is of class Object (we capture all points). ce2 is more adaptive than ce1 in that it works actively on a larger family of base programs. Pointcut ce2 works with any Java base program but it does not do any work for us. In AspectJ we can associate code with a pointcut: // afterpce2 after(Object a): ce2(a) { System.out.println("at " + a + " " + thisJoinPoint.getSourceLocation().getFileName()); } which prints something for each point selected by pointcut ce2. The combination of pce2 and afterpce2 is an example of an adaptive program that works actively with any Java base program. This example demonstrates that AspectJ facilitates the formulation of adaptive software. Adaptive software has the goal to separate concerns by minimizing dependencies between the aspects (AP book 1996, page 78). This is achieved by using property-based specifications of crosscutting sets rather than enumerating the sets element by element. For example, the this pointcut is a property based specification of a crosscutting set of points namely all points where the currently executing object is of some class. As pointed out in (AP book 1996, page 79), adaptive software can be realized in different ways and here we focus on the realization in AspectJ. A second useful pointcut is the target pointcut. The this pointcut and the target pointcut combined can be used to talk about edges in the dynamic call graph of the Java program. In other words, we can talk about caller-callee relationships. // pct2 pointcut ct2(Object a): target(a); defines the set of points where the current receiver object is of class Object (we capture all points). A useful pointcut is the call pointcut. For example, call(void f(B)) talks about all points where a method called f, returning void and with an argument of class B is called. Pointcuts may be combined using the set operation && to take the intersection of sets. Consider now an interesting intersection of the three kinds of pointcuts we introduced so far: pointcut callsite(Object caller, Object callee): this(caller) && target(callee) && call(* *(..)); The callsite pointcut is a very adaptive pointcut. It works actively with any base program because any Java program uses class Object. The pointcut selects all calls in the Java program (irrespective of return type, method name and arguments) and it makes the caller and callee available for each such point. The pointcut is adaptive because both the this and the target pointcut are adaptive and because the call pointcut uses the wildcard symbol * extensively not restricting the kind of function that may be called. AspectJ pointcuts are about expressing the interaction between concerns. In this paper we are interested in the following two concerns: (1) The composite concern expressed by the programmer in a Java program; (2) The coupling concern that is concerned about the programmer overextending him or herself by having to think about too many methods when studying a given method. The coupling concern crosscuts the Java program (representing a composite concern) in that we need to reason about all method calls occurring in the Java program. AspectJ programs may be written in a structure-shy style. "structure-shy" is here used as a synonym for "adaptive". Pointcut callsite is an example of a structure-shy pointcut that is composed of three simpler structure-shy pointcuts. AspectJ programs may be written in a crosscutting style. Again pointcut callsite is an example of a crosscutting pointcut that is composed of three simpler crosscutting pointcuts: this, target and call. The AspectJ literature typically talks about crosscutting and plays down the fact that crosscutting and structure-shy are tightly linked. hardwire = bad : is a way to summarize shy programming. hardwiring anything is bad: don't hardwire class graphs, interactions between concerns (pointcuts), etc. AspectJ also supports the within pointcut which talks about all points within some class or aspect. And we can use the complement operator to combine pointcuts. The pointcuts that we consider here live in an aspect (similar to a class) called Check and we don't want to include points within Check. This is expressed by the following pointcut: pointcut callsite(Object caller, Object callee): this(caller) && target(callee) && call(* *(..)) && !within(Check); The callsite pointcut will be used in the LoD checker to verify whether all the call sites satisfy the LoD, i.e., the callee object must be of a restricted type.