A Definition, Overview and Taxonomy of Generic Aspect Languages

A Definition, Overview and Taxonomy of
Generic Aspect Languages
Günter Kniesel — Tobias Rho
Institut für Informatik III
Universität Bonn
Römerstr. 164
D-53117 Bonn, Germany
[email protected]
[email protected]
ABSTRACT.
Aspect-orientation promises better modularity than pure object-oriented decomposition. A typical benefit of increased modularity is ease of maintenance, evolution and reuse.
However, it has been noted by various researchers that many of the first generation aspect
languages do not provide the degree of reusability initially hoped for.
In this paper, we argue that the problem of insufficient reusability is due to a lack of support
for aspect genericity. We analyze various problems of traditional aspect languages and
define aspect genericity to be the ability to concisely express aspect effects that vary
depending on the context of a join point known at weave-time, without falling back to runtime reflection. We identify the ability to parameterize aspect effects with meta-variables
ranging over base language elements as the technical prerequisite for achieving genericity
and describe the design space for generic aspect languages in terms of five basic questions
that a language designer should consider. Within this space we review the different proposals
for generic aspect languages made so far and compare them by showing which part of the
possible design space is explored within these languages.
Among the reviewed design options we identify predicate-based binding of logic metavariables, uniform genericity and fine-grained genericity as optimal answers to three of the
discussed questions. Last but not least, we identify open research problems that are specific
to aspect genericity or aggravated in the presence of genericity.
We expect that genericity will be a key ingredient of a second generation of aspect languages.
It will significantly reduce the dependency of aspects on base programs and will automatically select behavior depending on the weave-time context of a join point in the same way as
dynamic binding does depending on the type of a message receiver.
KEYWORDS: aspect-oriented programming, generic aspect language, uniform genericity, finegrained genericity.
2 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
1. Introduction
Aspect-oriented software development (AOSD) is a powerful new paradigm for
separation of concerns. Functionality that would otherwise be scattered throughout a
program because it cannot be modularized in the dominant decomposition (Ossher
et al., 2001a) of a particular language can be encapsulated into an aspect. Filman
and Friedman (Filman et al., 2000) characterize AOSD as a modularization concept
with two desirable properties: quantification, which is the ability to declare actions
to be applied consistently to many places in a program, and obliviousness, which
means that the modified program entities do not need to be aware of being subject to
aspect activity and do not need to provide special hooks for enabling such activity.
Obliviousness of base code greatly eases evolution, since changes in aspects do
not require corresponding changes in base code. However, while base code is oblivious to aspects (or should at least be as oblivious as possible), aspects are not at all
oblivious of base programs. Obviously, aspects must know about the base entities
that they want to influence. It is the degree of knowledge and implied coupling that
has turned out to be a problem in first generation aspect languages – AspectJ
(Kiczales et al., 2001), HyperJ (Ossher et al., 2001a), Composition Filters (Aksit et
al., 1992), DemeterJ (Demeter) – and later approaches that adopted and evolved one
of these archetypes, e.g. AspectC++ (Spinczyk et al., 2002).
These languages introduce strong dependencies of aspects on base code by
requiring aspects to use concrete names of types, classes, methods, and other
entities from base programs. In these languages, the only mechanism to alleviate the
dependence of aspects from base entities is the provision of wildcards1 in the
pointcut language.2 However, as noted by various researchers (De Volder, Hassoun
et al., 2003, Hanenberg et al., 2003a, Gybels et al., 2003, ) the lexical dependencies
introduced by wildcard-based pointcut languages negatively influence aspect
applicability, conciseness, reuse and evolution.
This paper makes the following contributions to the state of the art of aspectoriented language design:
− an analysis of the problems with aspect languages based exclusively on
wildcard-matching (Section 2 and 3),
− a definition of generic aspect languages (Section 4),
− a thorough discussion of the design dimensions of generic aspect languages
and a classification of current work in this area (Section 5),
− a discussion of research challenges imposed by generic aspects (Section 6),
1
In AspectJ, for instance, ‘*’ matches type, method and field names (or parts of them), ‘..’
matches a parameter list, and ‘**’, matches portions of a fully qualified Java type name.
2
The terms crosscut language and pointcut language are used to denote the aspect
sublanguage that specifies where and when aspect actions should be executed.
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
3
− a classification of existing generic aspect languages with respect to the
discussed design options and challenges (Section 7),
− a discussion of work related to aspect genericity in aspect languages and other
domains (Section 8).
The current paper is a significantly extended version of (Kniesel et al. 2005).
Besides various improvements of the structure and presentation of the material we
have refined our definitions and our taxonomy (Section 4 and 5), added the
summary section 7 and extended our discussion to include related work in the area
of non-generic aspect languages, logic meta-programming, program transformations, and predicate dispatch for object-oriented languages (Section 8).
1.1. Terminology
Before we delve into the sketched topics we first define a few terms that we need
to make the following discussion language-independent.
Aspect effect. The term aspect effect denotes the changes that an aspect
performs on a program or a program execution. Effect specifications are static
declarations of such effects. They correspond, for instance, to inter-type declarations
in AspectJ (Kiczales et al., 2001), filter types in Composition Filters (Aksit et al.,
1992), and composition specifications in HyperJ (Ossher et al., 2001a). An AspectJ
advice without the associated pointcut is also an effect specification.
Aspect predicate. An aspect predicate is a predicate that selects places in the
program or events in the program execution where aspect effects should be applied.
Predicates correspond, for instance, to the pointcuts of AspectJ and filter conditions
of Composition Filters.
Crosscut specification. A crosscut specification is a pair consisting of an aspect
predicate and an aspect effect specification. It expresses the crosscutting nature of
aspect effects by connecting them to all the places / events where they should occur.
Examples of crosscut specifications are filter declarations in Composition Filters,
introductions in Sally (Hanenberg et al., 2003a) and advice in AspectJ. Some
languages provide a single crosscut specification syntax that can express crosscutting introduction and advice in a unified way (e.g. Josh (Chiba et al., 2004),
LogicAJ (Rho et al., 2004, Windeln 2003), and recent versions of Sally).
Aspect. An aspect is a module that contains crosscut specifications. In many
aspect languages, aspects can also contain base language elements (fields, methods).
Base language. A base language is a conventional programming language that
has no notion of aspects, crosscut specifications, aspect effects or aspect predicates.
For instance, the base language of HyperJ and AspectJ, is Java. AspectC++ has
C++ as its base language. The Composition Filter model and its incarnation in the
aspect language Compose* has many different base languages.
4 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
Base module. A base module is a module containing only base language
elements. The set of all base modules in a program is called the base program.
2. Limitations of Non-Generic Aspect Languages
A large class of current aspect languages allows references to base language
entities (types, classes, methods, etc.) only via names or via patterns consisting of
names and wildcards. We call them wildcard-matching-based languages. This class
includes various derivates of AspectJ (e.g. AspectC++, AspectC#) but also different
instantiations of the Composition Filters model and HyperJ. The following
discussion of the problems arising from the sole reliance on wildcard matching is
applicable to all the languages in this category.
2.1. Expressiveness
Languages based on wildcard matching cannot express that certain wildcards
must match the same value, which limits their applicability. As an illustration of the
problem, consider the Eclipse framework. It is organized into public packages that
provide stable APIs for a major Eclipse version and internal packages, whose
implementation may change in every minor release. Each public package provides
an API to a set of internal packages. The Eclipse Internal Package Convention
states that an internal package may only be accessed from its public superpackage or
from another internal subpackage of its public superpackage (EPNC01). For
instance, ‘org.eclipse.platform’ is the public superpackage for all the packages named
‘org.eclipse.platform.internal.*’. Although this is a simple lexical convention, AspectJ
cannot express it because it cannot express that different wildcards matching a
package prefix must share the same value. This is illustrated in Figure 1.
1 aspect EclipsePackageAccessContract {
2
declare warning :
3
call(* **.internal.**.*.*(..))
4
&& !( within(**.internal.**) || within(**) )
5
:
6
"The call violates the Eclipse package access contract.";
7 }
Figure 1 In order to check the Eclipse Internal Package Convention it would be
necessary to express that the underlined wildcards must match the same value. This
is not possible with AspectJ.
2.2. Evolvability
It has been often pointed out that lexical dependencies make aspects highly
sensitive to changes in base programs – see, for instance, (Tourwé et al., 2003) and
(Hanenberg et al., 2003b). If names in base programs are changed, the aspects that
rely on those names must be changed too. For instance, this is the case if setter
methods are described as methods whose name starts with the string ‘set’ and the
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
5
naming convention is changed or abandoned entirely. Therefore, independent
evolution of aspects and base programs is not possible in languages based on
wildcard matching, except in trivial cases. Tourwé, Brichau and Gybels (Tourwé et
al., 2003) call this the aspect evolution paradox because one would generally
assume that improved modularity goes together with improved evolvability.
2.3. Conciseness
In order to implement a concern that has heterogeneous (that is, similar but not
entirely equal) effects on different base code entities, crosscut specifications that are
similar up to the used base entity names must be written for every relevant base
entity. This makes aspects highly redundant, which is inconvenient for programmers
and a source of errors and maintenance problems.
We illustrate the conciseness problem of wildcard-matching-based aspect languages by considering ‘class posing’ as an example of a crosscutting concern that
requires heterogeneous effects. A class posing statement in Objective C (Pinston et
al., 1991) guarantees that henceforth all statements of the program that specify
creation of S instances automatically create C instances instead, provided S is a
superclass of C. This is very useful for unanticipated object-oriented extension by
inheritance.3 A frequent scenario is the use of mock objects (Mackinnon et al.,
2002), a common technique for narrowing down the potential sources of a failure
during testing. Its essence is the replacement of some of the tested classes by mock
classes that provide a fixed, expected behavior. In a language that does not support
class posing, the common way to use mocks of a class S is to implement a subclass
of S, say C, that provides mock behavior and then replace all instantiations of S with
instantiations of C.4 This must be done for all the pairs of original classes and mock
classes to be used in a test run. For each pair, it must be done consistently
throughout the entire program, not just in the test classes – otherwise the
inconsistent simultaneous use of mocks and original objects might itself be a source
of errors.
An aspect implementing class posing must replace the creation of S instances by
the creation of C instances throughout the program. This can be done in AspectJ by
an around advice that replaces invocations5 of constructors of S by invocations of
constructors of C. However, if S has multiple constructors, we need to repeat the
same advice for every constructor, as illustrated in Figure 2. The problem is that
there is no way to intercept the values of an unknown number of arguments in the
3
Note that programmers cannot foresee every possible case where ‘class posing’ might be
useful in the future. Therefore one cannot assume that the entire program is written following
some of the object creation patterns (Gamma).
4
In the related work section we discuss the advantages of this implementation scheme over
an alternative one, known as “virtual mock objects”.
5
Replacing the execution of a constructor by an invocation of a subclass constructor would
lead to infinite recursion. Therefore, we can only replace constructor calls.
6 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
pointcut and to pass them to the body of the advice. This leads to redundant code
that is tedious to write, opens the door for editing errors, and hampers reuse (see
Section 2.4).
aspect AJ_Replace_S_by_C {
// Replace new S(String) Æ new C(String)
S around(String arg1) :
call(S.new(..)) && args(arg1) {
return new C(arg1);
}
// Replace new S(String,int) Æ new C(String,int)
S around(String arg1, int arg2) :
call(S.new(..))&& args(arg1,arg2) {
return new C(arg1,arg2);
}
// Continue like this for all other constructors of S...
}
Figure 2: Heterogeneous aspect effects via redundant code: Replacement of
constructor invocations by repeating largely similar advice.
2.4. Reusability
A further problem that stems from being dependent on concrete names of base
entities is the lack of reusability of aspects (De Volder 2001, Hassoun et al., 2003,
Hanenberg et al., 2003a, Gybels et al., 2003). For instance, the aspect from Figure 2
is specific to the classes S and C. It does not implement the class posing concern, it
just implements a specific instance of it. It is clearly not reusable, not even for
another pair of classes, say X and Y, within the same application.
This problem is amplified when trying to write an aspect that is reusable across
multiple applications. Then, reliance on base entity names is not possible, unless the
aspect programmer knows all of the applications well enough to specify relevant
entities by name.
2.5. Safety
A more reusable implementation of class posing could be achieved in AspectJ
by an around advice using runtime reflection, as illustrated in Figure 3. The advice
intercepts all constructor invocations (line 6). For every intercepted invocation it
checks whether the constructor belongs to the ‘old’ class and whether the ‘new’
class exists (line 7-21). If both are true, it accesses the dynamic join point context to
get the arguments of the intercepted constructor call (line 24-28). Then the auxiliary
resolveConstructor method determines via reflection the constructor with the right
signature from the new class (line 29-30). Finally, it uses reflection to invoke the
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
7
new constructor with the intercepted arguments (line 31).
The primary drawback of this solution compared to the first one is that it cannot
detect errors at weave-time. Use of non-existing classes, for instance, will result in
unforeseen ClassNotFoundExceptions at run-time. Apart from that, the solution is
lengthy, hard to read and error-prone.6 Last but not least, it is also inefficient, since
it requires run-time reflection instead of exploiting static information at weave-time,
as discussed next.
1 aspect AJClassPosingWithReflection {
2
3
abstract String getOldClassName();
4
abstract String getNewClassName();
5
6
Object around() : call(*.new(..)) {
7
Class class = thisJoin point.
8
getSignature().getDeclaringType();
9
Class newClass;
10
11
// Is this the class to replace?
12
if (!class.getName().equals(getOldClassName()){
13
return proceed();
14
}
15
16
// Does new class exist?
17
try {
18
newClass = Class.forName(getNewClassName());
19
} catch (Exception ex) {
20
return proceed();
21
}
22
23
// Try replacement
24
Object() args = thisJoin point.getArgs();
25
try {
26
Class() types =
27
((CodeSignature)thisJoin point().
28
getSignature()).getParamtypes();
29
Constructor constr =
6
30
resolveConstructor (newClass, types);
31
return constr.newInstance(args);
32
} catch (Exception ex) {
33
throw new RuntimeException(“AspectJ:”+
34
“Instance creation failed“);
35
}
36
}
37 }
Figure 3 Heterogeneous effects using runtime reflection in an advice. Constructor
invocations are replaced after lengthy, unsafe and inefficient run-time checking of
purely static information.
The implementation of the method resolveConstructor is not shown here, since it consumes
additional 30 lines of reflective code. The complete code of the example can be found at
http://roots.iai.uni-bonn.de/research/logicaj/examples.
6
8 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
3. Problem Analysis: Statically Expressing Variation
The examples from Figure 2 and Figure 3 illustrate that writing reusable and
non-redundant aspect code with AspectJ requires falling back on plain Java
reflection, with all the implied drawbacks. Looking at the reflection-based
implementation in Figure 3, it is noteworthy that all the reflective advice code,
except line 31, is concerned only with determining at run-time information that is
entirely static (classes, argument lists, and method signatures). Obviously, wildcardmatching based languages are not expressive enough to capture all the static context
of a join point and to parameterize the aspect effects by this context.
The need to parameterize aspect effects by the static context of a join point stems
from the fact that the effect of an aspect needs to vary depending on this context, as
illustrated by the class posing example.
The important point here is that the choice of which particular variant of an
effect applies at a particular join point should be done at weave-time by the aspect
weaver, whenever the variation is completely determined by information available
at weave-time. This frees programmers from having to hand-code the different
aspect effect variants, in the same way as dynamic binding frees object-oriented
programmers from having to manually encode message dispatch to different
receiver types.
Both cases are about a higher level abstraction that allows to concisely express
variant behavior. Dynamic binding expresses dependency of behavior on the
message receiver’s type whereas aspect genericity expresses dependency of
behavior on the context of a join point. A join point can be seen as the receiver of
the aspect’s advice and the join point context can be seen as the advice receiver’s
type. Continuing the analogy, the repetitive advice from Figure 2 corresponds to an
encoding of message dispatch by type tags and switch statements – each copy of the
advice is like a branch of a switch statement that discriminates over the static join
point context. The reflective advice from Figure 3 corresponds to a reflective
implementation of message dispatch in a non-object-oriented language. What we
want instead is to reduce the code from Figure 2 to a single advice that is
parametric with respect to the name, arity and parameter list of the intercepted
constructor call. Depending on the parameter values, the advice should perform
different effects at different join points. For instance, it should perform a C(arg1)
constructor call at a join point that matches a S(arg1) invocation and a C(arg1,arg2)
constructor call at a join point that matches a S(arg1,arg2) invocation. An example
of a generic advice that achieves this is given in Section 5.1.2, Figure 6.
Similar observations where made by (De Volder et al., 2000) and (De Volder).
They argue that a good aspect-oriented language should provide mechanisms of
genericity, polymorphism and parameterization that would allow code to be reusable
and to adapt to different contexts.
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
9
4. Aspect Genericity
In this section we give two definitions of aspect genericity. The first definition
says what must be expressible in a generic aspect language. The second one says
how it can be expressed.
The problem analysis from the previous section identified a desirable property
that is lacking in aspect languages based on wildcard-matching: the ability to
express variability concisely and safely. This leads us to our first, declarative
definition of generic aspect languages:
Definition 1 “Generic Aspect Language” (Declarative): An aspect language
is generic if its aspects can specify multiple variants of an aspect effect in one single
crosscut specification, without falling back on reflection.
Meta-variables. In order to express the desired variability we need to be able to
parameterize aspect effects by meta-variables. A meta-variable is a variable that
ranges over syntactic entities of the base language. For instance, an aspect language
based on Java could provide meta-variables that range over packages, types,
classes, fields, methods, modifiers, statements, and expressions. In the remainder we
will denote meta-variables by identifiers starting with a question mark, e.g. ?class or
?methodBody.
Based on meta-variables we can rephrase aspect genericity from a more
technical point of view:
Definition 2 “Generic Aspect Language” (Technical): An aspect language is
generic if it enables the use of meta-variables in aspect effect specifications.
This redefinition fulfils the requirement of the initial definition of aspect genericity because meta-variables contained in the aspect effects let the effects vary
depending on the meta-variables values. Such aspects provide a concise specification of many different effects. Meta-variables play the role of generic parameters of
the aspect and every tuple of values for the meta-variables of an aspect represents
one instantiation of the generic effects.
We claim that the use of meta-variables in aspect effect specifications is the only
way to achieve genericity according to our first definition. Therefore, we consider
the two definitions to be equivalent. Our claim cannot be proved formally.
However, it is supported by the approaches reviewed in this paper, which are all
based on meta-variables in aspect effects. To the best of our knowledge, this is a
complete overview of all existing work on aspect genericity.
5. Design Space for Generic Aspect Languages
The technical definition of aspect genericity in Section 4 encompasses an entire
family of aspect languages that can differ depending on the answers that their
designers choose for each of the following questions:
10 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
How values for meta-variables are provided (meta-variable binding)?
2. Where can meta-variables be used (meta-variable scope)?
3. What kind of meta-variables are supported (meta-variable kind)?
4. Over which base entities can meta-variables range (meta-variable domain)?
5. What actions can be performed on the base language entities referred to by
meta-variables (effect granularity)?
In this section we present these language design dimensions, explain their
impact on the expressiveness of a language, and discuss where existing systems fit
in these dimensions. Note that this is not meant to be an introduction to the different
languages. Please see the referenced papers for details of the discussed languages.
1.
5.1. Meta-Variable Binding
Regarding meta-variable binding there are two categories of generic aspect
languages: ones that use external parameterization and ones that use predicate based
binding.
5.1.1. External Parameterization
The simplest way of providing values for meta-variables is to promote the metavariables contained in the aspect effect to parameters of the aspect definition. Then
the values can be supplied “from the outside”. This external parameterization is
analogous to the way generic types are defined in object-oriented languages where
type variables get values when the generic type definition is instantiated by a client.
Figure 4 shows an example illustrating the syntax of SuperJ (Sihman et al.,
2003), a generic aspect language based on external parameterization. The SuperJ
preprocessor creates concrete AspectJ aspects from generic SuperJ aspects by
replacing formal parameters by basic variables, locations, and classes. For this it
uses a binding file, whose lines each contain a set of bindings between elements of a
particular base class and parameters of a particular generic aspect. Similarly, the
Lancaster Frame Processor (LFP) (Loughran et al., 2004) provides external parameters for aspect constructs and uses a macro expansion approach that replaces
parameter markers in AspectJ code by values provided in an external binding file.
LFP supports fine-grained external parameterization (see Section 5.3). Meta-AspectJ
(Zook et al., 2004) additionally supports syntactically typed meta-variables that guarantee at compilation time syntactic correctness of generated code (see Section 6).
External parameterization decouples the aspect code from concrete names of
entities in the base program. Thus, aspects become more reusable, in principle.
However, base entity names must still be provided statically in a binding file. In
order to provide the suitable bindings of meta-variables to base entities, the creator
of the binding file must have intimate knowledge of the generic aspect and of the
base classes to which the aspect is applied. This seriously limits the reusability of
externally parameterized aspects in practice. In addition, the binding file might
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
11
become very large since its size depends on the number of matches in the base
program, which can grow combinatorially with the size of the base program.
Manually editing large numbers of matches can be the source of omissions, typos
and other input errors that will lead to hard to locate errors at run-time.
Figure 5 sketches the start of a binding file7 necessary to express class posing via
external parameterization. Its purpose is to enumerate all combinations of values for
the required meta-variables (?className, ?subName and ??args). Compare this to the
solution using predicate-based binding shown below in figures 6 and 7..
aspect Constant_DPP_Heavy(?EAT_METHOD, ...) extends Common {
...
void around(?BOUND_CLASS C) : execution(?EAT_METHOD) ... {
...
forks = 0;
nAssigns++;
logRecord();
}
...
}
Figure 4 Excerpt of externally parameterized generic SuperJ aspect adapted from
(Sihman et al., 2003, Figure 6). For consistency with the notation used in our
paper, prepended question marks denote generic parameters whose values can be
provided when the aspect is instantiated.
bindings_for(?className, ?subName, ??args):
// All combinations for C and S:
( “C”, “S”, “arg1:String”)
( “C”, “S”, “arg1:String,arg2:int”)
( “C”, “S”, “arg1:String,arg2:int,arg3:T”)
( “C”, “S”, “arg1:String,arg2:int,arg3:T,arg4:T4”)
// All combinations for C1 and S1:
( “C1”,“S1”,“arg1:T1”)
( “C1”,“S1”,“arg1:T1,arg2:T2,arg3:int”)
( “C1”,“S1”,“arg1:T1,arg2:T2,arg3:int,arg4:T4,arg5:T5”)
// All other combinations:
... ;
||
||
||
||
||
||
||
Figure 5 External parameterization: Start of the listing of all tuples of relevant
values for the meta-variables required to express the class posing concern for one
particular base program (see Sections 2.3 and 5.1.2 for comparison).
7
Since the original literature does not describe the binding file contents in detail, we invented
our own ad-hoc syntax. Arguments are described by their name and type.
12 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
5.1.2. Predicate-based binding
A much more powerful alternative to external parameterization is provided by
predicate-based meta-variable binding. The idea is to replace manual enumeration
of statically known values by weave-time evaluation of predicates that bind metavariables to statically unknown values from the base program. In this approach the
aspect predicates (or pointcuts) play a double role: they select join points where
aspect effects are to be applied and they bind meta-variables to values from the
static context of the selected join points.
Andrew / Carma (Gybels 2001) is an aspect-oriented extension of Smalltalk that
lets meta-variables ranging over arbitrary values be used in pointcuts and advices.
OReA, (D’Hondt 2004, D’Hondt et al., 2004) extends this to hybrid aspect
languages, based on the integration of aspects with rules. AspectC++ (Lohmann et
al., 2004) enables the use of type variables in pointcuts and advice bodies. Silaghi
and Strohmeier (Silaghi et al., 2003) propose the same for AspectJ. Sally is an
aspect-oriented extension of Java. Its design described in (Hanenberg et al., 2003a)
supports meta-variables in pointcuts and introductions. Since its November 2005
release Sally also supports meta-variables in advice. LogicAJ (Rho et al., 2004) is an
aspect-oriented extension of Java that has supported meta-variables in pointcuts,
introductions and advice from its first release (Windeln 2003).
Logic variables. In order to enable predicate based binding, meta-variables must
be used in the entire scope of a crosscut declaration, that is, in aspect effect
specifications and in aspect predicates. Like wildcards, meta-variables in aspect
predicates are used as placeholders for statically unknown parts of a logic expression. They can match arbitrary structures when the predicate is evaluated. However,
they are strictly more powerful than unnamed wildcards. Meta-variables provide the
ability (1) to express that different occurrences of the same placeholder must agree
on the matched value and (2) to use the matched values as a building block of
associated effect specifications.
Both abilities depend on the guarantee that different occurrences of a metavariable in the scope of a crosscut declaration represent the same matched value.
Variables that have this property are called logic variables. A logic variable can
only be bound to a value by the evaluation of predicates that take the variable as an
argument. Logic variables cannot be manipulated in other ways (by assignments /
side-effects).
Upon evaluation of an aspect predicate the tuple of logic variables that it
contains is bound to the tuple of values for which the predicate is true. Such a tuple
is said to be a successful substitution of the logic variables. A predicate that has
multiple solutions successively yields multiple substitutions. For instance, assume
an aspect language whose predicate field(?F,?C) expresses that the field represented
by ?F is a member of the class represented by ?C. For a program that contains the
field c1 and c2 in class C, and b1 in class B the evaluation of the query class(?F,?C)
will successively bind the tuple <?F,?C> to <c1, C>, <c2, C> and <b, B>. Every suc-
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
13
cessful substitution triggers an execution of the associated aspect effect specification
during which the logic variables are replaced by the corresponding substitution
values.
Logic meta-variables. A logic meta-variable is a logic variable and a metavariable. The variables ?F and ?C in the above example are logic meta-variables
because are logic variables that ranges over syntactic entities of the base language.
Note that logic meta-variables are not specific to systems based on logic programming. They are commonly used, albeit in restricted forms, in object oriented
and aspect-oriented languages. For instance, generic type parameters in Java, Eiffel
or C++ are just strongly restricted logic meta-variables. They are logic variables
because they always represent the same value within a scope (cannot be explicitly
assigned to). They are meta-variables because they range over base language
entities. However they are subject to two restrictions: they only range over types and
their values are provided manually by specifying constants at instantiation time,
instead of being bound by the evaluation of predicates.
Indeed, even wildcards in aspect predicates (‘pointcuts’, ‘filter conditions’, etc.)
can be seen as a very restricted form of logic metavariable. The restriction is that,
strictly speaking, wildcards are not proper meta-variables. They range not over base
language entities but just over strings that are the names of base languages entities.
They are additionally restricted because they are unnamed – two occurrences are
always treated as being different. De Volder (de Volder1999) points out that this
leads to a set-oriented semantics of aspects and shows why a more powerful
relational semantics is needed.
The fact that the evaluation of a pointcut is side-effect free and yields all
matching values for contained wildcards is familiar to every aspect programmer.
Filman and Friedman (Filman et al., 2000) call this ‘quantification’ and regard it as
a basic characteristic of aspect languages. Acknowledging that wildcards are
restricted logic meta-variables we could say that the use of logic meta-variables is a
basic characteristic of aspect languages. In the following we will explore the added
expressiveness that can be achieved by removing the restrictions imposed by
wildcards and supporting the full power of logic meta-variables.
Example. We illustrate the power of predicate-based binding of logic metavariables by the generic implementation of the concept of class posing introduced in
Section 2. The implementation in Figure 6 uses the syntax of LogicAJ (Rho et al.,
2004, Windeln 2003): Logic meta-variables are denoted by names starting with a
question mark, e.g. “?class”. Identifiers starting with a double question mark, e.g.
“??args”, denote list meta-variables. They can match an arbitrary number of
elements, e.g. any number of call arguments or method parameters (see Section 5.4).
The pointcut of the advice in Figure 6 (line 7-14) binds the meta-variables ?sub
and ??args to values that conform to all the constraints checked in the pointcut.
These values are passed to the advice body. Every pair of values produced by the
14 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
pointcut evaluation instantiates the body in a different way. The instantiated body is
then executed. Let us see how this works in the scenario from Figure 2, with the
original superclass S and its subclass C having each four constructors. If the replace
pointcut returns the bindings ?class = S and ?sub = C, then the check in line 11
succeeds and the call pointcut in line 13 successively selects all join points where
constructors of S are called. For each intercepted join point the args pointcut in line
15 binds ??args to the list of constructor argument values at that join point. Thus the
advice body will be executed multiple times, with ?sub always bound to C and
??args bound differently each time. As a result, it will perform a C(arg1) constructor
call at a join point that matches a S(arg1) invocation and a C(arg1,arg2) constructor
call at a join point that matches a S(arg1,arg2) invocation.
1 abstract aspect ClassPosing {
2
3
// To be defined in a subaspect (See Figure 7):
4
// Who poses for whom? May return multiple pairs of values.
5
abstract pointcut replace(?class,/*by*/?sub);
6
7
Object around(?sub, ??args) :
8
// Determine replaced class and replacing class:
9
replace(?class, /*by*/?sub) &&
10
// Check if ?sub is a subclass of ?super:
11
subtype8(?sub,?class) &&
12
// Intercept ?super constructor invocations
13
call(?class.new(..)) &&
14
// Bind ??args to the argument list of the invocation:
15
args(??args)
16
{
// Return instance of posing subclass ?sub (includes
17
// weave time check that the constructor exists):
18
return new ?sub(??args);
19
}
20 }
Figure 6: Implementation of class posing in LogicAJ. The aspect replaces each call
of a constructor from ?class with a call to the respective constructor of the posing
subclass, if the subclass exists.
Comparison. It is instructive to compare the reflective example from Figure 3 to
the generic one from Figure 6. Most of the code in Figure 3 is concerned with
determining whether the intercepted join point was relevant at all, determining its
arguments, finding the constructor with the right signature from the new class, and
invoking it with the intercepted arguments. In the variant from Figure 6 only the
relevant join points are intercepted, their specific context information is captured in
meta-variables and used at the appropriate places of the aspect effect. The generic
8
The subtype predicate expresses the (reflexive, transitive) subtype relation. If called as
above – with all meta-variables bound to values by a previous predicate – it will just check
that the values are in a subtype relation. Otherwise it will successively bind the free variables
to suitable pairs of values.
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
15
aspect from Figure 6 has the same effect as the redundant code from Figure 2 and
the reflective one from Figure 3. However, it is
− precise
(only the relevant join points are processed),
− efficient (no run-time weaving is required),
− safe (it provides weave-time type checking),
− concise (just 7 lines of non-redundant code), and
− reusable (applying it to other classes or entirely different base programs
requires just another implementation of the replace pointcut in a concrete subaspect).
The last two benefits don’t apply for externally parameterized aspects because of
the need to provide a manually generated binding file for every base program to
which the aspect is applied. For instance, the abstract replace pointcut in Figure 6
subsumes an explicit parameterization of the entire aspect with the meta-variables
?className, ?subName and ??args. With predicate-based binding there is no need for
an explicit enumeration of all possible bindings because these can be expressed
concisely by stating the properties of base entities to be bound to the meta-variables.
Figure 7 shows a concrete subaspect of the class posing aspect from Figure 6. Its
definition of replace selects all the classes that have mock subclasses in any base
program (Rho et al., 2004). See for comparison the binding file from Figure 5,
which enumerates all the values for ?className, ?subName, and ??args for one
particular base program.
1
2
3
4
5
6
7
8
9
10
aspect MockObjectConcern extends ClassPosing {
// The mock replaces the orginal class.
pointcut replace(?class, /*by*/ ?mock):
// Pick a class:
class9(?class, _10, ?className,_) &&
// Its mock class must have the suffix “Mock”:
concat11(?className, "Mock", ?mockName) &&
class(?mock, _, ?mockName,_) ;
}
Figure 7 Predicate-based meta-variable binding: An aspect concisely defining class
posing for mock classes, assuming that every class to be tested has a single mock
class that defines all its mock behavior.
5.1.3. Other
Alvarez (Alvarez 2004) proposes to extend AspectJ by string-valued parameters
for the names of types, methods or fields. This proposal is called parametric
This use of the class predicate says that ?class is a class with simple name ?className.
Underscores are anonymous meta-variables.
11
The third argument of concat is the concatenation of the first and second one.
9
10
16 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
aspects. Parameter values must be provided by enumeration or by parametric
expressions. These are functions on the class hierarchy that are evaluated at weave
time and may yield a set of program element names. The proposal is not
implemented.
Parametric aspects look like a mix of explicit external parameterization and
predicate-based binding. However, they do not achieve the full functionality of
predicate-based binding. In particular, it is not possible to relate different parametric
expressions. Instead, the entire cartesian product of different parametric expressions
is created as a result. For instance, one can create a parametric expression that
selects fields and one that selects classes, but one cannot express that one wants
only those pairs of fields and classes for which the field is an element of the class.
In the example given in the explanation of logic variables (Section 5.1.2) the result
would also contain the wrong tuples <c1, B>, <c2, B> and <b, C>. We consider this a
flawed design. Therefore, it is not included in the overview of generic aspect
languages in Table 1 and Table 3.
5.2. Meta-Variable Scope
Different languages use meta-variables in different ways and for different purposes, depending on the scope in which meta-variables can be used. In this section we
discuss the available options and their implications.
The definition of generic aspect languages requires meta-variables to be used in
aspect effects in order to enable effect variability. It is up to aspect language
designers to decide (1) whether meta-variables are confined to effects or are additionally supported in aspect predicates and (2) whether meta-variables can be used in
all kinds of aspect effects or just in some of them.
Use of meta-variables in aspect effects and in their associated pointcuts enables
predicate-based binding (see 5.1.2). However, some languages do not take full
advantage of this option. For instance, SuperJ (Sihman et al., 2003) and LFP
(Loughran et al., 2004) only support external parameterization, although metavariables may be contained in their predicates. Their predicates can only check
externally provided values but cannot bind meta-variables to values.
Other languages support predicate-based binding but limit the use of meta-variables to a subset of the aspect effects expressible in the respective language. Some
support only advice containing predicate-bound meta-variables – we call this
generic advice. Others only support introductions containing predicate-bound metavariables – we call these generic introductions. For instance, Andrew12 (Gybels
2001) and OReA, (D’Hondt 2004, D’Hondt et al., 2004) only support generic
advice, whereas the initial design of Sally (Hanenberg et al., 2003a) supported only
generic introductions.
12
Andrew has since been renamed to "Carma", see prog.vub.ac.be/~kgybels/Research/.
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
17
Such restrictions limit the expressiveness of a language, since most non-trivial
applications require the joined power of introductions and advice. For instance,
Kniesel, Rho and Hanenberg (Kniesel et al., 2004) analyze design patterns as a
typical use case for generic aspect languages. They show that a language without
generic advice (1) cannot express instantiation of the decorator pattern for multiple
Component classes, (2) cannot enforce that all clients use the decorator instead of
the original component, and (3) cannot implement object based inheritance as a
generalization of simple decorators. Furthermore, they show that a language without
generic introductions cannot create decorators at all, since it cannot fill them with
the required forwarding methods.
External
Parameters
Meta-variable
values bound
by
Introductions only
Externally
parameterized
introductions:
—
Generic
Introductions:
Predicates
(Hanenberg et al.,
2003a)
Meta-variables used in …
Advice only
All effects
Externally
Uniform external
parameterized advice:
parameterization:
(Sihman et al., 2003)
—
(Zook et al., 2004)
(Loughran et al., 2004)
Uniform Genericity:
Generic Advice:
(Gybels 2001)
(Windeln 2003)
(Silaghi et al., 2003)
(Rho et al., 2004)
(D’Hondt et al., 2004)
(Lohmann et al., 2004) (Hanenberg et al., 2003a)13
Table 1 Design subspace for generic aspect languages defined by the options for
meta-variable binding and meta-variable scope. The table shows where known
languages fit within this space. The symbol “—” indicates an empty category.
Uniform Genericity. Summarizing the considerations of Sections 5.1 and 5.2
we can conclude that for maximum expressiveness a language should (1) support
predicate based binding of logic meta-variable values and additionally (2) enable
use of logic meta-variables in all aspect predicates and all aspect effects. A
language that does this is said to provide uniform genericity. Uniform genericity is
clearly the most powerful option in the design space discussed so far and
summarized in Table 1.
Currently, we know of only two uniformly generic aspect languages: LogicAJ
(Rho et al., 2004, Windeln 2003) and Sally (Hanenberg et al., 2003a).13 It appears
that the Andrew / Carma (Gybels 2001) prototype, which extends SOUL (Wuyts
2001, SOUL 2003) by generic advice, could be extended to support also generic
introductions, taking advantage of the reflective facilities of Smalltalk and of the
13
The version of Sally described in (Hanenberg et al., 2003a) only supports generic introductions. However, as of its November 2004 release, Sally also provides uniform genericity – see
http://dawis.informatik.uni-essen.de/site/site/research/aosd/sally/.
18 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
logic inference engine of SOUL. However, Gybels decided not to do so, considering
introductions to be just a by-product of the lack of support for explicit aspect
instances in more static aspect languages (Gybels 2001, Section 5.1.5). Similar
considerations apply for the second SOUL-based aspect language, OReA, (D’Hondt
2004, D’Hondt et al., 2004). It implements the concept of hybrid aspect languages
based on the integration of aspects with rules. Its concept of hybrid advice is a
hybrid language’s instance of generic advice. Like Andrew, OReA does not support
introductions but could be extended accordingly. Suitable extensions of these two
languages would qualify as uniformly generic.
5.3. Meta-Variable Domain
Table 1 does not yet provide a sufficiently fair comparison of existing generic
aspect languages since it does not reflect their significant differences with respect to
the domain of meta-variables. The variants of generic advice proposed by Silaghi
and Strohmeier (Silaghi et al., 2003) for AspectJ and by Lohmann, Blaschke and
Spinczyk (Lohmann et al., 2004) for AspectC++ let meta-variables range over types
only. They mimic type genericity of object-oriented languages in a generic aspect
language but do not achieve context-dependent variability of behavior14.
The other approaches in Table 1 are more expressive, letting meta-variables
additionally range over behavioral base language elements. Carma, Sally and
SuperJ support meta-variables for (the names of) types, fields, and methods.
LogicAJ 1.x additionally provides meta-variables ranging over code blocks but only
supports their use for matching entire method bodies.
Fine-grained genericity. Various researchers have pointed out that this is still
insufficient for modularizing certain cross-cutting concerns. For instance, program
optimization (Harbulot et al., 2004, Harbulot et al., 2005) and code-coverage (Rajan
et al., 2005), can only be modularized if aspects are able to address base language
entities at the finest level of granularity: individual statements and expressions.
Extension of this idea to generic aspect languages leads to the notion of fine-grained
meta-variables. We say that a language supports fine-grained meta-variables if its
meta-variables can range over all syntactic entities of the respective base language.
In Java, this would cover the entire spectrum from packages, types, methods and
fields, down to annotations, statements and expressions. A language supports finegrained genericity (fine-grained external parameterization) if it supports finegrained meta-variables and predicate-based binding (external parameterization).
14
In C++ one could use template meta-programming but this fallback to reflection by the
application programmer is not to be confused with functionality supported by the language
itself (see Definition 1 in Section 4).
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
19
The Lancaster Frame Processor (Loughran et al., 2004) and Meta-AspectJ
(Zook et al., 2004) support fine-grained external parameterization. LogicAJ 2 (Rho
et al., 2006) is the first proposal for fine-grained genericity.
5.4. Meta-Variable Kind
The example from Figure 6 illustrates the distinction between two kinds of metavariables: singular meta-variables and list meta-variables.
Singular meta-variables match only one base language element at a time, e.g. a
type, field, etc. With singular meta-variables only, we are still forced to write
sometimes redundant code that differs only in the length or depth of a nested
structure, e.g. in the number of arguments of a method. This is clearly undesirable
and limits the expressive power, since it is practically infeasible to enumerate an
infinite number of arbitrary length structures.
Therefore, Josh (Chiba et al., 2004) and LogicAJ (Rho et al., 2004, Windeln
2003) and additionally provide list meta-variables that match a sequence of
elements from the base language. Josh supports the $$ list meta-variable that can be
used in a proceed call to match an arbitrary list of arguments. LogicAJ supports list
meta-variables wherever structures of statically unknown length or depth must be
matched in aspect predicates or generated in aspect effects. Examples are argument
and parameter lists and the statements in a block. The concise implementation of
class posing from Figure 6 would not be possible without the list meta-variable
??args.
Some languages, for instance Sally (Hanenberg et al., 2003a), only support one
kind of meta-variables but allow them to match indiscriminately singular values and
list values. We call these hybrid meta-variables. Hybrid meta-variables do not allow
to distinguish syntactically conditions where exactly one value is required (?x) from
those where a (possibly empty) sequence of values is required (??x). However, this
distinction can alternatively be expressed by additional predicates for checking that
a meta-variable is a list and for accessing the different elements of the list.
Another sensible design alternative is to subsume the distinction of metavariable domains and meta-variable kinds in the concept of syntactic types for metavariables (see Section 6). The syntactic type of a meta-variable would indicate the
number and domain of base language elements that may be matched by a particular
meta-variable. Currently, syntactic typing is supported only by the externally
parameterized aspect language Meta-AspectJ.
5.5. Effect Granularity
Within a class of languages that have the same meta-variable domains it is
interesting to compare whether all possible effects (e.g. variants of introductions and
advice) can indeed be performed on all supported meta-variable domains. For
20 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
instance, Sally allows meta-variables for types, methods and fields but only allows
introduction of methods and fields. LogicAJ does not restrict the effect granularity
in any way. In particular, it also supports generic type introductions – that is the
generic creation of a set of types, whose names are not statically fixed in the aspect
code (Rho et al., 2004). This is very useful in many scenarios that require generative
capabilities. An example is the generic creation of abstract decorator classes that are
specific for a particular type of decorated objects. The following code from (Kniesel
et al., 2004, Figure 5) creates a decorator for a specific component type, declares it
to be a subtype of ?component and provides it with an instance variable parent of
type ?component to which messages can be forwarded.
1
2
3
4
5
6
7
introduce abstractDecorator(?component, ?decorator) :
component(?component) &&
decorator(?decorator) {
abstract class ?decorator implements ?component {
protected ?component parent;
}
}
Figure 9 Generic type introduction
The concept of generic type introductions falls out from the uniform granularity
of pointcuts and effects supported by LogicAJ. The above example demonstrates that
uniform granularity increases the expressiveness of a language. In addition it simplifies its specification, implementation and learning since it frees designers, implementers and users from having to deal with special cases.
6. Challenges for Generic Aspect Languages
The previous section has identified design dimensions for aspect genericity and
has discussed the options reflected in existing languages. Now we turn to open
problems of generic aspect languages, focusing on those that are typical of aspect
genericity or harder to address in conjunction with generic aspects.
Fine-grained genericity. Within the discussed design dimensions the combination of uniform and fine-grained genericity is addressed by a single approach (Rho
et al., 2006). Lacking alternative proposals and experience reports it is still unclear
whether this proposal is indeed a good design for a language that integrates uniform
and fine-grained genericity. In addition, fine grained genericity might impose new
challenges for the implementation of aspect languages.
Modular, static analysis versus global, weave-time analysis. One of the advantages of generic aspect languages over run-time reflection is their ability to perform weave-time type checking. During weaving, all meta-variables get concrete
values (either via external parameterization or by evaluation of pointcut decalrations). As soon as the value of the meta-variables are known all expressions in the
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
21
body of an advice can be type-checked. For instance, if we know that the value of
?metaVar is the class C, we know that the expression ?metaVar.m() is a class method
invocation and can check whether C contains a class method m with empty
parameter list.
However, weaving is a global process that requires a complete program as its
input, rather than a partial one. Various researchers have pointed out that more
modular analysis of aspect code would be desirable. In a modular approach, it
would be possible to analyze aspect definitions in isolation, before weaving. Therefore we also call it static analysis (in contrast to weave-time analysis). Modular,
static analysis is a largely unsolved challenge, even for non-generic aspects.
In the presence of meta-variables static analysis is even more difficult because
we need to verify program properties at a time when concrete meta-variable values
are not yet known. In such a case, an expression like ?metaVar.m() cannot be
checked with traditional techniques because we cannot even determine its syntactic
category. If the meta-variable value is a class, the expression is the invocation of a
class method. However, if the meta-variable value is a field, the expression is the
invocation of an instance method of that field’s type.
Modular static verification of aspects in such a setting involves, at least, three
challenges: syntactic typing, semantic typing and interference detection.
Syntactic typing. Static verification of uniformly generic aspects should ensure,
at least, that code using meta-variables is syntactically correct. For instance, one
would like to prevent substitution of classes where fields are expected and viceversa. This means that meta-variables need to be syntactically typed, that is every
meta-variable must have a type that determines the kind of syntactic entity from the
base language that may be substituted. Syntactic types can either be declared or
inferred from the definition of the predicates that are used to bind the respective
meta-variable values. Syntactic typing enables modular, static checking whether
values substituted for meta-variables in aspect effects will always produce legal
base language programs.
Meta-AspectJ (Zook et al., 2004) is the first external parameterization approach
that supports syntactically typed meta-variables, guaranteeing syntactic correctness
of generated code at compilation time. The type check is based on type inference.
Meta-AspectJ is fine-grained, its meta-variables range over all syntactic elements of
AspectJ. We know of no published generic aspect language with predicate-based
binding that supports syntactic typing.
Semantic typing. In addition, we need a second level of typing, in order to
determine also the base language type that a meta-variable will take on. We call this
the semantic type of the meta-variable because it refers to the type notion defined in
the static semantics of the base language. For instance, for our above invocation of
m() we need to know whether ?metaVar is guaranteed to be bound only to base
language elements whose base language type contains the method m().
22 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
Interference detection. Last but not least, as long as we know neither the
semantic nor the syntactic type of a meta-variable, let alone the precise entity to
which it will be bound at weave-time, aspect interference checking becomes much
harder than it already is in non-generic aspect languages. Performing modular interference analysis for generic aspects is a challenge that has not yet been addressed by
any published paper that we know of.
7. Generic Aspect Languages – A Quick Overview
In this section we categorize the generic aspect languages introduced in the
previous sections according to their position in the design space discussed so far.
Table 2 recalls the design dimensions for meta-variable binding (Section 5.1),
scope (Section 5.2) and domain (Section 5.3) and illustrates the design space
corresponding to the identified ‘optimal’ choices assuming an aspect language that
supports pointcuts, advice and introductions and a base language that has types,
methods, fields, statements and expressions. Every entry in the table names the
respective part of the design space. Because predicate-based binding is the optimal
choice in the binding dimension (see Section 5.1), uniform, fine-grained genericity
is the cumulated optimum in all three dimensions. Currently, the only proposal in
this category is (Rho et al., 2006).
The meta-variable kind dimension is not included in the table because we could
not identify a clear optimum. The effect granularity dimension has an optimum but
is not included since it is hard to visualize in a two dimensional space.
pointcut
Binding
External
parameterization
Predicate-based
binding
Scope
advice
introduction
Uniform external
parameterization
Uniform genericity
Domain
method / statement /
field
expression
Fine-grained external
parameterization
type
Fine-grained genericity
Table 2 Design space for meta-variable binding, scope and domain.
Table 3 categorizes existing generic aspect languages according to their position
in the design space discussed so far. The languages are grouped by their approach to
meta-variable binding (Section 5.1). The columns reflect the choices for scope
(Section 5.2), domain (Section 5.3) and typing (6). Only one approach supports syntactic typing. Static semantic typing is not yet supported by any of the surveyed
languages. Interference detection and resolution is not included in the table since we
found no related information in any of the reviewed papers.
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
23
8. Related Work
Our overview shows that there have been many, partly similar and partly highly
differing proposals for generic aspect languages. However, to the best of our
knowledge, there has been no comprehensive overview of the various proposals so
far. In particular, we know of no previous attempt to provide a definition of aspect
genericity that unifies all these approaches while still drawing a clear distinction to
non-generic aspect languages. While there is no immediately related work in this
sense, there are a number of interesting parallels of generic aspects in general to
work in the area of logic meta-programming, non-generic aspect systems, program
transformations, and dispatch in object-oriented programming.
Although AspectJ 5 uses the term “generic aspects” it is not a generic aspect
language according to any of the definitions given in Section 4. Without using
reflection it does not achieve effect variability and does not allow the use of type
variables in pointcut expressions and type patterns (AspectJ 2005). The “generic
aspects” of AspectJ 5 just enable use of the Java 5 genericity syntax within aspect
code.
The problem of hard couplings and dependencies between aspects is also
analysed in (Hassoun et al., 2003). In order to increase aspect reusability, Hassoun
and Constantinides propose a language framework based on run-time reflection.
This does not comply with our definition of genericity.
Various proposals in the context of aspect-oriented logic meta-programming
(AOLMP) have shown that some of the dependencies of aspects on base programs
discussed in Section 2 can be alleviated by the use of a logic-based pointcut language, e.g. (De Volder), (Gybels 2001), (Gybels et al., 2003). However, most
AOLMP research confines the scope of meta-variables to aspect predicates. The
resulting logic-based pointcut languages let aspect predicates implement powerful
analyses of base programs but do not achieve genericity. Aspect genericity requires
meta-variables to be used in aspect effects in order to enable effect variability.
Meta-variable
pointcut
External parameterization
SuperJ
9
LFP
9
Meta-AspectJ
9
Predicate-based binding
Better Generative
9
Programming
AspectC++
9
15
Scope
advice
Domain
Typing
method / statement / syntactic /
field
expression semantic
introduction
type
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9/ –
9
–
9
–
–
915
9
–
9
–
–
915
–
Trivial, because meta-variables can only be bound to types in this approach.
–
–
24 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
Carma
OReA
Sally
LogicAJ 1.x
LogicAJ 2
9
9
9
9
9
9
9
–
–
– 16
9
9
9
9
9
9
9
9
9
9
9
9
9
9
9
–
–
–
–
–
–
–
–
917
–16 / –
Table 3 Classification of existing generic aspect languages.
De Volder, Tourwé and Brichau (De Volder et al., 2000) and DeVolder (De
Volder) argue that a good aspect-oriented language provides mechanisms of
genericity, polymorphism and parameterization that would allow code to be reusable
and to adapt to different contexts. This is fully in line with our problem analysis.
There has been much work on program transformation systems and on their
relation to aspect-oriented programming. The following systems fall into this
category. On one hand, they cannot be considered generic aspect languages because
they don’t provide certain language features that are typical of aspects. On the other
hand, they are more expressive than aspect languages and are typically used to build
an aspect layer on top of them.
TyRuBa, de Volder’s Typed Rule Base language (De Volder 1998) introduces
logic meta-programming for Java programs. All block elements of the base program
are represented as quoted Java code within the TyRuBa rules. The quoted code logic
may contain meta-variables for types and identifiers. Both kinds of variables are
explicitly typed. Quoted code terms allow for easy manipulation of source code
templates. Using the logic inference-engine, it is possible to generate complete
programs by composing such templates. Quoted code terms can only be used as a
template for generating Java code but not in the query language.
SOUL, the Smalltalk Open Unification Language (Wuyts 2001, SOUL 2003), is
a reflective logic meta-programming system based on Smalltalk that incorporates
and extends the concept of quoted code terms of TyRuBa. Compared to TyRuBa,
SOUL achieves a much tighter and more dynamic integration of the logic inference
engine with the execution of quoted code terms, blurring the distinction between
code generation and code execution. Both can be seamlessly done ‘on the fly’, in
the typical style of dynamic languages. SOUL is the basis for the two generic aspect
languages Andrew / Carma (Gybels 2001) and OReA, (D’Hondt 2004, D’Hondt et
al., 2004), reviewed in Section 5 and 7. Both languages support generic advice (see
concluding discussion in 5.2).
Stratego/XT (Visser 2004, Visser 2002) is a framework for the development of
software transformations systems. It enables arbitrary transformations of source
16
17
Supported but yet unpublished.
Proposal in (Rho et al., 2006).
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
25
code, based on rewriting strategies. Transformations are described as conditional
term rewrite rules. The XT tools provide generators for parsers and source code
pretty printers. The rewrite rules transform the AST of the parsed source code,
supporting source patterns and meta variables. This is not quite the same as an
aspect language, although interesting analogies to aspects exist. A thorough
comparison of strategic and adaptive programming is presented in (Lämmel et al.,
2003). (Kalleberg et al., 2005) shows how to achieve aspect behaviour with
Stratego.
Castor and Borba (Castor et al., 2001) introduce JaTS, the Java Transformation
System, which allows pattern based program transformations. The structure of target
programs is described by base language code enriched by logic meta-variables that
act as placeholders. The transformation specification is described with another code
pattern containing meta-variables. The obvious advantage of code patterns is the
avoidance of the need to design and learn an artificial predicate language. The
disadvantage is the inability to specify conditions without implicitly specifying also
a certain textual order of elements. This makes it impossible to express recursive
conditions and very hard to express non-recursive ones that span multiple classes.
Spoon (Spoon 2006) is a program transformation tool based on the annotation
processing facilities and the type genericity of Java 5. Meta-variables that range
over types are translated to Java generic types, ensuring proper type-checking by the
Java compiler. This basic functionality is used to provide an annotation-based AOP
layer, Spoon / AOP (Pawlak 2005). It requires no language extension to Java,18
which is often an advantage in practice. A restriction that Spoon / AOP shares with
all approaches based on Java’s annotation facility is the inability to support finegrained aspects and fine-grained genericity.20 Since Spoon and Spoon AOP have
been released only recently21 and information about many details is still lacking, we
cannot precisely assess where this system fits in our taxonomy.
In Section 3 we have explained the analogy of generic aspects to dynamic
binding. That discussion implicitly assumed predicate-based meta-variable binding.
Achieving varying behavior via predicate based binding is strongly reminiscent of
the concept of predicate dispatching proposed for object-oriented languages by
Ernst, Kaplan and Chambers (Ernst et al. 1988). Doug Orleans (Orleans 2001)
shows that a simple extension to predicate dispatching can support separation of
cross-cutting concerns, which is one of the goals of aspect-oriented programming.
However, he notes that “another goal is the modularization of cross-cutting
18
Therefore it is not listed in our overview of generic aspect languages in Section 5 and 7.
The documentation at http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
specifies that annotation types “are restricted to primitives, String, Class, enums, annotations, and arrays of the preceding types”.
20
Annotations can only be added to declarations, not to statements or expressions (see
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html).
21
First public announcement and release in February 2006.
19
26 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
concerns, which is more than just separation; modularizing predicate dispatch
methods is an active area of research”. We claim that predicate-based meta-variable
binding in generic aspects is modularized predicate dispatch. We see it as the next
level of a unified theory of dispatch, stepping from locally inlined dispatch
predicates to extracted and modularized ones.
9. Conclusions
In this paper we have reviewed the needs, design options and technical challenges related to generic aspect languages. This includes a comprehensive overview of
the various proposals for generic aspect languages and a first definition of aspect
genericity that unifies all these approaches while still drawing a clear distinction to
non-generic languages.
We started from an analysis of the limitations of non-generic aspect languages
regarding, evolvability, expressiveness, conciseness, reusability and type safety. The
common cause of the identified problems is the reliance of aspects on concrete
names of base program entities and wildcards. This makes aspects highly
susceptible to changes of base code and prevents statically expressing contextdependent variation of aspect effects.
We defined generic languages as those that are able to express the desired
variation and identified the ability to use meta-variables in aspect effects as their
common technical essence.
Our review of existing and proposed generic languages revealed five basic
questions that language designers must consider when extending their aspect
language towards genericity:
− How
are the values of meta-variables provided (meta-variable binding)?
− Where can meta-variables be used (meta-variable scope)?
− Over which base entities can meta-variables range (meta-variable domain)?
− What kind of meta-variables are supported (meta-variable kind)?
− What actions can be performed on the base language entities referred to by
meta-variables (effect granularity)?
With respect to the first three design dimensions we were able to identify
predicate-based binding, uniform genericity and fine grained genericity as the most
expressive design options. Predicate-based binding frees programmers from having
to hand-code different aspect effect variants, in the same way as dynamic binding
frees object-oriented programmers from having to manually encode message
dispatch to different receiver types.
Reaching beyond the current state of the art we have discussed two main
challenges for future generic aspect languages: the development of modular static
analysis techniques for generic aspects and a combination of uniform and fine
grained genericity that goes beyond the first approach in (Rho et al., 2006).
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
27
10. Acknowledgements
We want to thank the anonymous referees of JFDLPA 2005 for thorough
proofreading of an early version of this paper and many encouraging but also
critical remarks that showed us how it could be improved. Stimulating discussions
with the participants and the excellent organization by Lionel Senturier made
JFDLPA a rewarding event. We are indebted to Laurence Duchien, Renaud Pawlak,
and Mireille Blay-Fornarino for an interesting day of mutual exchange of
experience at LIFL. Discussions with Maja d’Hondt, Kris Gybels and Johann
Brichau helped us understand better how SOUL, Carma and OreA relate to uniform
genericity. Our numerous meetings and sometimes deeply philosophical discussions
with Stefan Hanenberg about the very essence of aspects and the relation of Sally to
LogicAJ have been challenging, enlightening and fun. Our work benefited from its
embedding in the ideal environment of senior guidance by Prof. Armin B. Cremers
and enthusiastic help by our colleagues and students in the ROOTS group – Daniel
Speicher, Malte Appeltauer, Mark Schmatz, Lukas Degener are just the tip of the
iceberg. Last but not least, we are grateful to Julia Lawall for her knowledgeable
and thoughtful shepherding. Her numerous up-to-the-point comments and
constructive suggestions have considerably shaped this paper.
11. References
Aksit M., Bergmans L., Vural S.: “An Object-Oriented Language-Database Integration
Model: The Composition Filters Approach”, ECOOP 1992 proceedings, SpringerVerlag, 1992.
Alvarez J.: “Parametric Aspects: A Proposal”. Proc. of ECOOP'2004 Workshop on
Reflection, AOP and Meta-Data for Software Evolution, March 2004.
The AspectJ Team: The AspectJ 5 Development Kit Developer's Notebook,
http://www.eclipse.org/aspectj/doc/released/adk15notebook/generics-inAspectJ5.html,
Feb. 2005.
Castor F., Borba P., “A Language for Specifying Java Transformations” V Brazilian
Symposium on Programming Languages, Curitiba, Brazil, 23rd-25th May 2001, pages
236-251.
Chiba S., “Load-time structural reflection in Java”, in ECOOP 2000 proceedings, LNCS
1850, pp. 313–336, Springer-Verlag, 2000.
Chiba S., Nakagawa K.: “Josh: An Open AspectJ-like Language”, in AOSD 2004
Conference Proceedings, pp. 102-111, ACM Press, 2004.
Compose* Homepage: http://composestar.sf.net/
Demeter/Java Homepage: http://www.ccs.neu.edu/research/demeter/releases
de Volder K., Type-Oriented Logic Meta Programming, Ph.D thesis, Vrije Universiteit
Brussel, 1998, Brussels.
de Volder K.: Type-Oriented Logical Meta Programming, PhD thesis, Vrije Universiteit
Brussel, Belgium, 1998.
28 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
de Volder K.: “Code Reuse, an Essential Concern in the Design of Aspect Languages?”,
Workshop on Advanced Separation of Concerns, Budapest, 2001.
de Volder K., Tourwé T., Brichau J.: “Logic meta-programming as a Tool for Separation of
Concerns”. In ECOOP 2000 International Workshop on Aspects and Dimensions of
Concerns", 2000.
D’Hondt M., “Hybrid Aspects for Integrating Rule-based Knowledge and Object-oriented
Functionality”, PhD Thesis, Vrije Universiteit Brussel, May 2004.
D’Hondt M., Jonckers V., “Hybrid Aspects for Weaving Object-Oriented Functionality and
Rule-Based Knowledge”, in AOSD '04: Proceedings of the 3rd international
conference on Aspect-oriented software development, Lancaster, UK, ISBN 1-58113842-3, http://doi.acm.org/10.1145/976270.976287, p. 132-140, ACM Press, New York,
NY, USA, 2004.
Eclipse
Platform
Naming
Conventions,
http://www.eclipse.org/documentation/
html/plugins/org.eclipse.platform.doc.isv/doc/reference/misc/naming.html, June 2001.
Ernst M., Kaplan C., Chambers C.: “Predicate Dispatching: A Unified Theory of
Dispatch.” In: E. Jul (ed.): ECOOP'98 - -Object-Oriented Programming (12th
European Conference; Brussels, Belgium, July 1998, Springer-Verlag, LNCS 1445, p.
186-211, 1988.
Filman R. E., Friedman D. P.: “Aspect-Oriented Programming is Quantification and
Obliviousness”, Workshop on Advanced Separation of Concerns, OOPSLA 2000,
October 2000, Minneapolis.
Gamma E, Helm R, Johnson R, Vlissides J.: Design Patterns: Elements of Reusable ObjectOriented Software, Addison-Wesley, 1995.
Gybels K., “Aspect-Oriented Programming using a Logic Meta Programming Language to
express cross-cutting through a dynamic join point structure”, Licentiate's Thesis
Dissertation, Aug 2001
Gybels K, Brichau J, “Arranging Language Features for More Robust Pattern-based
Crosscuts”, Proceedings of the 2nd International Conference on Aspect-Oriented
Software Development (AOSD), Boston, MA, March 17-21, ACM Press, 2003
Hassoun Y., Constantinides C., “Considerations on component visibility and code
reusability in AspectJ”. In Proceedings of third German Workshop on Aspect-oriented
Software Development of the German Informatics Society (AOSD-GI 2003),
http://dawis.informatik.uni-essen.de/site/events/GI_AOSD_2003/index.html, p. 33-38.
Hannemann J., Kiczales G., “Design Pattern Implementations in Java and AspectJ”,
Conference on Object-Oriented Programming Systems, Languages and Applications,
OOPSLA 2002, November 4-8, 2002, Seattle, Washington, USA. SIGPLAN Notices
37(11), November 2002, ACM Press, pp. 161-173.
Hanenberg, S.; Unland, R.: Parametric Introductions, 2nd International Conference of
Aspect-Oriented Software Development (AOSD), Boston, MA, March 17-21, ACM
Press, 2003, pp. 80-89.
Hanenberg S, Unland R., Oberschulte C., “Refactoring of Aspect-Oriented Software”, Net
ObjectDays 2003, Erfurt, Germany, September 2003.
Harbulot B, Gurd J. R., “Using AspectJ to Separate Concerns in Parallel Scientific Java
Code”, Proceedings of 3rd International Conference on Aspect-Oriented Software
Development (AOSD), March 2004.
A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
29
Harbulot B, Gurd J. R., “A Join Point for Loops in AspectJ”, Proceedings of FOAL 2005 –
Workshop on Foundations of Aspect Languages, collocated with 4th International
Conference on Aspect-Oriented Software Development (AOSD.05), March 2005.
Hassoun Y., Constantinides C, “Considerations on Component Visibility and Code
Reusability in AspectJ”, Proceedings of third German Workshop on Aspect-Oriented
Software Development, March 4-5, 2003, Essen, Germany, p. 33-36,, University of
Duisburg-Essen.
Rajan H., Sullivan K., "Generalizing AOP for Aspect-Oriented Testing", In the proceedings
of the Fourth International Conference on Aspect-Oriented Software Development
(AOSD 2005), 14-18 March, 2005, Chicago, IL, USA, ACM Press, 2005.
Kalleberg K. T. and Visser E.. Combining Aspect-Oriented and Strategic Programming. In
H. Cirstea and N. Marti-Oliet, editors, Workshop on Rule-Based Programming
(RULE'05), Electronic Notes in Theoretical Computer Science, Nara, Japan, April
2005. Elsevier Science Publishers. http://archive.cs.uu.nl/pub/RUU/CS/techreps/CS2005/2005-030.pdf
Kiczales G., Hilsdale E., Hugunin J., Kersten M., Palm J., Griswold W., “An Overview of
AspectJ”, Proceedings of ECOOP 2001
Kniesel G., Rho T., “Generic Aspect Languages – Needs, Options and Challenges”,
Proceedings of JFDLPA 2005, 2ème Journée Francophone sur le Développement de
Logiciels Par Aspects, Lille, Sept. 15, 2005, http://www.lifl.fr/jfdlpa05/kniesel.pdf
Kniesel G., Rho T., Hanenberg S., “Evolvable Pattern Implementations need Generic
Aspects”, ECOOP 2004 Workshop on Reflection, Aspects and Meta-Data for Software
Evolution, Oslo, June 2004, http://roots.iai.uni-bonn.de/research/logicaj/ publications
Lämmel R., Visser, E., Visser J., “Strategic Programming Meets Adaptive Programming”,
Proceedings of Aspect-Oriented Software Development (AOSD'03), March 2003,
Boston, USA, pp. 168-177, ACM Press, 2003.Loughran N, Rashid A., “Framed Aspects
: Supporting Variability and Configurability for AOP”, International Conference on
Software Reuse 2004 (ICSR-8), Madrid, Spain, July 2004
Mackinnon T., Freeman S., Craig P., “Endo-Testing: Unit Testing with Mock Objects”,
Proceedings of eXtreme Programming and Flexible Processes in Software Engineering
- XP2000, May 2000.
Orleans, D., “Separating Behavioral Concerns With Predicate Dispatch, or, If Statement
Considered Harmful”, position paper at OOPSLA 2001 Workshop on Advanced
Separation of Concerns in Object-Oriented Systems, http://www.cs.ubc.ca/
~kdvolder/Workshops/ OOPSLA2001/submissions.html
Ossher H., Tarr P., “Using multidimensional separation of concerns to (re)shape evolving
software”, Communication of the ACM, 44 (10), 2001, pp. 43-50.
Ossher H., Tarr P., “Hyper/J: Multi-dimensional separation of concerns for Java”,
Proceedings of ICSE 2001, IEEE Computer Society.
Pawlak R. “Spoon: Annotation-Driven Program Transformation - The AOP Case”. First
Workshop on Aspect-Orientation for Middleware Development at Middleware 2005,
Grenoble, France. http://www.lifl.fr/~pawlak/papers/Pawlak_AOMD05.pdf
Pinson L., Wiener R., “Objective-C: object-oriented programming techniques”. ISBN:
0201508281, Addison-Wesley, 1991.
30 A Definition, State of the Art Overview and Taxonomy of Generic Aspect Languages
Rho T., Kniesel G., Appeltauer M., “Fine-Grained Generic Aspects”, Proceedings of
FOAL 2006 – Workshop on Foundations of Aspect-Oriented Languages in conjunction
with 5th International Conference on Aspect Oriented Software Development
(AOSD.06), March 20-24, 2006, Bonn, Germany.
Rho T., Kniesel G., “Uniform Genericity for Aspect Languages”, Technical Report IAI-TR2004-4, Computer Science Department III, University of Bonn, December 2004.
Silaghi R., Strohmeier A., “Better Generative Programming with Generic Aspects”. 2nd
OOPSLA 2003 Workshop on Generative Techniques in the context of Model-DrivenArchitecture. Technical Report IC/2003/80, Swiss Federal Institute of Technology in
Lausanne, Switzerland.
Sihman M., Katz S., “Superimpositions and Aspect-oriented Programming”, The Computer
Journal, 46 (5), pp. 529-541, doi:10.1093/comjnl/ 46.5.529, British Computer Society,
2003.
SOUL homepage, http://prog.vub.ac.be/research/DMP/soul/soul2.html, accessed Feb. 2006
(last update October 22, 2003)
Homepage of Spoon and Spoon/AOP http://spoon.gforge.inria.fr/ (Accessed Feb. 2006).
Spinczyk O., Gal A., Schröder-Preikschat W., “AspectC++: An Aspect-Oriented Extension to C++”, Proceedings of the TOOLS Conference Pacific 2002, Sydney, Australia,
February 18-21, 2002
Lohmann D., Blaschke G., and Spinczyk O., “Generic Advice: On the Combination of AOP
with Generative Programming in AspectC++”. In Proceedings of GPCE'04, October
24th-28th, 2004, Vancouver, Canada, LNCS 3286, p. 55-74, Springer Verlag 2004.
Tourwé T., Brichau J., Gybels K., “On the Existence of the AOSD Evolution Paradox”,
SPLAT Workshop, Boston, AOSD 2003.
StrategoXT homepage, http://www.stratego-language.org/Stratego/StrategoXT, accessed
Feb. 2006 (last update Nov. 17, 2002)
E. Visser. Program Transformation with Stratego/XT: Rules, Strategies, Tools, and Systems
in StrategoXT-0.9. In C. Lengauer et al., editors, Domain-Specific Program
Generation, volume 3016 of Lecture Notes in Computer Science, pages 216-238.
Spinger-Verlag, June 2004. See also http://www.cs.uu.nl/research/techreps/UU-CS2004-011.html and http://www.stratego-language.org/Stratego/StrategoXT.
Wampler D., “The Challenges of Writing Reusable and Portable Aspects in AspectJ:
Lessons from Contract4J”. In Chapman M., Vasseur A., Kniesel G. (Eds): International
Conference on Aspect Oriented Software Development (AOSD 2006) – Industry Track
Proceedings, March 20-24, 2006, Technical Report IAI-TR-2006-3, ISSN 0944-8535,
Institut für Informatik III, Universität Bonn, Germany, 2006.
Windeln T., „LogicAJ – eine Erweiterung von AspectJ um logische Meta-Programmierung“
(in German), Diploma thesis, CS Dept. III, University of Bonn, Germany, August 2003.
Wuyts, R., “A Logic Meta-Programming Approach to Support the Co-Evolution of ObjectOriented Design and Implementation”, Ph.D. Thesis, Vrije Universiteit Brussel, 2001.
Zook, D., Huang, S. S., and Smaragdakis, Y., Generating AspectJ Programs with MetaAspectJ. In Proceedings of GPCE'04, LNCS 3286, pages 1-19. Springer-Verlag, 2004.