You are on page 1of 56

Concepts of AOP, Study of AspectJ's

Limitations, and CaesarJ


Jan Grék
Concepts of AOP, Study of AspectJ's Limitations, and CaesarJ
Jan Grék

Published June 2007


Copyright © 2007 Jan Grék
Table of Contents
Dedication ......................................................................................................................... vi
Abstract ........................................................................................................................... vii
1. Introduction .................................................................................................................... 1
Hard Problems of Software Development – Coggins (Y. 1997) ............................................. 1
AOP, FOP, AP, SOP, Hyperslices (1990s) ......................................................................... 1
Summary ................................................................................................................... 2
2. Aspect-Oriented Programming ............................................................................................ 4
AOP – G. Kiczales (Y. 1997) ......................................................................................... 4
Summary ........................................................................................................... 5
AOP – Filman, Friedman (Y. 2000) ................................................................................. 5
Summary ........................................................................................................... 6
Summary ................................................................................................................... 7
3. AspectJ – Basic Constructs ................................................................................................. 8
Joinpoints .................................................................................................................. 8
Pointcuts .................................................................................................................... 8
Advice ..................................................................................................................... 11
Aspects .................................................................................................................... 11
Summary .................................................................................................................. 12
4. Modular Reasoning in the Presence of AOP ......................................................................... 13
Definition of Terms – Kiczales, Mezini (Y. 2005) ............................................................. 13
What's Wrong with Traditional Modularity Measures ........................................................ 13
Coupling .......................................................................................................... 13
Cohesion .......................................................................................................... 14
Approaches to Modular Reasoning – Aldrich (Y. 2004), Kiczales, Mezini (Y. 2005) ................ 14
Summary .................................................................................................................. 15
5. AspectJ – Advanced Constructs ......................................................................................... 17
Aspect Inheritance in AspectJ ....................................................................................... 17
The Jumping Aspect Problem and Vanishing Aspects ........................................................ 17
Vanishing Aspects – Constanza (Y. 2000) ............................................................... 17
Jumping Aspect Problem – Brichau et. al. (Y. 2000) .................................................. 18
Summary .......................................................................................................... 19
GoF Design Patterns and SOP – Vlissides (Y. 1998) ......................................................... 19
GoF Design Patterns and AOP – Hannemann, Kiczales (Y. 2002) ........................................ 20
Observer Pattern Implementation in AspectJ – Hannemann, Kiczales ........................... 21
Highlights of the AspectJ Implementation of Gof Design Patterns ............................... 23
Summary .......................................................................................................... 24
Inter-Type Declarations and Per-Clause .......................................................................... 24
Observer Pattern Implementation in AspectJ with Inter-type-member Declarations ......... 25
Per-Clause ........................................................................................................ 28
Observer Pattern Implementation in AspectJ with Per-clause ...................................... 28
Summary .......................................................................................................... 35
6. CaesarJ ......................................................................................................................... 36
Introduction .............................................................................................................. 36
Deficiencies of AspectJ – Mezini, Ostermann (Y. 2003) ..................................................... 36
Aspect Collaboration Interfaces (ACIs) .......................................................................... 37
The Expression Problem – P. Wadler (Y. 1998) ................................................................ 39
Virtual Classes and Solution to the Expression Problem – Ernst, Ostermann, Cook (Y.
2006) ....................................................................................................................... 40
CaesarJ's Solution to AspectJ Deficiencies ...................................................................... 42
7. Conclusions ................................................................................................................... 44
Filman and Friedman's definition of AOP ....................................................................... 44

iii
Concepts of AOP, Study of AspectJ's
Limitations, and CaesarJ

The Essence of AspectJ-like Programming ...................................................................... 44


Coupling, Cohesion, Encapsulation and Modular Reasoning .............................................. 44
AspectJ's Modularity – Language Features Discordance .................................................... 45
AspectJ – Recommendation for Small Improvements ........................................................ 45
Bibliography ..................................................................................................................... 46
Glossary ........................................................................................................................... 48

iv
List of Examples
3.1. Statically Undeterminable Pointcuts ................................................................................. 10
5.1. Jumping Aspect Problem ............................................................................................... 18
5.2. ObserverProtocol, General Part in AspectJ – Hannemann, Kiczales ........................................ 22
5.3. ObserverProtocol Binding in AspectJ – Hannemann, Kiczales .............................................. 23
5.4. ObserverProtocol with Inter-type-member Ddeclarations ..................................................... 26
5.5. ObserverProtocol Binding with Inter-type-member Declarations ........................................... 27
5.6. ObserverProtocol with Per-clause in AspectJ ..................................................................... 30
5.7. ObserverProtocol Binding with Per-clause in AspectJ .......................................................... 32
6.1. ObserverProtocol ACI ................................................................................................... 37
6.2. ObserverProtocolImpl in CaesarJ .................................................................................... 38
6.3. ObserverProtocol Binding in CaesarJ ............................................................................... 39
6.4. A Virtual Class for the Expression Problem ....................................................................... 41
6.5. A Virtual Class after Addition of a Negative Expression ....................................................... 41
6.6. A Virtual Class after Addition of a Negative Expression ....................................................... 41
6.7. A Combination of a Negative Expression and eval() method ................................................. 42
6.8. LazyColorObserver ...................................................................................................... 42

v
Dedication
To the authors of AspectJ Programming Guide – many thanks for keeping my brain active. I am just so
fed up with those precise, complete and educating materials!

vi
Abstract
Aspect-oriented Programming (AOP) has gained a lot of attention in the last ten years. AOP techniques
and approaches have been studied by academics and quite successful implementations (AspectJ) are being
used in practice.

AOP is a very broad and fast-developing discipline and this might be a reason, there is a lack of understand-
ing, what AOP is about, in practitioner area, as well as in academics. I found, there are two kinds of tutorials
available: ones, their understanding is too shallow and others, understanding of which is too narrow.

This work tries to fill this gap, mapping authors way through AOP-related papers and websites to his own
practicing in AspectJ and to his own conclusions about AOP. It is kind of a walk through important
achievements in the field of AOP in the style of highly objective historical approach, as well as highly
concrete study of fine AspectJ's features and their mutual non-compliance, as well as study of topics espe-
cially relevant to evaluation of AOP as a new programming paradigm. Every topic is followed with author's
conclusions.

This work includes these topics: Historical approaches to the separation of concerns, related to AOP, At-
tempts to define AOP, Failing of structured development theory in the presence of AOP, Approaches to
modular reasoning with AOP, Introduction to AspectJ GoF Design patterns implementation in AspectJ, a
case study in modularity; All rational Observer design pattern implementations in AspectJ, study in AspectJ's
features' discordance; Evolution in AspectJ – Jumping aspect problem, CaesarJ's philosophy – AOP is not
about join point interception, Evolution in CaesarJ – Expression problem (extensibility problem),

The main contributions of this work are: connecting theory with practice in the learning process, rectification
of AspectJ Programming Guide in its approach and corrections in some important details, elaborated study
of AspectJ's implementations of the observer design pattern, thereby revealing AspectJ limitations; author's
own opinion on topics covered.

Particularly worth of pointing out is discovery of some kind of historical pattern in AOP: improvements
of modularity do not consider modularity of their own mechanism. An interesting implementation of the
observer design pattern is given, that was yet not considered, by interfacing aspects to Java (partially imit-
ating CaesarJ's unified approach). Study of AspectJ's features suggests there are possible relatively small
improvements in language semantics with sensible impact on its modularity.

Way through writing this work led me to my own conclusions, as realizing that success of AspectJ-like
programming lies in its local mechanism for separation and handling of overlapping parts of completely
nonorthogonal concerns, that makes it also special.

I hope, reading through this work will do the same job for its readers.

vii
Chapter 1. Introduction
Hard Problems of Software Development – Cog-
gins (Y. 1997)
Software development can be – according to James Coggins [ Coggins 1996 ] – characterised as: “a difficult
intellectual and social activity, coding is not where the real challenge of software development lies. The
hard problems are the larger questions ” and suggests several illustratory questions:

• What software does the client need?

• What functions must the software support?

• How should the software interact with its intended social, political, and regulatory environment?

• How should the software be organized into modules?

..., and continues: “These questions are not answerable in software: they require a combination of human,
systemic, and technical reasoning, negotiation ad debate, measurement and evaluation. ”

Coggins continues and hits the nail on its head with the following questions:

Does OOP programming address these essential questions of software development? Quick answer
follows. “No.” He characterizes OOP as: “a collection of mechanisms, rules, and pragmas govering the
structure of small-to-medium sized bodies of code.”, and continues that OOP actually is a “coding discipline”
and the questions above “aren't a coding issue”.

Can object oriented programming have a long-term strategic impact on software development? His
answer is - yes. This was proven in the recent past.

Questions and answers Coggins gave in 1996 exactly signaled shortcuts of OOP languages like Java that
were about to emerge in large software systems. It took almost a decade since 1996 production-ready im-
plementations of AOP came to rescue with a particular problem of OOP – no support for multidimensional
decomposition.

AOP, FOP, AP, SOP, Hyperslices (1990s)


In this section I give a review of historical approaches to composition and decomposition of programs in
relation to OOP.

Approaches to program composition, 1990s


• feature-oriented programming (FOP)

• adaptive-programming (AP)

• subject-oriented programming (SOP), Hyperslices

• aspect-oriented programming (AOP)

Feature Oriented Programming (FOP). Traditionally, feature is a unit of functionality as specified


by the end user. Target of FOP is given by features specification. FOP is aimed at situations, when one

1
Introduction

faces to designing families of related programs (so called product families). FOP software is designed in
terms of models that are being automatically transformed into programs. Adding functionality may create
cross-cutting concerns.

“To add a feature to an OO [object-oriented] framework, there are predefined methods and classes that are
to be extended... ...there is little or no quantification, but there are indeed cross-cuts.” [Schwartz]

Adaptive Programming (AP). This methodology was laid down by K. Lieberherr in a book “Adaptive
Object-Oriented Software: The Demeter Method with Propagation Patterns ”. Lieberherr describes adaptive
object-oriented programming as “expressing the elements – classes and methods – that are essential to an
application, by avoiding a commitment on the particular class structure of the application. ”. Actually, this
is a general meaning of so called “Law of Demeter”, which explicitly guides programmer to keep low
coupling between modules (It says, “Just talk to your friends.”). Law of Demeter for functions means, that
instead of calling function B from body of function A(in a separate module M2) to get X, I rather put X
on the interface of function A to get A(M2.B). Such code has got better modularity. That's just to the basic
idea of AP.

Subject Oriented Programming (SOP). Subject-oriented Programming is a composition technology


of object-oriented programs initiated by Harold Ossher and Bill Harrison at IBM. “In subject-oriented
programming, a subject is a collection of classes or class fragments whose class hierarchy models its domain
in its own, subjective way. A subject may be a complete application in itself, or it may be an incomplete
fragment that must be composed with other subjects to produce a complete application. ” See ht-
tp://www.ccs.neu.edu/research/demeter/SOP/.

Hyperslices. [Tarr et. al. 1999] describe Hyperslices as: “...a new paradigm for modeling and imple-
menting software artifacts, one that permits separation of OVERLAPPING concerns along multiple dimen-
sions of composition and decomposition. ”

“A hyperslice is a set of conventional modules, written in any formalism. Hyperslices are intended to en-
capsulate concerns in dimensions other than the dominant one. The modules within it contain all, and only,
those units that pertain to, or address, a given concern.”

“Done well, separation of concerns can provide many software engineering benefits, including reduced
complexity, improved reusability, and simpler evolution. The choice of boundaries for separate concerns
depends on both requirements on the system and on the kind(s) of decomposition and composition a given
formalism supports. The predominant methodologies and formalisms available, however, support only
orthogonal separations of concerns, along single dimensions of composition and decomposition. These
characteristics lead to a number of well-known and difficult problems. ” Solving “commonalities” from
different hyperslices happens in hypermodules: “...composition cannot be a fully automatic process. It is
the task of the composition rule in the hypermodule to specify the details of composition. ”

Complexity of the composition rules together with low granularity of the composition later showed [HyperJ]
as the main hurdle of this approach.

Aspect Oriented Programming (AOP). AOP was introduced by [Kiczales et al. 1997]. In the focus
of AOP is separation of s.c. “crosscutting concerns” (for definition, see the section called “AOP – G.
Kiczales (Y. 1997)”). The main difference of AOP to previous techniques is usage of a powerful compos-
ition language (in the paper it was lisp macros) to solve its task.

Summary
AP, AOP and SOP were laid down in the same decade. All these techniques try to aleviate separation of
concerns (SOC), in some way. AP and SOP are bound by context of their definition to object-oriented
programming.

2
Introduction

As we will see later, AOP is not derived from OOP and is not just a complement to OOP. However, AOP
is a separate “technique” from OOP it is very often considered (even implicitly) in the context of OOP.

Historically, AP respected AOP as one of its own part and vice-versa. Later, AP has been redefined as a
part of AOP and today, we can only say that AP is AOP restricted to graphs and traversal strategies.

There are also very rare definitions of AOP from early 1990s that nobody that nobody refers to, today. For
further information on early AOP-related approaches, see http://www.ccs.neu.edu/research/de-
meter/AOP/early-def/AP-AOP.html. Extensive study of AOP-related techniques can be found in [Assmann
2003].

3
Chapter 2. Aspect-Oriented Programming
AOP – G. Kiczales (Y. 1997)
The approach of aspect-oriented programming, was introduced in a famous paper by [ Kiczales et al. 1997
]. Actually, AOP was here described as a “new programming technique”.

“We have found many programming problems for which neither procedural nor object-oriented programming
techniques are sufficient to clearly capture some of the important design decisions [design decisions – if
they cause, what is here called tangling – we call today cross-cutting concerns] the program must implement.
This forces the implementation of those design decisions to be scattered throughout the code, resulting in
tangled code [general form of tangling is today called just cross-cutting; there are two forms of it (today):
tangling and scattering] that is excessively difficult to develop and maintain. ...We call the properties
[properties are some constraints] these decisions address [meaning: these decisions are collections of
properties] aspects [thus: aspects = properties in those cross-cutting concerns],... ”

There were yet not said what IS AOP, but what it does: “[AOP] makes it possible to clearly express programs
involving such aspects [aspects means in 1997 constraints], including appropriate isolation, composition
and reuse of the aspect code. ”

The most important outcome of the paper is conclusion that distinguishing factor of AOP is a notion of
s.c. “cross-cutting concern”.

Definition (Kiczales et. al.). Cross-cutting concern arises, in general, whenever two properties being
programmed must compose differently and yet be coordinated.

Examples of cross-cutting concerns. Classical examples of cross-cutting, let's say, from the area of
J2EE programming, are logging, security, caching, exception handling, synchronization.

For the purpose of this work I identify three types of cross-cutting (called also tangling, vaguely).

• tangled code that can be removed by further decomposition (T)

• scattered code, caused by dominant decomposition of the problem, while multiple decomposition is
desirable (SD)

• scattering independent of decomposition criteria – “Some aspects are so common that they can easily
be thought about without reference to any particular domain. ” (e.g. exception handling) (SID)

In the presence of scattering, even a little change IN ONE CONCERN requires performing it on multiple
places. In the presence of tangling, it is not easy to specify what and how has to be changed, when change
is made, nobody can be sure that the coexisting concern was not changed, either. In general, tangling makes
reasoning about code difficult.

Why “cross-cutting”? [ Kiczales et al. 1997 ] show, how the diagram of a functional decomposition
of the problem, cross-cuts its data-flow diagram – where-from cross-cutting took its name.

Notice. I suppose a reader of this chapter has already seen, how AspectJ-like programming looks like.
If not so, I encourage her/him to do so.

AOP-based implementation of an application consists of [Kiczales et al. 1997]:

• (i.a) a component language with which to program the components,

4
Aspect-Oriented Programming

• (i.b) one or more aspect languages with which to program the aspects,

• (ii) an aspect weaver for the combined languages,

• (iii.a) A component program, that implements the components using the component language,

• (iii.b) one or more aspect programs that implement the aspects using the aspect languages

AOP-based implementation works using mechanism called join point interception. This mechanism is in
the very core of the AOP.

Definition. join point interception (JPI) is a mechanism, that allows triggering methods on certain events
in programs (e.g. function call) using available context of the event (e.g. function arguments). Points in
programs, representing these events are called join-ponits. Of course, JPI is declared from a place separate
to where it applies. Example of JPI is e.g. “Windows Hooks”.

A Terminological Note. The term aspect in [ Kiczales et al. 1997 ] was used in the meaning of a cross-
cutting concern, as in the meaning of the unit of its implementation! “With respect to a system and its im-
plementation using a generalized procedure language, a property that must be implemented is (1) a com-
ponent, if its implementation can be cleanly encapsulated in a generalized procedure (i.e. object, method,
procedure, API). By cleanly, we mean well-localized, and easily accessed and composed as necessary or
(2) an aspect, if its implementation cannot be cleanly encapsulated in a generalized procedure. ” Since later
on, till now, the term aspect is being used pervasively in the meaning of the unit of implementation of
particular concern. This is due to an AspectJ terminology that I will try to stick to.

Aspect as a transformation. AOP, was in [ Kiczales et al. 1997 ] compared, also, to some kind of
transformation, specifically: “A transformation that takes some program in a higher-level language and
passes it through other programs (aspects) and adds some extra properties to it. Usually, transformation
programs operate in terms of the syntax of the program being transformed.”

The concept of transformations is traditional one, with similar ideas to AOP, but with different goals.

Summary
The idea of AOP must not apply only to OO languages. Even, AOP doesn't have to be necessarily a separable
technique – functional languages, like Lisp or Scheme, make use of AOP techniques by means of own
language features.

Systems that had got AOP properties had existed already for years. However, AOP comes with the idea
to use join point interception, for separation of cross-cutting concerns and claims itself to be a generally
applicable technique. Also, interception in AOP is connected with powerful query-macro-like language.
We take a look at refinement of the notion of AOP in the section called “AOP – Filman, Friedman (Y.
2000)”.

Software-engineering notion of aspects is in the focus of aspect oriented software development (AOSD)
discipline. AOSD investigates, how awareness of multidimensionality and notion of crosscutting concerns
should be incorporated in the software development from its early phase to the very end. AOSD has no
special treatment in this work.

AOP – Filman, Friedman (Y. 2000)


Notion of AOP has been evolving since 1997 and it has been evolving ever since. The quest for definition
of AOP still lasts.

5
Aspect-Oriented Programming

The most influential definition of AOP was given by [ Filman, Friedman 2000 ]. Authors claim that an
AOP system must bear two properties: quantification and obliviousness.

Definition (Filman, Friedman). “ AOP can be understood as the desire to make quantified statements
about the behavior of programs, and to have these quantifications hold over programs written by oblivious
programmers.”

Definition (Filman, Friedman). “ Quantification is statement of the form: In programs P, whenever


condition C arises, perform action A , over conventionally coded programs P.”

In relation to P, C and A we ask:

• What kinds of conditions C can we specify.

• How do actions A interact with base program and each other.

• How the system will allow actions A interact with program P.

Attempt for a Definition. An oblivious programmer is a programmer, “who doesn't have to expend
any additional effort to make the AOP mechanism work. He doesn't have to be aware, that aspects will be
applied to it.”

This twofold definition – particularly expressions “additional effort” and “to be aware” – was corrected
in [ Filman 2001 ]:

Definition (Filman). “ Obliviousness states that you can’t tell that the aspect code will execute by ex-
amining the body of the base code.”

Explanation. “will execute” – I suppose this means, that you are not able to say, that the condition will
fire. “by examining the body of the base code” – there is no sign of binding of an aspect in the body. So,
AOP is all about what we could call an “oblivious quantification”, as mentioned in the paper, but usually
both characteristic properties (quantification and obliviousness) are kept separate.

Further, [Filman, Friedman 2000] give bunch of other useful definitions.

Definition (Filman, Friedman). Static quantification is quantification about program as a text.

Definition (Filman, Friedman). Dynamic quantification tightens aspects to something that happens
only at run-time.

Examples of dynamic quantification include “raising of an exception”, or “The call of subprogram X


within a temporal scope of a call of Y” – e.g. not refreshing display after single move of a particular object,
which is part of a whole collections of objects being moved, “Patterns on the history of the program” –
e.g. three times unsuccessful login attempt.

AOP Systems that quantify over the public interface of a program, like functions are Black-box AOP Systems
( composition-filters 1) and conversely systems, that quantify over the syntax tree are White-box AOP
Systems (AspectJ).

Summary
Can we be satisfied with the definition? [Filman, Friedman 2000] give their explanation, whether some
real systems should be classified as AOP-Systems, also expressing this provocative statement: “Rule-based

1
see [ Aksit M. and Bedir Tekinerdogan, B. Solving the modeling problems of object-oriented languages by composing multiple aspects using
composition filters. AOP'98 workshop position paper, 1998.]

6
Aspect-Oriented Programming

systems like OPS-5 or, to a lesser extent, Prolog are programming with purely dynamically quantified
statements. Each rule says, whenever the condition is true, do the corresponding action. If we all programmed
with rules, we wouldn’t have AOP discussions. ”

Pure Prolog is not an AOP-System. Let's have a look at a small Pure Prolog example – Money transfer:
possibletransaction(who, ammount, accountfrom , accountto):- draw(am-
mount, accountfrom, accountto). , where possibletransaction is one of possible many imple-
mentations in the system. Local imlpementation of the primitive security concern, looks like: possib-
letransaction(who, ammount, accountfrom , accountto):- loggedin(who),
draw(ammount, accountfrom, accountto). Since we want to implement the login aspect,
we want to check for loggedin(who) whenever (before) we draw an account. Because there may be
some other possibletransactions, we want loggedin(who) to be ENCAPSULATED in
draw(..! To do this in Prolog, we have to RENAME (see the section called “The Expression Problem
– P. Wadler (Y. 1998)”) the original draw and implement a new draw as we did with possibletrans-
action. Login concern is exactly in the form of quantification – “In programs P, whenever condition C
arises, perform action A ”. The problem here is, that Pure Prolog's expressivity is limited to first-order
logic and quantification about program P is of “higher-order” than program P.

Java 5 adds annotations (metadata facility) and AspectJ 5 allows quantification over annotations. This
raises a question if such quantification is oblivious. Annotations can be considered an alternative naming
and some annotations can serve not only to bind aspects. I leave it upon reader.

Summary
We have seen two most influential characterizations of AOP. Cross-cutting is more like a software-engin-
eering perspective (although it isn't quite). AOP is supposed to deal with tangling and scattering. While,
quantification and obliviousness are concrete principles (maybe to concrete). Notion of quantification and
obliviousness showed useful from the perspective of programming languages. This definition doesn't have
any notion of cross-cutting concern and it basically describes what is otherwise called join point interception
(known as hooking mechanisms from operating systems). Surprisingly, since then, it seems nobody has
came up with better definition or similarly pragmatic definition of AOP.

7
Chapter 3. AspectJ – Basic Constructs
AspectJ in One Sentence. AspectJ is a general purpose aspect-oriented language for Java. Another
One-sentence characteristic of AspectJ was given in [ Hannemann, Kiczales 2002 ]: “AspectJ is a seamless
aspect-oriented extension to Java, which means that programming in AspectJ is effectively programming
in Java plus aspects.”

Resources. This chapter explains AspectJ in accordance with [AspectJ Guide] . Moreover, some histor-
ical context is provided, so that reader can better understand the reasons. Here described version of AspectJ
is 1.2.x, if not otherwise stated. For information specific to AspectJ 5 see [AspectJ Notebook] .

Joinpoints
Definition. join point is a well-defined point in the execution of a program.

Most often, programmer needs to use two different joinpontis: method calls (call(..)) and method ex-
ecutions(execution(..)). The only difference between the two is, that the call captures context from
the outside of the method call, whereas execution from the inside of the methods' environment. Call is
useful when e.g. accessing methods of libraries, where execution would result in a compile-time error.

Joinpoints on fields are allowed, with exception to static fields, that are inlined by a compiler. Other useful
joinpoints include, e.g. constructor call and handler execution. For complete list of joinpoints, see [AspectJ
Guide]

Pointcuts
Definition. Pointcuts are a means of referring to collections of join points and certain values at those
join points. Pointcuts can arbitrarily expose these “certain values” (= data accessible in the execution
context of the joinpoints) to advice body. Data in the context of AspectJ means variables or objects.

Pointcuts combined with other pointcuts create a new pointcut. Set operators, denoted as their boolean
equivalents, as intersection (&&), union (||) and inversion (!) can be applied to pointcuts. Pointcuts them-
selves operate on joinpoints and pick up those – satysfying constraints.

Pointcuts appear in advice declaration – unnamed! Pointcuts can be declared also at the top level of the
aspect or even in a class – named. This naming serves mainly for better inner modularity and for inheritance
(only from an abstract aspect to concrete one). Pointcut can be inherited as abstract (empty) or concrete
and can be overridden. Pointcut's maximal scope is protected. Although, declaring pointcut public is legal,
it is not possible to access top-level pointcut from another aspect in the same package.

Dynamic Crosscutting. Dynamic crosscutting, means dynamic quantification (see the section called
“AOP – Filman, Friedman (Y. 2000)”). This same thing is in AspectJ Guide called “dynamic joinpoint
model”. In AspectJ Guide one can read: “Each method call at runtime is a different join point, even if it
comes from the same [method] call expression in the program.” In [Kiczales et al. 2001], the same thing
is called “dynamic dispatch”: “The use of certain pointcut designators, like cflow, callsto, and instanceof[old
names], can require a run-time test to determine whether a particular corresponding method actually matches
a particular join point designator. In such cases, the corresponding method includes residual testing code
that guards the execution of the advice. This overhead is relatively small. ” The ability of dynamic cross-
cutting is crucial to the “universal” solution to s.c. “jumping aspect problem”, see the section called
“Jumping Aspect Problem – Brichau et. al. (Y. 2000)”.

In this example is a pointcut, that selects only non-static methods:

8
AspectJ – Basic Constructs

after(SomeClass c): execution(* *(..)) && target(c)


{System.out.println("not static method");}

target([Type]) designator selects an instance, method of which has been called. This instance must
have type that is the subtype of [Type]. Of course, static methods can't be selected with target, cause they
do not belong to any instance. In the same time, target exposes data to the advice. Not all pointcut
designators can in them bind names. Only target, this and args can. Names can also be used in
signatures.

Statically undeterminable pointcuts. [AspectJ Guide] gives list of pointcuts, that “pick out join points,
but they do so in a way that is statically determinable.”

List of statically undeterminable pointcuts in AspectJ


• cflow

• cflowbelow

• this

• target

• args

• if

Caveat, to this! Look at this example of the observer protocol (and do not get confused that it is a bit arti-
ficial, situation is quite normal!)

9
AspectJ – Basic Constructs

Example 3.1. Statically Undeterminable Pointcuts

public interface Shape {


public int getX();
public void setX(int x) ;
}

public class Point implements Shape{


private int x,y;

public int getX() {


return x;
}

public void setX(int x) {


this.x = x;
}

public Point(int x, int y) {


super();
setX(x);
this.y=y;
}
}

aspect ObserverProtocolImpl1 extends ObserverProtocol {

//this pointtcut selects only on subclasses of Point!


pointcut subject(int x):
execution(* Point+.set*(..)) && args(x) && !withincode(* Point+.set*(..));

declare parents : Shape+ implements Subject;

after(int x):subject(x){
System.out.println(x);
}
}

import java.util.Collection;
import java.util.LinkedList;

public class Application {

public static void main(String[] args){


//Subject
Point p = new Point(1,2);
RandomCollection l = new RandomLinkedList();
p.setX(5);// here applies advice and writes 5!
l.add(p);
l.addTenRandomShapes();l.shuffle();
Object o = l.iterator().next();
((Shape)o).setX(48);//this writes 48, but we could have

10
AspectJ – Basic Constructs

//hardly known statically this o casts to Point –


//and that's the Point
((Point)o).setX(92);//this writes 92, of course
}
}

Although, type of o is statically undeterminable, advice defined with execution pointcut applies to it as it
was of type Point, but Shape is just a supertype of Point. This behavior is eventually no surprise – late-
binding is one of the main characteristics of OO. Now the question is, what does it mean – statically
(un)determinable pointcuts? A resolution to this mystery is probably hidden in the fact, that execution(My-
Type.methodName) is equivalent to execution(methodName) && this(MyType) for the
non-static methods. Now it seems clear, unfortunately [AspectJ Guide] didn't help us much.

Advice
Definition. Advice are method-like constructs used to define additional behavior at joinpoints.

Advice defines code that will execute and where. Its declaration is the only place, where Joinpoints can
be combined with pointcuts and advice designator (this is my own term, I suppose). Advice designators
are before or after or around. Advice designator state, how advice will apply at each point. Advice imlpe-
mentation must follow in an advice body. This tight coupling of declared pointcut with advice implement-
ation received a lot of critique in an AOP community. See Chapter 6, CaesarJ.

The important question, one can ask here, is whether “declared pointcut” can apply (if so declared) to as-
pects? For beginners, answer, that follows, is a bit surprising. Yes, it does! Advice can apply to itself, as
well as to other advice! One would not anticipate this, because AspectJ advice – from the viewpoint of
Java – is a “second-class” language construct.

Let's have a look at this example from The AspectJ Guide 1, that shows how easy it is, to “fall into a loop”
with AspectJ.

aspect A {
before(): call(* *(..)) { System.out.println("before"); }
after(): call(* *(..)) { System.out.println("after"); }
}

Would program with this aspect applied ever finish? It would not. It would, even, not throw an exception.
This is so, because these advice apply to each other, as well as each one to itself, as we already know.
Solution to this kind of problem is a big issue in AOP languages. Similar cascading effects can arise under
less obvious circumstances. See the section called “Jumping Aspect Problem – Brichau et. al. (Y. 2000)”.
Moreover, exactly using one advice from this example, suffices to demonstrate the same consequences.

Aspects
Definition. Aspects are units of modular crosscutting implementation, composed of pointcuts, advice,
inter-type declarations and ordinary Java member declarations.

Advice is not the only place, where from changes to a regular Java code can be applied. Additional members
can be declared on types, see the section called “Inter-Type Declarations and Per-Clause”. Also interface,

1
sadly, authors put this in the pitfalls section

11
AspectJ – Basic Constructs

constructor and the super-type of the type, can be redefined in AspectJ Aspects (under constraint, that the
parent of the class being introduced must be an ancestor of the introducing class).

Aspects are instantiated in a way different from pure Java classes. Aspect declaration may include a type
of its instantiation. These instantiation criteria (issingleton, perthis, pertarget, percflow, percflowbelow)
take pointcut as an argument and because they cut down the set of aspects, they also cut down the set I
called previously “adviced pointcut”. So, places – one has to look at, to find out what is the definitive set
of pointcuts – are a bit scattered throughout an aspect declaration.

Summary
Now, we can put more precisely the quotation from the begining of the chapter (“AspectJ is effectively
Java + Aspects”).

Bird's View of AspectJ 5 Grammar (Warning: this is not exactly BNF!)


• AspectJ := Class+ Aspect+

• Aspect := Modifier* 'abstract'? 'aspect' Name PerClause* '{' JavaMemeber* InterTypeDeclaration*


PointcutDec* Advice* '}'

• PointcutDec :=Modifier* 'pointcut' Name '(' ParamList? ')' ':' PointcutExpression

• Advice := Modifier* (before|after|around) '(' ParamList? ')' ':' PointcutExpression '{' AdviceBody '}'

• AdviceBody := JavaMethodBody MembersProvidedByAspectJ*

• PerClause := (('pertarget'| 'perthis' | 'percflowbelow' | 'percflow') '(' PointcutExpression ')') | 'pertype-


within' '(' TypePattern ')'

• PointcutExpression := (PointcutPrimitive | ReferencePointcut) | '!' PointcutExpression | '(' PointcutEx-


pression ')' | PointcutExpression '&&' PointcutExpression | PointcutExpression '||' PointcutExpression

A Part of the “official” AspectJ 5 grammar can be found at http://www.eclipse.org/as-


pectj/doc/next/adk15notebook/grammar.html

I've got few remarks to AspectJ Guide. Some rules can be found only in unexpected places, e.g. the fact,
that Advice can apply to itself. This rule is best described in pitfalls section with two advice – thus blurring
the point. Fine grained constructs of the language have no names , thus explaining things can get clumsy,
e.g. advice designators (I mean – before, after, around) are called just “advice”. There is no word for sets
of joinpoints, instead one reads “pointcuts pick up joinpoints”.

12
Chapter 4. Modular Reasoning in the
Presence of AOP
Definition of Terms – Kiczales, Mezini (Y. 2005)
Definition. Module is [ Wikipedia [http://en.wikipedia.org/wiki/Module] ]

• self-contained component of a system,

• which has a well-defined interface to the other components.

This definition is somewhat abstract, but it doesn't claim module to be a piece of functionality – that would
be a mistake. It shows more efficient to define modularity of code.

Definition. [ Kiczales, Mezini 2005 ] Code that implements a concern is modular if

• it is textually local

• there is a well-defined interface, that describes how it interacts with the rest of the system

• the interface is an abstraction of the implementation, in that it is possible to make material changes to
the implementation without violating the interface,

• an automatic mechanism enforces that every module satisfies its own interface and respects the interface
of all other modules, and

• the module can be automatically composed in various configurations with other modules to produce a
complete system.

Definition. “ Modular reasoning means being able to make decisions about a module while looking
only at its implementation, its interface and the interfaces of modules referenced in its implementation or
interface. ”

Definition. “ Expanded modular reasoning means also consulting the implementations of referenced
modules. ”

Definition. “ Global reasoning means having to examine all the modules in the system or sub- system.”

What's Wrong with Traditional Modularity Meas-


ures
Coupling
Modularizing tangling causes higher coupling. There's no doubt about it, when talking about only one
module. So, what about modularizing scattering? To explain this, we rather take a closer look at some
definitions (because all are very complicated) from [Yourdon, Constantine 1979].

“The key question is: How much of one module must be known in order to understand another module?
... The fact that we must know something about another module is a priori evidence of some degree of in-
terconnection even if THE FORM OF THE INTERCONNECTION IS NOT KNOWN. ” According to

13
Modular Reasoning in the Presence of
AOP

this, scattering can be NOT KNOWN FORM OF INTERCONNECTION, because scattering can manifest
itself in the presence of change so that one has to repeat the change simultaneously in multiple modules.
But, in general, to understand a module, one doesn't have to understand another because of the same scat-
tering (e.g. logging).

“Obviously, WHAT WE ARE STRIVING FOR IS LOOSELY COUPLED SYSTEMS – that is, systems
in which one can study (or debug, or MAINTAIN) any one module without HAVING TO KNOW very
much about any other modules in the system. ” Seems, tangling was not considered an issue in those times!

“Coupling as an abstract concept – the degree of interdependence between modules – may be operationalized
as the probability that in coding, debugging, or modifying one module, a programmer WILL HAVE TO
TAKE INTO ACCOUNT something about another module. ” Scattering is not form of coupling, in general.
Both terms, as they are, do not have anything in common.

Cohesion
Notion of cohesion is bound to “[functional] relatedness” [Yourdon, Constantine 1979] of internal elements
to one another, in one module in isolation.

In [Yourdon, Constantine 1979] distinguish 7 levels of cohesion:

• coincidental association

• logical association

• temporal association

• procedural association

• communicational association

• sequential association

• functional association

These levels are listed in order of increasing strength of COHESION. In other words – each level's rank
in this list is measured by its “functional relatedness”.

We can see that the term cohesion is aimed towards functional decomposition! This scale does not account
on different functional decompositions with different levels of “functional relatedness”.

Approaches to Modular Reasoning – Aldrich (Y.


2004), Kiczales, Mezini (Y. 2005)
Notion of crosscutting has turned the philosophy of Structured development (SD) upside-down. Conven-
tional modularity based on functional interfaces was also one of the implicit assumptions of SD: “...con-
ventional modularity and encapsulation mechanisms are not flexible enough to capture many concerns that
are likely to change.” [ Kiczales et al. 1997 ]

“Prior to AOP modules had a "black-box" property – the interface of a module was defined in a single
place, either part of the module or directly referred to by the module. ” [ Kiczales, Mezini 2005 ]

So, the question is: “Does AOP necessarily break modular reasoning?”

14
Modular Reasoning in the Presence of
AOP

[ Aldrich 2004 ] devoted himself to an important issue of separate (non-local, distributed) module develop-
ment. Aldrich asked himself a question: “How can developers specify an interface for a library or component
that permits as many uses of advice as possible, while still allowing the component to be changed in
meaningful ways without affecting clients ... while still ensuring correctness properties of the component
implementation? ”

Aldrich designed a small AOP-aware module system “Open Modules”: “Open Modules are open in two
respects. First, their interfaces are open to advice; all calls to interface functions from outside the module
can be advised by clients. Second, clients can advise exported pointcuts. ”

Open Modules describes a module system that:

• allows external aspects to advise external calls to functions in the interface of a module

• allows external aspects to advise pointcuts in the interface of a module

• does not allow external aspects to advise calls from within a module to other functions within the
module (including exported functions).

“Abstraction ensures that clients can not affect or depend on the internal implementation details of a
module. As a result, programmers can both separate concerns in their code and reason about those concerns
separately. ”

Open Modules also places significant limitations on advice. Aldrich notes, that: “...in practice, some ap-
plications may only be able to reuse a library or component if they can get around these prohibitions. We
think this should be an option for developers, but it should be a conscious choice,... ”

[ Kiczales, Mezini 2005 ] propose a modul system, that PRESERVES modular reasoning in the presence
of the full power of static AOP. But whole-system assembly is needed in the first step – then modular
reasoning is possible. “..these authors [icl. Aldrich] have generally sought to restrict the power of AOP in
order to preserve existing black-box reasoning mechanisms. In contrast, our goal is to show that the full
power of AOP [its static part] is compatible with modular reasoning, if we are willing to change some of
our existing reasoning mechanisms. With aspect-aware interfaces we require a global analysis of the de-
ployment configuration to determine module interfaces. But once that is done, modular reasoning is possible..

To make pointcut interface work, one has to add a short description of advice to the advised method de-
scription on the module interface:

void setX(int) : UpdateSignaling – after returning UpdateSignaling.move();

: UpdateSignaling – after returning UpdateSignaling.move() denotes:

• UpdateSignaling aspect has after returning advice that affects execution of the method

• the pointcut, advice refers to, is move(), also defined in UpdateSignaling.

Summary
Accordingly to [Kiczales, Mezini 2005]:

15
Modular Reasoning in the Presence of
AOP

Advantages in modular reasoning with AOP


• Modular reasoning is possible, although global configuration is nesessary precondition.

• Programmers get modular reasoning benefits for crosscutting concerns whereas without AOP they do
not.

• Limits on advice as stated above.

Disadvantages in modular reasoning with AOP


• Modular reasoning with AOP requires a change in that, how module interfaces are specified.

• Complete system configuration is needed to fully determinate modul interfaces. As noted by authors:
“While this may seem anti-modular, it is an inherent property of crosscutting concerns.”

• Need for tool support to automatically compose interfaces with aspects.

I here people yelling: “AOP breaks encapsulation!” Yes it does. Breakage into encapsulation with AOP –
DONE RIGHT – is the consequence of “inherent” complexity of the problem itself. According to a principle
of information hiding [ Parnas 1972 ]: “Developers should break a system into modules in order to hide
information that is LIKELY to change.” So nobody knows sure answer to the question – “How should the
software be organized into modules?”.

See [Date 1998] for discussion of encapsulation, from the databases field.

Evolution of systems brings another issue specific to AOP that was impossible with convetional modularity,
see the section called “The Jumping Aspect Problem and Vanishing Aspects”.

AOP development environments, e.g. AJDT plugin for Eclipse, rely on global configuration (compilation).
AJDT provides a developer with analogy of pointcut interfaces and keeps programmer “in the picture”
while coding. However, only statically determinable application of aspects is displayed to developer. In
OOP, polymorphism makes many pointcut expressions dynamic, see Example 3.1, “Statically Undetermin-
able Pointcuts”. Displaying also possibility that an aspect will apply might be useful.

16
Chapter 5. AspectJ – Advanced
Constructs
Aspect Inheritance in AspectJ
An aspect can inherit from class or an abstract aspect. An aspect can implement interfaces, except for
java.io.Serializable and java.lang.Cloneable. Inheriting aspect can override parrent's
instantiation model (see the section called “Per-Clause”), e.g. from perthis() to issingleton().

Pointcuts and Java-members can be inherited as with regular Java classes. Advice has no name in AspectJ
and can not be inherited. Pointcuts can be declared abstract, without any expression, also protected, public,
private and can also be declared in regular java classes. Pointcuts can be overriden.

The Jumping Aspect Problem and Vanishing


Aspects
Vanishing Aspects – Constanza (Y. 2000)
Constanza [ Constanza 2000 ] calls aspects with unintended behavior in the presence of change vanishing
aspects – i.e. aspects that bind on methods, implementation of which is mutually dependent, in the sense
that at least one method calls the other. He proposes solution based on separation of inner implementations
of mutually dependent methods. Illustration on counting-bytes-written aspect follows.

public class OutputStream {


public void write(byte b) {...}
public void write(byte[] b) f
for (int i = 0; i < b.length; i++) write(b[i]);
}

Constanza argues that either the implementation of write(byte b) can change in terms of write(byte[] b) or
implementation of both writes can change (e.g. more efficient implementation with use of methods Super-
writer.write(byte b) and Superwriter.writebytes(byte b)). His solution resides in class OneOutputStream.

public class OneOutputStream extends OutputStream {


// internal implementation
private void internalWrite(byte b) {...}
private void internalWrite(byte[] b) {
for (int i = 0; i < b.length; i++) internalWrite(b[i]);
}
private void internalWrite(byte[] b) {...}
// external representation
public void write(byte b){ internalWrite(b); }
public void write(byte[] b){ internalWrite(b); }
}

17
AspectJ – Advanced Constructs

Constanza claims, that his proposal also solves the problem of jumping aspect. Mutual methods from
separate classes have to be implemented in terms of internal-implementation interfaces.

This solution has got some quirks. Additional requirements on interfaces break the principle of obliviousness
and takes too much from interface flexibility. At least, the idea that there are more “degrees of freedom”
to class interfaces is alright.

Jumping Aspect Problem – Brichau et. al. (Y. 2000)


Coding in AspectJ can be even tricky – see the section called “Advice” [11]. Problems arise, when advice
is being applied to advice (particularly to itself). Implementers must not have an explicit information about
the advice applied in the code to their disposal. Advice applies to code, that has yet not been written. In
the presence of dynamic AOP application of advice can not be decided at compile time, see Statically un-
determinable pointcuts. And we can not forget about ubiquitous evolution of programs, see the section
called “The Expression Problem – P. Wadler (Y. 1998)”.

Definition. “When aspects apply on methods, we have just added, in an unintended way, we talk about
a problem of jumping aspect. ” [ Brichau et. al. 2000 ]

Example 5.1. Jumping Aspect Problem

interface Shape {
public void moveBy(int dx, int dy);
}
class Point implements Shape {
private int x, y;
public Point(int x, int y) {
this.x=x;this.y=y;
}
public int getX() { return x; }
public int getY() { return y; }
public void setX(int x) { this.x = x; }
public void setY(int y) { this.y = y; }
public void moveBy(int dx, int dy) {
setX(x+dx);
setY(y+dy);
}
}
public aspect UpdateSignaling {
public pointcut change():
execution(void Point.setX(int)) || execution(void Point.setY(int))
|| execution(void moveBy(int,int)); //added after creating moveBy(int,int)
after() : change() { Display.update(); }
}
public class Application {
public static void main(String[] args) {
Point p = new Point(1,2);
p.setX(5); //advised by UpdateSignaling 1 time
p.moveBy(4,6); //advised by UpdateSignaling 3 times!
}
}

18
AspectJ – Advanced Constructs

What happens in the example, is a classical example of jumping aspect problem as it was presented in [
Kiczales, Mezini 2005 ]. After adding a new method moveBy(int, int) a programmer adds || execu-
tion(void moveBy(int,int)) to existing pointcut, not realizing that now after a point was moved,
display would get updated 3 times in a row, causing an unintended behavior.

Wise-compositor-based solution to the jumping aspect problem. [ Brichau et. al. 2000 ] describe
their approach to the solution, that is actually a description of mechanism used in AspectJ: “Static join
points, such as method names, can not themselves always specify the location at which aspects or concerns
are to be composed. For context-sensitive compositions (jumping aspects), it is necessary to specify join
points and the (possibly dynamic) context in which the composition should occur, and to provide any as-
sociated declarative, compositor, and run-time support needed to enable compositions to be affected by
context-sensitive conditions. ”

Solution to the jumping aspect problem in AspectJ. [ Kiczales, Mezini 2005 ] argue that resolution
to the jumping aspect problem in AspectJ is simple and can be realized using cflowbelow primitive
pointcut, excluding possible hierarchy of aspect bindings. cflowbelow(Pointcut) picks out the join
points below the control flow of the join points picked out by Pointcut. Assuming, programmer has realized
possibility of an unintended hierarchical composition, is encouraged to use following code in advice de-
claration:

after() : change()
&& !cflowbelow(change()) { Display.update();}

Summary
Apparently, there is no other solution to the Jumping Aspect Problem. Although, cflowbelow is a realization
of “wise compositors” idea, there are limitations of pure AspectJ pointcut policy, that make solution of
Jumping Aspect Problem impossible without rewriting existing code. So there is no further future for
compositors idea in ApsectJ.

Yet to the example above – the fact, that there will come another methods as moveBy(int,int) can be a
separate concern. Saying that the solution above is really a solution goes against AOP owns principles, as
obliviousness – which must also apply to AOP extensions themselves. Jumping Aspects Problem is just a
model of a situation, that can happen in a larger scope, where modification of existing code is simply un-
desirable. Jumping Aspect Problem is kind of Expression Problem, see the section called “The Expression
Problem – P. Wadler (Y. 1998)”.

Pointcut designator cflowbelow(Pointcut) is an example of s.c. control-flow pointcut designators


(PD). It's dynamic and requires some runtime checks (to apply or not). Alternatively one can opt for a
static solution (but excludes less cases), using within(TypePattern) PD, which picks out each join
point where the code executing is defined in the declaration of one of the types in TypePattern. PD
within is an example of text-based PD. Usage of both designators belongs to a “good practice” because
programmer should try immediately exclude as much potential disruptive jumping-scenarios as he can
(before is too late, or modifying code would be necessary) – both these PDs belong amongst the strongest
weapons of AOP.

GoF Design Patterns and SOP – Vlissides (Y.


1998)
This section is only intended as introduction to design patterns and is not standalone and can be skipped.
It should also emphasize similarities between AOP and SOP.

19
AspectJ – Advanced Constructs

The book [GoF 1994], described by its authors as: “.. a book of design patterns that describes simple and
elegant solutions to specific problems in object-oriented software design ”, finds its way to almost any
writing about OOP. It's not different with this work 1.

At http://researchweb.watson.ibm.com/sop/sopcpats.htm 2 can be found description of some of the problems


with design patterns. John Vlissides – one of the GoF authors – wrote an article [Vlissides 1998], in which
he describes how SOP can solve some of this problems. SOP composition is similar to AOP, however
there are no special entities like aspects. He shows how a class can be “advised”, without changing its
code. Interestingly, he is not interested in separation of concerns, he highlights the fact, that after compos-
ition is everything in one file. There is nothing bad about it.

Very absurd seems fact, that the same thing could be solved through inheritance, but he would have to
change one name in the “advised” class, which he wants to avoid. On the other hand this absurdity makes
clear, what have both approaches (AOP and SOP) in common. Compare with Prolog example in the section
called “AOP – Filman, Friedman (Y. 2000)”.

GoF Design Patterns and AOP – Hannemann,


Kiczales (Y. 2002)
In 2002 [ Hannemann, Kiczales 2002 ] published a comparative study of all 23 GoF design patterns with
a clear conclusion: “Our results show that using AspectJ improves the implementation of many GoF pat-
terns.” Their result is, among others, significant from the perspective of modularity. With no surprise, they
observed, that patterns with the best improvement are ones with structure involving crosscutting of some
form - one object playing multiple roles or many objects playing one role.

Patterns in numbers. Hannemann and Kiczales achieved better modularity of patterns implementation.
The group of 17 patterns they modularized in the way that they removed code-level dependencies from
the participant classes to the implementation of the pattern. For the group of 12 of the patterns their imple-
mentation enables the core part of the pattern to be abstracted in a form of reusable code. 14 patterns im-
plementation allows one participant to participate in multiple patterns.

Some implementations change the structure of participants, some do not. The improvements of the AspectJ
implementation of the GoF patterns can be divided in two groups – general improvements and specific
improvements. General improvements result from better modularity of AOP code, whereas specific im-
provements result from additional possibilities of aop – beyond inheritance – which can be also implement-
ation specific.

General improvements of “AspectJ-ed” GoF-patterns [Hannemann, Kiczales 2002]


Locality The part of code common to more participants is placed in an ab-
stract aspect of the pattern. The participant classes are free of any
tangling code. Therefore potential changes can be made all in one
place - abstract aspect res. participant-class-specific aspects (concrete
aspect).

1
I have bad memories from when reading this book. It's text is so convoluted. It lacks definitions and descriptions of a single design pattern follows
in a sequence of statements contradicting previous ones and it's not clear, what is definitional for a particular pattern until one reads how it differs
from the others at the end of the pattern's description. Thus one has to know, what the other patterns mean. Once you read all patterns descriptions
from the whole group, everything makes sense. Then APIs of somebody who respcts the names of the patterns reads as a breeze.
2
There is a mistake in the article. In the second example, Display should be initialized as a Decorator, not as an Adapter.

20
AspectJ – Advanced Constructs

Reusability The core pattern code is placed in the abstract aspect. The abstract
aspect is reusable. Implementation needs concrete aspect per each
abstract one in the pattern.

Dependency inversion Pattern's implementation code depends on participants; not vice


versa. 3.

Composition transparency If some of the participants take part in multiple instances of the same
pattern or in some other pattern, code is kept clear. And implementor
of the other pattern can benefit from the obliviousness of previous
aspects applied in the sense that he can reason about his aspect inde-
pendently.

(Un)pluggability It is possible to switch between using a pattern (aspect) and not using
it in the system 4.

Observer Pattern Implementation in AspectJ – Hannemann,


Kiczales
The implementers of this pattern (see Example 5.2, “ObserverProtocol, General Part in AspectJ – Han-
nemann, Kiczales”) have got several possibilities. Hence, they have to make some decisions. The criterion
upon that they chose a particular implementation was to achieve as much general usage of the pattern, as
possible. [Hannemann, Kiczales 2002] split an implementation of the Observer pattern up to two parts:
the first (abstract aspect) – is part common to all instantiations of the pattern, the second (aspect binding)
– is specific to a particular instantiation. The same technique works with other patterns, too.

3
See related and in Java community more hyped term inversion of control.
4
Obliviousness does not imply unpluggability. However, AOP terminology knows term of orthogonality. We say that an Aspect A is orthogonal to
the system if after adding an aspect to the system, system doesn't change its behavior and after removing it from the system, system doesn't change
its behavior. Similarly, orthogonality can be defined for a class. See [ Colyer et al. 2004 ] for orthogonality definition. BTW., here, one can find an
alarming example of non-orthogonality of Java Serialization mechanism.

21
AspectJ – Advanced Constructs

Example 5.2. ObserverProtocol, General Part in AspectJ – Hannemann, Kiczales

import java.util.WeakHashMap;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;

public abstract aspect ObserverProtocol {


protected interface Subject { }
protected interface Observer { }
private WeakHashMap perSubjectObservers;

protected List getObservers(Subject subject) {


if (perSubjectObservers == null) {
perSubjectObservers = new WeakHashMap();
}
List observers = (List)perSubjectObservers.get(subject);
if ( observers == null ) {
observers = new LinkedList();
perSubjectObservers.put(subject, observers);
}
return observers;
}
public void addObserver(Subject subject, Observer observer) {
getObservers(subject).add(observer);
}
public void removeObserver(Subject subject, Observer observer) {
getObservers(subject).remove(observer);
}

protected abstract pointcut subjectChange(Subject s);

after(Subject subject): subjectChange(subject) {


Iterator iter = getObservers(subject).iterator();
while ( iter.hasNext() ) {
updateObserver(subject, ((Observer)iter.next()));
}
}
protected abstract void updateObserver(Subject subject, Observer observer);
}
/**
* @author Jan Hannemann
* @author Gregor Kiczales
* @version 1.1, 02/13/04
*/

22
AspectJ – Advanced Constructs

Example 5.3. ObserverProtocol Binding in AspectJ – Hannemann, Kiczales

public aspect ColorObserver extends ObserverProtocol


declare parents: Point implements Subject;
declare parents: Line implements Subject;
declare parents: Screen implements Observer;

protected pointcut subjectChange(Subject s):


(call(void Point.setColor(Color)) ||
call(void Line.setColor(Color)) ) && target(s);

protected void updateObserver(Subject s, Observer o) {


((Screen)o).display("Color change.");
}
}
/**
* @author Jan Hannemann
* @author Gregor Kiczales
* @version 1.1, 02/13/04
*/

[Hannemann, Kiczales 2002], divide features of this implementation into tow groups, as stated before:

Parts, common to all potential instantiations


1. Subject and Observer roles

2. Maintenance of mapping from Subjects to Observers (i.e. methods getObservers, addObserver, remo-
veObserver).

3. Observer pattern characteristic logic (i.e. abstract method updateObserver).

Parts, specific to each instantiation of the pattern


1. Which classes can be Subjects and which can be Observers (i.e. marker interfaces, declared with declare
parents).

2. A set of changes of interest on the Subjects that trigger updates on the Observers (i.e. concrete pointcut).

3. The specific means of updating each kind of Observer when the update logic requires it (i.e. imple-
mentation of updateObserver method).

Highlights of this implementation. This implementation of the Observer pattern allows Subjects to
play Observer role in other Observer pattern instances.

Highlights of the AspectJ Implementation of Gof Design


Patterns
This section was taken entirely from [ Hannemann, Kiczales 2002 ] and is reduction of the original version.

23
AspectJ – Advanced Constructs

General Improvements
• Observer, Composite, Command, Mediator, Chain of Responsibility - these patterns introduce roles,
that need no client-accessible interface and are only used within the pattern.

• Singleton, Prototype, Memento, Iterator, Flyweight - these patterns formulate access policy to certain
objects. In AspectJ, these patterns implementations are reusable.

• Adapter, Decorator, Strategy, Visitor, Proxy - the Adapter and Visitor pattern can be realized by ex-
tending the interface of the Adaptee pattern.

• Abstract Factory, Factory Method, Template, Method, Builder, Bridge - in these patterns inheritance
addresses well enough structural needs of these patterns. In AspectJ, “small improvement” is possible
here – we can replace abstract classes, used in GoF implementation, with an inter-type declaration
[http://www.eclipse.org/aspectj/doc/released/progguide/starting-aspectj.html#inter-type-member-declarations].
This feature provides for a form of multiple inheritance and allows us to go around the fact, that multiple
inheritance in Java is not possible.

• State, Interpreter - GoF implementation requires tight coupling between participants. In AspectJ the
coupling can be modularized.

There is no improvement for Façade design pattern.

Specific improvements. Detailed discussion of additional possibilities resulting from AspectJ imple-
mentation is beyond the scope of this paper. Singleton, e.g. can be made an inherited feature. And no
modification of the class is required. For more detailed characteristics of patterns implementations, see
original [ Hannemann, Kiczales 2002 ].

Summary
Hannemann and Kiczales proved positive impact of AOP on design patterns implementations' modularity:
“the improvements manifest themselves as a set of properties related to modularity. ”

In the opinion of some authors Hannemann and Kiczales didn't address all, that should be addressed, [
Bardou, Hachani 2003 ] claim, that implementation “is not sufficient: aspect-orientation also needs to be
considered at the design level in the description of design patterns. We also discuss different issues relative
to the aspectization of object-oriented design patterns.”

[Mezini, Ostermann 2003] criticise AspectJ, for its limited abstraction abilities (see the section called
“Observer Pattern Implementation in AspectJ with Inter-type-member Declarations”) To overcome a whole
group of abstraction-related issues, they designed language CaesarJ, see Chapter 6, CaesarJ.

Inter-Type Declarations and Per-Clause


Definition. Inter-type-member declarations are declarations of members (methods, fields, constructors)
on types (type is a class or an aspect or even an interface!) located (these declarations) in aspects.

The purpose of such declarations is not only that they take place “from outside”, but they differ also in
rules on visibility and scope that apply to them (from now on, speaking only vaguely – about visibility,
instead mentioning both terms).

Other kind of inter-type declaration is e.g. declare parents, as we have seen in the binding of the
observer pattern – declare parents: Point implements Subject; has the same effect as
proper declaration in the declaration of the Point class.

24
AspectJ – Advanced Constructs

Custom Java modifiers are allowed with inter-type-member declarations, but their meaning is different.
They apply to aspects, where the declaration takes place, instead of to classes being introduced.

Scope of inter-type declarations. private modifier means that method is visible only from the de-
claring aspect. package (default) modifier means that method is visible from the types in the same
package and, of course, from the declaring aspect. public modifier has the same meaning as in regular
Java class and actually declaration has the same effect, as had been done in class, as normally. protected
modifier is not allowed with inter-type declarations. abstract modifier is allowed, with straightforward
meaning. static modifier is also allowed.

Observer Pattern Implementation in AspectJ with Inter-


type-member Declarations
We sometimes want to keep some information specific to the adviced object, e.g. caching aspect. “A simple
example would be an implementation where observers maintain a history of the observed state change,
e.g., when they need to react on sequences of events rather than on individual changes. ” [Mezini, Ostermann
2003]

The aspectual observer pattern implementation from Hannemann and Kiczales must hold a hashmap to
remember the relation between concrete subjects and observers. Such an approach requires to keep this
map at a one place (aspect is the most convenient for it). However, natural place, from the OOP view, to
keep pointers to observers is on the subject object. Hanneman's and Kiczales' implementation represents,
what Martin Fowler calls anemic domain model.

With object-oriented programming one can handle only few things well and mapping of the domain model
is one of them.

Since we want to place addobserver and removeObserver methods on Subject interface, we have
basically two possibilities. One AspectJ mechanism uses special instantiation of an aspect, s.c. per-clause
construct, see the section called “Per-Clause”. Second possibility utilizes inter-type declarations, using
both, inter-type-member declaration to declare addObserver and removeOserver methods on the
Subject interface and updateObserver on the Observer interface , as well as declare parents
construct to introduce these interfaces to particular types in the binding part of the aspect implementation
(binding remains the same, see Example 5.3, “ObserverProtocol Binding in AspectJ – Hannemann,
Kiczales”).

Now, I am going to show that there is only one viable way, how to implement ObserverProtocol avoiding
anemic domain model, provided we do not use per-clause. First, the implementation.

25
AspectJ – Advanced Constructs

Example 5.4. ObserverProtocol with Inter-type-member Ddeclarations

package test.observer3;

import java.util.LinkedList;
import java.util.List;

public abstract aspect ObserverProtocol2 {

public interface Subject{};


public interface Observer{};

private List Subject.observers = new LinkedList();


List Subject.getObservers() {
return observers;
};

public void Subject.addObserver(Observer o) {


observers.add(o);
};

public void Subject.removeObserver(Observer o){


observers.remove(o);
};

void Subject.notifyObservers(){
for (Object obj :getObservers()){
((Observer)obj).update(this);
}
}

protected abstract pointcut subjectChange(Subject s);


}

26
AspectJ – Advanced Constructs

Example 5.5. ObserverProtocol Binding with Inter-type-member Declarations

package test.observer32;

import test.observer3.ObserverProtocol2;

aspect ObserverProtocolImpl2 extends ObserverProtocol2 {

declare parents : Shape+ implements Subject;


declare parents : Display+ implements Observer;

public void Display.update(Subject s){


System.out.println(((Point)s).getX()+" "+((Point)s).getY());
}

protected pointcut subjectChange(Subject s):


execution(void Subject+.set*(..)) && args(int) && target(s)
&& !withincode(* Subject+.set*(..));

after(Subject s):subjectChange(s){
s.notifyObservers();
}
}

public void Subject.addObserver(Observer o) is an example of inter-type-member de-


claration on the interface. The code in the body of the method declaration is equivalent as if declared on
type plus also static members on the declaring aspect are here visible.

Why interfaces Subject and Observer are declared in an aspect. If they could be declared protected
this would be the only place, however current compiler (within AJDT 1.5.0) requires them to be declared
as public.

Why have inter-type-member declarations public visibility. Binding part of an aspect belongs to a
package, where binded classes are visible, hence it will be in a different package. As we have seen above,
default visibility of inter-type-declaration is a package of declaring aspect, thus this package can be con-
sidered as a view on the classes being introduced. If we require also Subject and Observer interfaces to
have package visibility (to simulate view in a perfect way), we would have to declare them also in this
package. Not only marker interfaces must be public. The package, representing a view, must also contain
declarations of all the view-specific members (with package visibility). Because, Java doesn't support
multiple inheritance, it is impossible to implement a view in a single class.

Highlights of this implementation


• Avoids anemic domain model.

Drawbacks of this implementation


• Playing the same roles in different pattern instantiations is not possible, causing to coincide multiple
methods with public visibility on the type being introduced.

27
AspectJ – Advanced Constructs

Conclusion. Programming in a subject-oriented style (using views) is not possible under usual Java
packaging scheme, provided we do not use per-clause.

Per-Clause
Per-clause is AspectJ construct allowing specific instantiation of the aspects. By default there is one
instance per aspect. Stated explicitly, declaration looks like: aspect AspectName issingleton()
{ ... }.

Other types of per-clause allow aspects to be instantiated at objects belonging to certain pointcuts, namely

Non-default types of per-clause


• pertarget([Pointcut]),

• perthis([Pointcut]),

• pertypewithin([Pointcut])(from AspectJ 5 on),

• percflowbelow([Pointcut]),

• percflow([Pointcut]) clauses in AspectJ.

E.g. aspect declared with perthis(Pointcut) will be instantiated for each particular instance of object
at this(Pointcut). Aspect instantiation is different from classes in several important details, see [AspectJ
Guide] for more information.

Observer Pattern Implementation in AspectJ with Per-


clause
How can we use per-clause to improve our implementation of the observer pattern? Well, per-clause doesn't
allow us improve our previous implementation based on inter-type-member declarations. However, we
can design our solution from the ground up with per-clause.

Views and Roles. Our interest throughout this paper is to allow objects to be treated with ease from
different perspectives. Roles, objects play in design patterns (subject or observer in observer pattern), are
kind of perspective. Larger scopes of perspective, not associated necessarily with sole object are called
views. Because these terms are not well defined I will sometimes use them vaguely. Implementation in
the presence of the concept of views allows one to keep concerns as separate as one can imagine (let's say
orthogonal) – in the case of observer design pattern – e.g. allowing one object play multiple roles in different
pattern instantiations, or allowing one swapping between views flexibly. However, I consider the most
important fact, that it could be also possible to get views simply plugged-in, allowing some kind of ad-hoc
polymorphism for at least a scope of block of code.

Within implementation in this section I try to make use of the special aspect instantiated per each subject
or observer role. This aspect represents an extra space that can be used to implement a particular view on
the object in an orthogonal way, i.e. we will not get those clashing method names on the interfaces of objects
associated with this views, as we got with inter-type member declarations. So we do kind of repairing of
our previous implementation while programmign it from the ground up. Of course, there will be some
trade-offs!

The first key is that we approach our extra per-this space from regular Java classes through a special class
(View) that we inject with proper methods (subject, observer) that expose particular aspects through inter-

28
AspectJ – Advanced Constructs

faces we need (Subject, Observer) 5. In this case, View class represents the view of observer design pattern
(of course, this View class should be instantiation specific – not hampering multiple instantiations).

The second key is that we can switch between the roles of our objects. Thus, we can write something like
ColorObserver.subject(p).addObserver(ColorObserver.observer(d));.

Take a look at the details.

5
At least, for my current AOP environment (AJDT 1.5.0), I can say that even static members on an aspect are not accessible from regular Java code
through their aspect type, which is simply not visible.

29
AspectJ – Advanced Constructs

Example 5.6. ObserverProtocol with Per-clause in AspectJ

package test.observer6;

public abstract aspect ObserverRole implements Observer


perthis(observer())
{
abstract protected pointcut observer();
public abstract void update(Subject s);
}

package test.observer6;

import java.util.LinkedList;
import java.util.List;

public abstract aspect SubjectRole<SR> implements Subject

perthis(subject())
{
protected abstract pointcut subjectChange(SR s);

protected abstract pointcut subject();

private List<Observer> observers = new LinkedList<Observer>();

protected List<Observer> getObservers() {


return observers;
};

public void addObserver(Observer o) {


observers.add(o);
};

public void removeObserver(Observer o){


observers.remove(o);
};

protected abstract void notifyObservers(SR s);


//body of this method can not be implemented here, because it needs
//aspectOf() which can not be used in an abstract aspect
}

package test.observer6;
public abstract class ObserverProtocol {
}

package test.observer6;

public interface Observer {


public void update(Subject s);
}

30
AspectJ – Advanced Constructs

package test.observer6;

public interface Subject {


public void addObserver(Observer o);
public void removeObserver(Observer o);
}

31
AspectJ – Advanced Constructs

Example 5.7. ObserverProtocol Binding with Per-clause in AspectJ

package test.observer62;

import test.observer6.Observer;
import test.observer6.Subject;
import test.observer6.ObserverRole;

public aspect ObserverRoleImpl extends ObserverRole {


protected pointcut observer():
execution(Display+.new(..));

public void update(Subject s){


System.out.println("ObserverRoleImpl was updated.");
}

public static Observer ColorObserver.observer(Object obj){


if (hasAspect(obj)){
return (Observer)aspectOf(obj);
}
else {
//handling exception comes here
return null;
}
}
}

package test.observer62;

import test.observer6.Observer;
import test.observer6.SubjectRole;
import test.observer6.Subject;

public aspect SubjectRoleImpl extends SubjectRole<Shape>


perthis(subject())
{
protected pointcut subject():
execution(Shape+.new(..));

protected void notifyObservers(Shape s){


for (Object obs :SubjectRoleImpl.aspectOf(s).getObservers()){
((Observer)obs).update(SubjectRoleImpl.aspectOf(s));
}
}

protected pointcut subjectChange(Shape s):


execution(void Shape+.set*(..)) && args(int) && target(s);

after(Shape s):subjectChange(s){
notifyObservers(s);
}

32
AspectJ – Advanced Constructs

public static Subject ColorObserver.subject(Object obj){


if (hasAspect(obj)){
return (Subject)aspectOf(obj);
}
else {
//handling exceptional state comes here
System.out.println("ERORR: NULL POINTER in ObserverProtocolImpl2");
return null;
}
}
}
package test.observer62;

import test.observer6.ObserverProtocol;

public class ColorObserver extends ObserverProtocol{


}

package test.observer62;

public class Display {


}

package test.observer62;

public class Point implements Shape{


private int x,y;

public int getX() {


return x;
}

public void setX(int x) {


this.x = x;
}

public int getY() {


return y;
}

public void setY(int y) {


this.y = y;
}

public Point(int x, int y) {


this.x=x;
this.y=y;
}

package test.observer62;

public interface Shape {

33
AspectJ – Advanced Constructs

package test.observer62;

public class Application {

public static void main(String[] args){


Point p = new Point(1,2); //Subject
Display d = new Display(); //Observer
ColorObserver.subject(p).addObserver(ColorObserver.observer(d));
p.setX(5);
Display d2 = new Display();
ColorObserver.subject(p).addObserver(ColorObserver.observer(d2));
p.setX(3);
ColorObserver.subject(p).removeObserver(ColorObserver.observer(d2));
p.setX(4);
}
}

Note, the usage of aspectOf() method, which is provided within per-clause aspects, it can be used in
an implementation of advice and it is just different name for this (this of an aspect), because normal this
collides on inter-type declarations.

General issues regarding AspectJ I found during the implementation


• Nowhere in the tutorials of AspectJ can one read about how aspect types can bee accessed from regular
Java code.

• Aspects, even static members on them, can not be accessed from regular Java classes (POJOs) because
aspect types' scope doesn't involve POJOs (at least, when using AJDT 1.5.0). However, aspects can
be accessed when casted to a common Java interface. Making this casting possible involves a little
trick – programming these methods on aspects, while injecting them in regular Java class (View, in
this case).

• In AspectJ, per-clause in the declaration of an abstract aspect can be overridden in the concrete one.
Therefore, per-clause can not be decided in an abstract aspect. This was maybe the reason of the de-
signers decision that aspectOf() method can not be used in an abstract aspect.

Note on generics and AspectJ5. AspectJ Tutorial claims that aspects are parametrizable. We would
need pointcuts to be also parametrizable, e.g. in public abstract aspect ObserverRole
<OR> implements Observer perthis(observer()) {.. we want to be able to write pro-
tected pointcut observer():execution(OR+.new(..));. In AJDT 1.5.0, compiler doesn't
complain! In fact, pointcuts are NOT parametrizable (it doesn't work).

Issues concerning particularly per-clause implementation, and generics


• notifyObservers() can not be implemented in an abstract aspect due to the fact, it uses aspectOf()
method.

• Inter-type methods ColorObserver.subject(Object obj) and ColorObserver.observer(Object obj) can


not be declared on an abstract aspect due to the fact, they use sspectOf() method.

34
AspectJ – Advanced Constructs

• We want these methods to share parameteric type (in place of Object) with pointcuts. Even if we could
put these static methods on the an abstract aspect, we could not parametrize them (with generics) to-
gether with pointcuts (see above).

• If we want to parametrize these methods for a sole type from a collection of types (e.g. types that are
in the subject role), we could not do so with generics, because generics support only type intersection.
We would need to use marker interfaces instead.

Advantages of this implementation


• We have achieved total orthogonality of our implementation, we do not need even marker interfaces
to apply advice. (However, usage of marker interfaces makes things much easier.)

• No clashing methods on interfaces.

• We have implemented roles – something that can be considered a step towards views.

• We avoided anemic domain model of our domain, as well as of our aspects.

Disadvantages of this implementation


• No views – in the sense that objects could be treated polymorphically in some broader context.

• Objects in roles need to be casted.

• Unable to define reusable logic (which is the essence of this pattern) on an abstract aspect because as-
pectOf() is not reusable. This is a total failure.

• If not using marker interfaces, we are not able to enforce concrete implementation to be free of
typecasting errors.

Summary
With per-clause, implementing views in AspectJ is not possible. In this section, we were able to implement
roles (see informal definition above). However, approach demonstrated here suffers from many specific
technical constraints of AspectJ, mainly disallowed usage of aspectOf() method in abstract aspects – this,
in the end, breaks reusability of what we can call an essence of the observer pattern. Also, we had to use
some “tricks”.

35
Chapter 6. CaesarJ
Introduction
In this chapter we take a look at another AOP extension of Java, which should be actually considered not-
only extension. “CaesarJ is an aspect-oriented language with a strong support of reusability. It combines
aspect-oriented constructs, pointcut and advice, with advanced object-oriented modularization mechanisms.”
[ Aracic et. al. 2006 ] CaesarJ supports many concepts: virtual classes (kind of overridable classes), family
polymorphism (polymorphism of hierarchies) join point interception (AspectJ join point model), unification
of aspects and classes.

Deficiencies of AspectJ – Mezini, Ostermann (Y.


2003)
[ Mezini, Ostermann 2003 ] name drawbacks of an observer pattern implementation by Hannemann and
Kiczales (Example 5.2, “ObserverProtocol, General Part in AspectJ – Hannemann, Kiczales”). They
identify a whole pack of problems with AspectJ-based implementation:

Lack of support for multi-abstraction aspects - inner modularity. I have pointed out to this problem
with somewhat fancier name “anemic domain model”. Methods addObserver and removeObserver imple-
mented as top-level methods of the aspect constitute bad separation of concerns inside of the aspect itself
and create all the problems that imply from a non-modular code. Consider, you want to associate some
state with objects in the subject role. Where should you put the data ? Putting them into ObserverProtocol
aspect will after several more extensions like this clutter your code. This is just case of tangling. One of
the problems, AOP was invented to overcome!

Definition. System is called independently extensible, if it can cope with late addition of extensions
without requiring a global integrity check. [ C.Szyperski, Independently Extensible Systems - Software
Engineering Potential and Challenges, Proceedings of the 19th Australasian Computer Science Conference,
Melbourne, Australia, January 31 - February 2, 1996. ]

Lack of support for multi-abstraction aspects - independent extensibility. The problem with inde-
pendent extensibility shows up in case we need one object to play the same role in different instantiations
of the same pattern. This situation relates to inter-type-member declaration implementation in AspectJ.

Lack of Support for Sophisticated Mapping. declare parents construct takes TypePattern as
its argument. TypePattern allows basically two kinds of query – over a type or over a type and all its sub-
types. Per-clause – in gegneral – takes as an argument pointcut. However, even with all different types of
per-clause it is impossible to associate an instance of an aspect with a particular state. “Consider, for example,
an observer that is to be notified when the coordinates of points p1 and p2 are changed, reducing their
distance to less than some d. In this case, there is no direct mapping from the subject role to any application
class the subject role is represented by a pair of point objects. ” In AspectJ we choose a type of implement-
ation of an aspect that also determines its instantiation.

Lack of Support for Reusable Aspect Bindings. Once again, aspect binding is coupled to a particular
implementation. Yet, inheriting from a concrete aspect is not allowed. There is no reason to suppose, that
different implementation can not have the same binding or that the same binding can not fit to different
implementations. This is as natural as having multiple views of some arbitrary data. Abstract syntax tree
as data and groups of some specific task functions working on the tree nodes as an aspect is a classical
example (actually the Visitor pattern).

36
CaesarJ

Lack of Support for Aspectual Polymorphism. In CaesarJ it is possible to deploy aspects dynamically
and to deploy advice dynamically. We can say that advice is late-bound as we can say it about methods.
Static deployment is an option.

Aspect Collaboration Interfaces (ACIs)


Abstract part of the aspect in CaesarJ is defined in Aspect Collaboration Interface (ACI). ACI lays down
a bidirectional communication protocol between implementation and binding. Implementation and binding
are separate modules (see below) and all three parts constitute the whole aspect. ACI contains nested inter-
faces that represent independent modules. The main advantage of ACIs stems from their inheritance ability
– these are not ordinary Java interfaces. ACIs can be reused by overriding (see the section called “The
Expression Problem – P. Wadler (Y. 1998)”). Advice-method can be also declared on the nested interface.
Advice can thus be treated as an ordinary method! ACI may consist several nested ACIs, one for each ab-
straction of the modular structure of an aspect. Nested ACIs are “mutually recursive” in the sense that
name of each type can be used in the definition of the other. Let's take a look at the observer pattern.

Example 6.1. ObserverProtocol ACI

interface ObserverProtocol {
interface Subject {
provided void addObserver(Observer o);
provided void removeObserver(Observer o);
provided void changed();
expected String getState();
}
interface Observer { expected void notify(Subject s); }
}
/**
* @author Mezini, M.
* @author Ostermann, K.
* @version 03/2003
*/

Modifiers provided and expected are called facets. Facet provided means that an implementation
of this ACI must implement this method. Facet expected means that the implementation of provided
methods (of this ACI) can call expected methods that must be provided, where this interface is binded
– hence in the aspect binding.

Implementation of the ACI. Aspect implementation is a class in which provided facets of the nested
ACIs must be implemented, copying the interface structure. Nested implementation classes are free to
define additional state and behavior.

37
CaesarJ

Example 6.2. ObserverProtocolImpl in CaesarJ

class ObserverProtocolImpl implements ObserverProtocol {


class Subject {
List observers = new LinkedList();
void addObserver(Observer o) { observers.add(o);}
void removeObserver(Observer o) {
observers.remove(o);
}
void changed() {
Iterator it = observers.iterator();
while ( iter.hasNext() )
((Observer)iter.next()).notify(this);
}
}
}
/**
* @author Mezini, M.
* @author Ostermann, K.
* @version 03/2003
*/

Aspect Binding. Aspect binding implements all expected methods in the top ACI and its nested interfaces
and declares pointcuts – CaesarJ's joinpoint model is roughly the same as of AspectJ.

38
CaesarJ

Example 6.3. ObserverProtocol Binding in CaesarJ

class ColorObserver binds ObserverProtocol {


class PointSubject binds Subject wraps Point {
String getState() {
return "Point colored "+wrappee.getColor();
}
}
class LineSubject binds Subject wraps Line {
String getState() {
return "Line colored "+wrappee.getColor();
}
}
class ScreenObserver binds Observer wraps Screen {
void notify(Subject s) {
wrappee.display("Color changed: "+s.getState());
}
}
after(Point p): (call(void p.setColor(Color)))
{ PointSubject(p).changed(); }
after(Line l): (call(void l.setColor(Color)))
{ LineSubject(l).changed(); }
}
/**
* @author Mezini, M.
* @author Ostermann, K.
* @version 03/2003
*/

A binding declares binding classes (e.g. PointSubject) by encapsulating the base objects (e.g. Point).
The wraps clause is a syntactic sugar for:

class PointSubject binds Subject {


Point wrappee;
PointSubject(Point wrappee) { this.wrappee = wrappee; }
...
}

Wrapper class can have one or more “wrappees” that can be initialized or computed in the constructor.
This makes aspect instantiation very flexible.

The Expression Problem – P. Wadler (Y. 1998)


The expression problem – also known as extensibility problem – is a classical benchmark of language ex-
tensibility. The term “expression problem” (EP) was introduced by Philip Wadler in 1998 on Java-Generics
mailing list[Wadler 1998]: “The goal is to define a datatype by cases, where one can add new cases to the
datatype and new functions over the datatype, without recompiling existing code, and while retaining
static type safety (e.g., no casts). For the concrete example, we take expressions as the data type, begin
with one case (constants) and one function (evaluators), then add one more construct (plus) and one more

39
CaesarJ

function (conversion to a string). Whether a language can solve the Expression Problem is a salient indic-
ator of its capacity for expression.”

The definition of the problem is being slightly changed in the course of years. Following definition was
given by [Torgersen 2004].

A solution to the expression problem is a combination of:

• a programming language

• an implementation of a Composite structure in that language, and

• a discipline for extension

which allows both new data types and operations to be subsequently added

1. any number of times

2. without modification of existing source code

3. without replication of non-trivial code

4. without risk of unhandled combinations of data and operations

This definition, except last requirement – where would one find static type safety, in general – can be
considered (in my opinion) a standard version of EP.

[Odersky, Zenger 2005] add requirement of Independent extensibility: “It should be possible to combine
independently developed extensions so that they can be used jointly ” and present their solutions in SCALA.

Why EP is a problem? As said by [Wadler 1998]: “Yet I know of no widely-used language that solves
The Expression Problem while satisfying the constraints of independent compilation and static typing.”
At last, Java-Generics allow for a type-safe solution in Java.

Generally, solutions of the expression problem fall into two groups. One group, in that solutions are based
on object decomposition and the second, in that solutions are based on the implementation of the visitor
pattern. See [Torgersen 2004], for thorough explanation. Nice discussion of various solutions in different
programming languages can be found in [Odersky, Zenger 2005].

Virtual Classes and Solution to the Expression


Problem – Ernst, Ostermann, Cook (Y. 2006)
[Ernst, Ostermann, Cook 2006]: “Virtual classes are class-valued attributes of objects. They are analogous
to virtual methods in traditional object-oriented languages: they follow similar rules of definition, overriding
and reference. In particular, virtual classes are defined within an objects class. They can be overridden and
extended in subclasses, and they are accessed relative to an object instance, using late binding.”

We can represent EP with the following simple grammar:

Exp ::=Lit Add


Lit ::=non-negative integer
Add ::=Exp + Exp

Adding a new type of expression – Neg

40
CaesarJ

Exp ::=Lit Add Neg


Neg ::='-'Exp

The operation, we add, is eval(), that returns a value (int) of the expression.

“Solution”, that follows, was taken from [Ernst, Ostermann, Cook 2006], where more importantly a proof
of soundness of virtual class calculus was given, that was awaited for a long time.

Example 6.4. A Virtual Class for the Expression Problem


class Base {
class Exp {}
class Lit extends Exp {
int value; //a mutable variable
}
Lit zero; //a mutable variable
out.Exp TestLit() {
out.Lit l;
l= new out.Lit();
l.value=3;
l;
}
}

Example 6.5. A Virtual Class after Addition of a Negative Expression

class WithNeg extends Base {


class Neg extends Exp {
Neg(out.Expe) { this.e=e; }
field out.Exp e;
}
out.Exp TestNeg() {
newout.Neg(TestLit());
}
}

Example 6.6. A Virtual Class after Addition of a Negative Expression


class WithEval extends Base {
class Exp {
int eval() { 0; }
}
class Lit {
int eval() { value; }
}
int TestEval() {
out.TestLit().eval();
}
}

41
CaesarJ

Example 6.7. A Combination of a Negative Expression and eval() method


class NegAndEval extends WithNeg,WithEval {
class Neg {
Neg(out.Expe) { this.e=e; }
int eval() { -e.eval(); }
}
int TestNegAndEval() {
out.TestNeg().eval();
}
}

The keyword out refers to an enclosing object of a virtual class. Virtual classes can be arbitrarily nested.
Style of class combination is kind of mixin composition – e.g. when Base.TestLit is called from
WithEval.TestEval, the references to Lit are interpreted as WithEval.Lit, not Base.Lit.

Summary. We have seen that the “solution” to the expression problem with virtual classes is very nat-
ural – in fact, no special preparation was needed. I encourage a reader of this chapter to see also other
solutions from referenced papers.

CaesarJ's Solution to AspectJ Deficiencies


Now, after we have seen some demonstration of virtual classes, I can finally show, what can CaesarJ do
in response to loads of criticism imposed on the mainstream AOP language.

Support for multi-abstraction aspects – inner modularity. We have seen, that Subject and Observer
roles have their own modular representation within the ACIs. Methods as getState can be implemented
differently for various implementations.

Support for multi-abstraction aspects – independent extensibility. Further extensions of ColorOb-


server are possible.

Example 6.8. LazyColorObserver

public class LazyColorObserver extends ColorObserver {


override class ScreenObserver {
int count = 0;
void notify(Subject s) {
count++;
if (count >= 10) { super.notify(s); count = 0; }
}
}
}

Support for Sophisticated Mapping. Aspect binding is just a syntactic sugar. Thus, wrappee can be
specified with all object-oriented stuff available.

Support for Reusable Aspect Bindings. Aspect inheritance is not limited only to abstract aspects – as
in AspectJ. Aspects in CaesarJ can be composed as mixins.

42
CaesarJ

Support for Aspectual Polymorphism. Dynamic deployment is supported, however it is not a main
problem of AspectJ. Dynamic deployment can be useful beyond obvious cases like testing aspects, or
caching aspects. Also, AspectJ per-clause instantiation can be easily simulated in CaesarJ.

43
Chapter 7. Conclusions
Filman and Friedman's definition of AOP
Quantification and obliviousness cover only certain kind of multidimensional SOC (MDSOC) techniques.
Recall e.g. FOP, Hyperslices, see the section called “AOP, FOP, AP, SOP, Hyperslices (1990s)”. Consider
mixin composition (see e.g. [Cardone, Lin 2003]).

Obliviousness is far too strong requirement. When using AspectJ 5 together with annotations, its hard to
say if this is oblivious – obliviousness is than question of very specific details. There is a language that
marks events – that look like blocks – in code, allowing quantified composition, etc., however not being
oblivious.

On the contrary, information that in a certain place aspect will apply (recall pointcut interfaces) allows
programmer to reason more globally. If the composition of dimensions could be completely orthogonal
than we would probably not need AspectJ-like programming! Thus, requirement of obliviousness goes
against the power of AspectJ-like programming.

I try to explain more in the next section.

The Essence of AspectJ-like Programming


The argument for Filman and Friedman's definition that it aims to capture, what is specific for AspectJ-
like AOP, stands on only when looking at it shallowly.

Certainly, notion of AOP has gone beyond this style, today. However, I think there is more to AspectJ-like
AOP.

In the section called “AOP, FOP, AP, SOP, Hyperslices (1990s)” I have mentioned several MDSOC
techniques. The idea of Hyperslices sounded compelling, until one realizes that the HARDEST PART
about it is how to merge those hyperslices (recall that every hyperslice has got a set of rules that specify,
how to merge with others). There is no obvious answer to a question, into which of merging hyperslices
one should put the rules – thus it is hard to encapsulate the rules.

It's a bit strange that a notion of multidimensionality somehow disappeared from AspectJ. How can then
AspectJ help with MDSOC?

The idea of AspectJ-like languages is that they have got powerful query language that allows them to expose
those overlapping parts of hyperslices to one module and code those hyperslices' interactions locally (and
fire up this proces at a certain moment of compiletime or at runtime)! This is a significant improvement
beyond HyperJ. HyperJ simply didn't manage modularity of its own mechanism. However, with AspectJ,
it is the same story, when compared to CaesarJ.

Coupling, Cohesion, Encapsulation and Modular


Reasoning
In the section called “Cohesion” I explained that term cohesion doesn't say much in AOP. Moreover, its
somewhat complementary to coupling.

44
Conclusions

In the section called “Coupling” I explained that it's not always obvious, how measures of coupling behave
when one modularizes scattering. Reducing tangling raises coupling, therefore “low coupling” is not anymore
an “obvious goal that we are striving for”. Coupling, as defined, is even not measurable at the time of
design and its approximation by functional dependency fails with respect to scattering and tangling.
Therefore, in AOP, more reasonable measure is – more general – ability of modular reasoning.

Breaking encapsulation, as well as preserving encapsulation must have a particular reason.

AspectJ's Modularity – Language Features Dis-


cordance
I elaborated, as I hope, all rational implementations of the observer design pattern and subjected them to
a thorough analysis. However, observer pattern is not all of the universe, one can generalize pretty much
from it.

Both new implementations feature better modularity of the solution. Further shift in usability of the imple-
mentation caused total breakage of reusability of the implementation.

AspectJ's aspects allow iterative reusability only through abstract aspects. And we have seen that aspectOf()
method (upon that implementation with per-clause is based) can not be used in an abstract aspects.

To sum it up: Kiczales' and Mezini's original implementation is the least modular of all, but quite usable.
Implementation with inter-type-member declaration is the most modular of all, but has got pure usability
(injected methods name clashes). The implementation with per-clause has got the best usability (roles im-
plemented with tricks) but impossibility to implement notifyObservers(SR s) in an abstract aspect is a blast
in the very heart of the original idea.

AspectJ – Recommendation for Small Improve-


ments
The outcomes of the analysis of the observer design pattern suggest that some features of AspectJ were
not designed cautiously (e.g. usage of the aspectOf() method in abstract aspects and its overriding in concrete
ones). Upon constraints from the analysis one can propose a set of small improvements to AspectJ. I did
not do this, because it's clear that to get AspectJ working right further extensions to the language are neces-
sary.

AspectJ's better modularity can be achieved basically in two ways.

First, extending Java packaging mechanism with respect to scoping and visibiilty rules (see ht-
tp://www.cs.utah.edu/plt/jiazzi/, maybe this project could help, further work is needed), so that one could
use packages like overlapping views – (recall clashing names problem of the implementation with inter-
type-member declarations). Modularity of this mechanism per se and reusability of such views is doubtful,
however it matches with noninvasiveness property of AspectJ.

The other way around is extending Java inheritance, this rout was chosen by CaesarJ. Take CaesarJ!

45
Bibliography
[Aldrich 2004] Aldrich, J., Open Modules: A Proposal for Modular Reasoning in Aspect-Oriented Programming,
Carnegie Mellon Technical Report CMU-ISRI-04-108, 2004.

[Aracic et. al. 2006] Aracic, I. and Gasiunas, V. and Mezini, M. and Ostermann, K., Overview of CaesarJ, Transactions
on Aspect-Oriented Software Development I. LNCS, Vol. 3880, Feb 2006, pp. 135 - 173 .

[Cardone, Lin 2003] Cardone, R. and Lin, Calvin, Using Mixin Technology To Improve Modularity, Mehmet Aksit,
Siobhan Clarke, Tzilla Elrad, and Richard Filman, eds. Aspect-Oriented Software Development, Addison-
Wesley, 2003, pp. 219-242 .

[Assmann 2003] Assmann, Uwe, Invasive Software Composition, Springer Verlag, 2003 .

[AspectJ Guide] AspectJ Team, The AspectJ Programming Guide, http://www.eclipse.org/aspectj/doc/released/prog-


guide/ .

[AspectJ Notebook] AspectJ Team, The AspectJ 5 Development Kit Developer's Notebook, http://www.eclipse.org/as-
pectj/doc/released/adk15notebook/index.html .

[Bardou, Hachani 2003] Bardou, Daniel and Hachani, Ouafa, On Aspect-Oriented Technology and Object-Oriented
Design Patterns, AAOS 2003: Analysis of Aspect-Oriented Software, ECOOP 2003, 2003 .

[Brichau et. al. 2000] Brichau, Johan and De Meuter, Wolfgang and De Volder, Johan, Jumping Aspects, position paper
at the workshop Aspects and Dimensions of Concerns, ECOOP 2000, Sophia Antipolis and Cannes, France,
June 2000.

[CaesarJ Guide] CaesarJ Programming Guide. http://caesarj.org/index.php/ProgrammingGuide/Contents .

[Cardone, Lin 2003] Cardone, R. and Lin, Calvin, Using Mixin Technology To Improve Modularity, Mehmet Aksit,
Siobhan Clarke, Tzilla Elrad, and Richard Filman, eds. Aspect-Oriented Software Development, Addison-
Wesley, 2003, pp. 219-242 .

[Coggins 1996] Coggins, James M., Subject-Oriented Programming, George H. Jacoby and Jeannette Barnes, eds.,
ASP Conference Series, Vol. 1, 1996 .

[Colyer et al. 2004] Colyer A. and Rashid, A. and Blair, G., On the Separation of Concerns in Program Families,
Technical Report, Computing Department, Lancaster University, January 2004 .

[Constanza 2000] Costanza, Pascal, Vanishing Aspects, Workshop on advanced separation of concerns at OOPSLA
2000, Minneapolis, Minnesota, USA, 2000.

[Date 1998] C.J. Date, Encapsulation Is a Red Herring, http://www.dbpd.com/vault/9809date.html.

[Ernst, Ostermann, Cook 2006] Ernst, E., Ostermann, K., and Cook, W. R. A virtual class calculus. In Conference
Record of the 33rd ACM SIGPLAN-SIGACT Symposium on Principles of Programming Languages (Char-
leston, South Carolina, USA, January 11 - 13, 2006). POPL '06.

[Filman, Friedman 2000] Filman, R. E. and Friedman, D. P., Aspect-Oriented Programming is Quantification and
Obliviousness, Workshop on Advanced Separation of Concerns, OOPSLA 2000, Minneapolis, October 2000.

[Filman 2001] Filman, R. E., What Is Aspect-Oriented Programming, Revisited, Technical Report, RIACS, 2001.

[GoF 1994] E. Gamma, R. Helm, R. Johnson, and J. Vlissides. Design Patterns: Elements of Reusable Object-Oriented
Software. Addison-Wesley, 1994.

46
Bibliography

[Hannemann, Kiczales 2002] Hannemann, J. and Kiczales, G. 2002, Design pattern implementation in Java and aspectJ,
In Proceedings of the 17th ACM SIGPLAN Conference on Object-Oriented Programming, Systems, Languages,
and Applications, Seattle, Washington, USA, November 04 - 08, 2002, OOPSLA '02, ACM Press, New York,
NY, 2002, 161-173 .

[HyperJ] HyperJ: Multi-Dimensional Separation of Concerns for Java. http://www.research.ibm.com/hyperspace/Hy-


perJ/HyperJ.htm.

[Kiczales et al. 1997] Kiczales, G. et al., Aspect-oriented programming, ACM Computing Surveys, 28, 4es (Dec.
1996), Article n. 154, 1996.

[Kiczales et al. 2001] Gregor Kiczales, Erik Hilsdale, Jim Hugunin, Mik Kersten, Jeffrey Palm, and William G. Griswold.
An overview of AspectJ. In Proceedings of the European Conference on Object-Oriented Programming,
Budapest, Hungary, 18–22 June 2001.

[Kiczales, Mezini 2005] Kiczales, G. and Mezini, M. 2005. Aspect-oriented programming and modular reasoning, In
Proceedings of the 27th international Conference on Software Engineering, ICSE '05, 49-58, St. Louis, MO,
USA, 2005.

[Lieberherr 1995] Lieberherr, K. J., Adaptive Object-Oriented Software, the Demeter Method with Propagation Patterns,
PWS Publishing Co., 1995 .

[Odersky, Zenger 2005] Odersky, Martin and Zenger, Matthias, Independently Extensible Solutions to the Expression
Problem, Proc. FOOL 12, January 2005 .

[Mezini, Ostermann 2003] Mezini, M., Ostermann, K., Conquering Aspects with Caesar, to appear in Proc. of Inter-
national Conference on AspectOriented Software Development (AOSD 2003), March 2003, http://cite-
seer.ist.psu.edu/mezini03conquering.html .

[Parnas 1972] Parnas, D. L. 1972, On the criteria to be used in decomposing systems into modules. Commun. ACM
15, 12 (Dec. 1972), 1972, 1053-1058.

[Schwartz] Product-Line Architecture Research Group. http://www.cs.utexas.edu/users/schwartz/Started.html.

[Tarr et. al. 1999] P. Tarr, H. Ossher, W. Harrison, and S. M. Sutton, Jr. N degrees of separation: Multi-dimensional
separation of concerns. In Proceedings of the 21 International Conference on Software Engineering (ICSE'99),
107–119, May 1999.

[Torgersen 2004] M. Torgersen, The expression problem revisited — Four new solutions using generics. In Proceedings
of the 18th European Conference on Object-Oriented Programming, Oslo, Norway, June 2004.

[Vlissides 1998] John Vlissides, Subject-Oriented Design. C++ Report, February, 1998 http://researchweb.wat-
son.ibm.com/sop/sopvlisdecorator.htm .

[Yourdon, Constantine 1979] Edward Yourdon and Larry L. Constantine. Structured Design: Fundamentals of a Dis-
cipline of Computer Program and System Design Prentice-Hall, 1979, see e.g. ht-
tp://www.win.tue.nl/~wstomv/quotes/structured-design.html or http://www.magma.ca/~dmattins/cysd07tc.htm
.

[Wadler 1998] Philip Wadler, The expression problem. Discussion on the Java-Genericity mailing list, December 1998
.

47
Glossary
Advice Advice (meaning advice body) defines interaction of several concerns at an asso-
ciated pointcut. Behavior it defines may influence any of the concerns.

Vaguely advice might mean advice body with its associative pointcut together.

Anemic Domain Model “Anemic domain model is represented by objects with their behavior implemented
outside these objects (usually in service objects).” [ http://www.martinfowl-
er.com/bliki/AnemicDomainModel.html ]

Aspect An aspect (in AspectJ) is a “corsscutting type”, implementation of that can cut
across other types. The aspect declaration is similar to the class declaration in that
it defines a type and an implementation for that type and it is a unit of modularity
and encapsulation.

Aspect declaration in AspectJ wraps up pointcuts, advice, and inter-type declarations


and per-clause.

Aspect was originally defined as a constraint implementation of which is scattered


or tangled.

Cohesion “Intramodular functional relatedness [??] – is a clumsy term. What we are consid-
ering is the cohesion of each module in isolation – how tightly bound [?] or
[functionally] related its internal elements are to one another. ” [Yourdon, Con-
stantine 1979]

Concern A concern is some part of the problem which is natural to treat as a single concep-
tual unit. In other words, it is a set of constraints on program functionality, imple-
mentation or whatever.

Coupling “Coupling as an abstract concept – the degree of interdependence between modules


– may be operationalized as the probability that in coding, debugging, or modifying
one module, a programmer will have to take into account something about another
module. ” [Yourdon, Constantine 1979]

Encapsulation If an implementation is encapsulated, then no other module can depend on its im-
plementation details [Liskov, Barabara, Data Abstraction and Hierarchy, OOPSALA
'87 Addendum to the proceedings, MIT Laboratory for Computer Science, Cam-
bridge, Ma. 02139, 1987].

Feature Oriented Programming Feature Oriented Programming (FOP) is a design methodology for which incre-
mental action is a feature – the unit of user defined functionality. The goal is to
specify a target program declaratively in terms of the features that it offers, and to
synthesize an efficient implementation that meets these specifications. ht-
tp://aosd.net/2005/tutorials/fop.php

Inversion of Control A way of decoupling code. E.g. method A.x calls method B.y and method C.y
consequently. We might want the implementation of method A.x to have no notion
of B. We can achieve this in several ways e.g. calling B.y from C.y. For detailed
explanation see http://www.martinfowler.com/articles/injection.html.

Known also as Hollywood principle: “Don't call us, we'll call you”

48
Glossary

Join point Join point is a well-defined point in the “execution” of a program. (Its precise
quantification may depend on a piece of runtime information.)

Pointcut Pointcut is an AOP language construct that picks out join points and exposes in-
formation available in their execution context. Pointcuts are used primarily in an
association with advice. Another way to say it (but excluding some minor cases):
the pointcut is a set of join points.

Role The role is a concept mostly used to refer to the role an object plays in the system.
http://swt.cs.tu-berlin.de/~stephan/VAR05/postws/PanelStatement-AwaisRashid.pdf

Scattering Implementation of a concern is scattered, if it spans multiple regions (regions are


typically modules, but may be blocks of exception handling).

Tangling Code that implements a concern is tangled, if it is not textually separated from the
code that implements other concern(s).

View A view is a perspective on the system. This perspective, that usually spans multiple
system elements, may be that of external actors, e.g. stakeholders, external systems,
etc. http://swt.cs.tu-berlin.de/~stephan/VAR05/postws/PanelStatement-
AwaisRashid.pdf

Weaving Weaving is the process of composing modules of the component language with
aspects. It is an implementation issue.

49

You might also like