I would like to thank my advisor, Karl Lieberherr for
entertaining my interests in this research and giving me the opportunity to
contribute to the aspect oriented programming community. He has always been
supportive in giving advice and direction for this thesis. I would also like to
thank my other brothers-in-arms in the field of aspect oriented programming,
Doug Orleans, Pengchang Wu, Johan Ovlinger, and Therapon Skotiniotis for their
helpful comments, questions and suggestions. This thesis would not have been
possible if Mitch Wand were not willing to read and review my small
contribution to the aspect oriented programming field. Lastly, this thesis
would never have been conceived without the faculty, students and
administrators of the School of Computer Science at Northeastern University.

Aspect Oriented Programming (AOP) is becoming prominent in
the field of Computer Science. The tools that allow programmers to use AOP
methodologies to improve their productivity have been around for quite sometime.
However, there has not been much research into the basic concepts used in these
methodologies. We bring this to the attention of the research community by
attempting to understand the fundamental concepts behind these aspect oriented
programming tools, how those concepts are applied in different aspect oriented
programming tools, and create a coherent model of AOP concepts that would allow
us to make informed decisions about how these concepts could be applied in
novel ways.

First, we will investigate the fundamental concepts that
are evident in AspectJ [9
Kiczales2001], DemeterJ [14
DemeterJ], DJ [15
DJ], and Fred [1
Orleans02]. These tools use the concepts of predicated
execution, advice and traversal in different ways. AspectJ uses predicated
execution and advice concepts on a program’s control flow graph. Fred attempts
to define the program’s control flow graph using the predicated execution and
around concepts. DemeterJ and DJ use traversals and advices on an object graph.
Some of these tools have been around for years, but we still do not understand
how these tools and their concepts are related. We will investigate these
relations and determine their usability for AOP tool analysis.

One way to explore these relations is to attempt to
implement concepts from one language to another. The simple implementation of
factorial function written in Fred and AspectJ with branches in Figure 1, shown below, illustrates how one may apply the
concepts from branch oriented programming from [1 Orleans02] using AspectJ.

In this simple example that implements the factorial
function, the first line defines a message named fact. The second Scheme line
defines a branch that handles the case where the first argument is equal to
one. The last line defines the default branch that handles the case where the
first argument is not equal to one. In this manor, a programmer would describe
each case of what happens for this particular message.

We translate the Fred implementation of the Factorial
Example in Figure 1 to AspectJ as shown in Figure 2. In this AspectJ implementation, the FactClass is empty and the
factorial method is defined within the FactExample aspect. The two pointcuts and the
corresponding around advices are the two possible branches for the method fact().

The close correspondence between the Fred implementation
and the AspectJ with branches implementation of the factorial function is very
clear in the Factorial Example. There is an one to one correspondence between
the two implementations. This relatively simple translation process opens the
possibility for implementing Fred concept using AspectJ.

In order to find more of these types of concept
applications, a consistent view that one can take to make all of the AOP
approaches clearly would be useful. One way to accomplish this is to view these
ideas as abstracting the different parts of a program into graphs. The instance
of nodes and edges in each AOP tool are different, but the basic concepts are
same. This allows us to think of all of the different things that one can do
with graphs, traversals, mapping, grouping of nodes, subgraphs, etc. If we
apply these graph concepts to the different graphs evident within programs that
is consistent with the different implementations of aspect oriented programming
tools, we maybe able to find possibilities for future development of those
aspect oriented programming tools.

This idea of abstracting AOP concepts into generic graphs
will be explored by attempting to implement an idea from a graph operation to
different tools. In [10
Kiczales et. al], the authors present an example in which one wants to
have access to some node or context that the entity doing the traversal has
seen before. In AspectJ, you would use the pointcut to specify the specific
join point that you want to expose to the join point encountered later in the
traversal of the dynamic call graph. In the example in [10 Kiczales et. al], the Caller
c is exposed to all of the Workers w by the pointcut shown in Figure 3.

When the NodesOf
operator is applied to a graph, it returns all the nodes in the class graph.
Given a strategy, it would return all of the nodes that are in the traversal
graph that is the result of applying the strategy to a class graph. It would be
useful to extend AspectJ with strategies and NodesOf to define AspectJ type patterns more
flexibly.

In DJ, one would use the ContextVisitor to expose the stack of objects that
the visitor has encountered thus far in the object graph during a traversal of
the object graph. In both of these cases, the program can expose parts of the
graph that was traversed earlier during the current traversal. This is a
fundamental concept that is evident in AspectJ, DemeterJ and DJ. This thesis
will attempt to find and categorize these types of commonalities between AOP
tools and integrate them into a consistent view of aspect oriented programming
concepts.

The relevant type of experiments for this thesis include
using AspectJ to implement the concepts from other AOP tools, integrating
AspectJ and AP Library, and implementing a real-world application using the
tool from the integration work. The purposes of the first experiments should
expose the relationships between AspectJ and other AOP tools. Some examples of
these experiments have already been presented. The next type of experiment,
integrating AspectJ and AP Library, is designed to find out how well these
tools interact with each other. The last experiment will measure the
effectiveness of the integration experiment. All of these experiments have one
purpose, to direct the shaping of the consistent view of aspect oriented
programming that integrate concepts from AspectJ and Demeter.

The consistent view of aspect oriented programming that
will be shaped by the proposed experiments should be based on abstracting
aspect oriented programming concepts into graphs and the manipulation of these
graphs as mentioned. This new view should be a starting point for a new way of
analyzing aspect oriented tools, i.e. aspect oriented tool analysis. This new
type of analysis should expand the current understanding of aspect oriented programming
tools and concepts that will lead to future development of those tools and
concepts.

This master's thesis started with vague notions that there
have to be better ways of expressing what a user would want the computer to
accomplish on behalf of the user. Because of this notion, a quick survey of
latest aspect oriented programming languages were taken from such source as [22 CACM]. The languages surveyed were DemeterJ [14 DemeterJ], DJ [15
DJ], Fred [1
Orleans02], and AspectJ [9
Kiczales2001]. DemeterJ and DJ were developed at Northeastern
University and were a natural selection as a graduate student of Northeastern
University. Doug Orleans, from Northeastern University, developed Fred as part
of his Ph.D. Dissertation and its close ties with AspectJ made it a prime
candidate for this research. AspectJ was selected for its popularity among the
AOP community. These four AOP Tools were determined to be the tools that will
be used in our experimentation and analysis.

However, we will not present the idea of cross cutting
concerns and the reason why this is important in AOP. Much of this has been
discussed is many papers and magazine articles. If you would like a quick
overview of the issues in AOP, then one should read the October, 2001 issue of
the Communications of the ACM[22
CACM].

Fred [1
Orleans02], developed by Doug Orleans, is a language that
integrates aspect oriented programming and predicate dispatching and it is
implemented in [13
MzScheme]. The main components in Fred are message, branch, and
decision point. In order to simplify these terminologies, we will map these
components to components from functional programming. A message maybe thought
of as a function. Defining a message is equivalent to declaring a function.
Then, a branch is analogous to a function call. It is actually more complicated
than that, but we will just use this analogy for simplicity sake. The decision
point is where a decision is made about which branch should be invoked. This
requires that a predicate is associated with each branch. Fred follows the
branch that satisfies Fred's rules about predicates in cases where multiple
branch predicates are true.

In order to understand how this works, we will present a
simple factorial example. In Fred, a programmer defines a message by calling
the function define-msg.
In Figure 6, the first statement defines a message called fact. Next, we define some
branches for this message fact.
We will handle the base case where the first argument is equal to one. This is
expressed in Fred in Figure 6 by the second MzScheme statement. We use the function
define-branch to
define a new branch that executes its body when the message is equal to fact and the first argument
is equal to one. Within this body, we return one, which is what would happen if
we called the function factorial with one as the argument. Next, we handle the
recursive case by defining another branch as represented by the third MzScheme
statement in Figure 6. It defines a branch that is invoked when the message
is fact. In the body
of the branch, we make a recursive call to fact with x - 1 as the argument and multiply that
by x. Then, we return the result of that multiplication as shown in Figure 6.

There is some complex situation regarding the predicates
for the two branches. The predicates for both of these branches maybe true for
the case (fact 1).
What does Fred do in this case? Fred determines the more specific predicate and
invokes that branch. Thus, when (fact
1) is encountered, Fred invokes the first branch instead of the second
branch. The rationalization for this decision is that the first predicate is
more specific than the second predicate, i.e. the second predicate is always
true when the first one is true, but not vice versa. Thus, Fred always selects
the more specific predicated branch. Therefore, the second branch is invoked
for all other cases for the call to the function fact. This gives us the behavior that we want from
Fred for the implementation of the factorial function.

Next, we will introduce Demeter concepts and how these
concepts are implemented in DemeterJ and DJ. The main concepts of Demeter are
class graph, strategy, visitor, and advice. The class graph is the schema of
the data structures used within a program. It defines all the possible
manifestations of object graphs created during an execution of a program. A
strategy is a direction on how to traverse the object graph. Strategies such as
"from Company to Employee" and "from Top via Middle to
Bottom" combined with a class graph yields a traversal graph. This
traversal graph is a sub-graph of the class graph that includes all possible
paths defined by the given strategy. The visitor in Demeter is the one that
traverses the traversal graph. It has advices that are invoked for particular
types of nodes in the traversal graph. Thus, a task within Demeter requires the
programmer to specify at least the class graph, strategy and visitor. This
Demeter process is shown in Figure
7.

The way in which the programmer specifies the three
components class graph, strategy and visitor is different for DemeterJ and DJ.
In DemeterJ, the class graph is described within the class dictionary. The
syntax of the class dictionary is a modified Backus Naur Form (BNF) that allows
programmers to describe the class graph efficiently. The visitor is declared
within the Class Dictionary as well, since it is implemented as a Java class.
The strategy and the definition of the visitor are specified in behavioral
files.

We will go through the Basket Example to illustrate how
DemeterJ is used to implement programs. The class graph of the example is shown
in Figure 8. The class, Basket, may contain three objects, one of
type Pencil and two of Fruit. A Fruit may also be an Orange. Every Fruit has a
reference to the class Weight, which has an integer.An Orange has a reference to a Color class, which is represented
by a String class. In this example, we will count the integers in the class Weight
that are contained in a Basket.

In DemeterJ, we first need to specify the class graph in a
class dictionary. We specify all of the relationships within the class graph
using the modified BNF as shown in Figure
9. The identifier on the left is the class being
defined. The "=" can be interpreted as "has-a" relationship
in object oriented programming terminology. The identifiers within
"<" and ">" are labels for these "has-a"
edges within the class graph. The "is-a" relationship is defined by
the ":" symbol. The "common" keyword indicates that the
class Fruit has a "has-a" relation ship with Weight with label
"w". In the classic case of inheritance, all of the classes that have
"is-a" relationship with Fruit will inherit this "has-a"
relationship. Lastly, the period ends the sentence within the class dictionary.

Because of the way DemeterJ implements alternation classes
as abstract classes, we need to change the way inheritance is expressed between
Fruit and Orange. If want the class Fruit to be a concrete
class instead of an abstract class, we need to use "extends" instead
of the alternation with ":". The modified class dictionary is shown
in Figure 10. The ":" for Fruit has changed to "=" and the string
"extends Fruit"
was added to the definition of Orange.
This signifies that Orange
inherits from Fruit.

Next, we need to specify the strategy for the traversal.
Since we want to count each of the integers in Weight objects within the Basket, we need to traverse from the Basket class to Weight. Therefore, the
strategy becomes "from Basket to Weight". The resultant traversal
graph from applying this strategy to the Basket Example class graph is shown in
Figure 11.

Now that we have a traversal graph that we want to
traverse, we need define this traversal and visitor that will count the
integers stored within each Weight object. We accomplish this by defining the
traversal and the visitor in a DemeterJ behavioral file. However, we have not
actually declared the visitor class in the class dictionary. We may accomplish
this by adding the line shown in Figure
12 to the class dictionary. It defines a class CountWeightVisitor with a
data member variable total
of type int.

Now, we are ready to define the traversal and the visitor
in the behavioral file. When defining the traversal, you have to first specify
the starting node of the traversal in our strategy, i.e. Basket. Then, we type
in "{" to start the scoping of behavior to be added to the class
Basket. We start the definition with the key word "traversal" then
the name of the traversal. Next, we have the visitor name with parenthesis
around it. Then, another "{" to start specifying the rest of the
strategy. We add the keyword "to" and then the destination, Weight.
We are finished with this definition of a traversal, so we signifying the end
of the strategy with ";" and "}". Then close the scope of
the class Basket with another "}". This traversal definition is shown
in Figure 13.

The definition of the CountWeightVisitor is similar to the traversal. We
start with the scoping by having the name of the Class CountWeightVisitor and "{". Then,
we specify two methods and an advice. The two methods are start() and getReturnValue(). The state() method initializes
the running total of the weights, while getReturnValue() returns the total weight counted.
The definition of these methods looks exactly like Java code, except for the
double curly-braces. This is used to signify pure Java code to the DemeterJ
weaver.

The advice specified within CountWeightvisitor is a before advice. It is
executed before visiting all the "children" of the node Weight. Within the advice,
there is a keyword "host", which is similar to "this" in
Java. Instead of the current object, it refers to the object of type Weight we are currently
visiting. The accessor method get_i()
in the advice is generated automaticallyfor us by DemeterJ. This advice is executed every time we encounter an
object of type Weight
and add the integer within Weight
to the total.

This does seem like a lot of work, so the designers of
DemeterJ created a way of specifying the strategy and the visitor at the same
time using in lined visitors. This is useful for small traversals, such as
accessor traversals that retrieve one object from a complicated object graph.
In this method, we do not need to declare the visitor as a class in the class
dictionary. This usage of the in lined visitor is illustrated in Figure 14 below.

The body of the method getTotalWeight looks almost exactly like the CountTotalWeight visitor.
The difference is that the method has the string "to Weight" to
specify the strategy "from Basket to Weight". Next, we have the
statement "{{ in total=0;}}", which defines and sets the running total
of the weights for the in lined visitor. We specify the advice similar to the
one in Figure 12. Then, we specify the return value total and the
return type to be int.
This in line visitor is very useful if you do not have complicated visitors
that you want to reuse.

Another significant feature of DemeterJ is its ability to
generate a parser for the class dictionary. As an example, we will convert the
class dictionary in Figure 9. We will convert it in a way that the grammar will
specify a language that reads in XML as input and creates an object graph. In
order accomplish this task, we add the appropriate XML tags around the
statements in the class dictionary as shown in Figure 15.

This parser generation feature of DemeterJ is significant,
because it allows programmers to add minimal amount of strings to specify an
input file language. DemeterJ also generates default visitors and traversals to
print and display the object graph parsed from an input file. This maybe used
for internal testing of the application being developed.

The next implementation of the Demeter Concepts is DJ.
This is a Java library that allow programmers to specify the class graph,
strategy, and visitor through a Java API. This is useful for programmers that
do not want to learn a new language to reap the benefits of the Demeter
Concepts. Programmers may include the AP Library in their program and obtain
the full capabilities of these concepts.

As in DemeterJ, DJ allows programmers to specify the class
graph. While DemeterJ uses class dictionaries, DJ uses Java Reflection to
construct a representation of the class graph. DJ provides an API to access
this functionality. The class ClassGraph
in the AP Library [16
APLib], allows programmers to obtain the class graph and use
it to traverse object graphs.

The actual specification of the class graph is in pure
Java as shown in Figure 16. The class ClassGraph allows the programmers to access the class graph and
the relevant methods. Thus, the definition of the class graph is accomplished
by the usual method of specifying classes and their definitions in Java. The
DJ's ClassGraph class provides the reference to the class graph defined by the
programmer. The Java code to specify the Basket Example class graph in Figure 8 is shown in Figure
16. It uses the usual method of data member variables
for "has-a" relationships and uses the "extends" keyword
for the "is-a" relationships. This Java code would have been
generated from the class dictionary in DemeterJ.

Obtaining the reference to this class graph is simple as
calling the constructor to the class ClassGraph as shown in Figure
17. DJ uses Java Reflection to construct the class graph
representation from the current running program. This allows programmers to
adapt their existing applications to use DJ.

Next, we define a visitor to count the weights within the
Basket as shown in Figure 18. The Java code is very similar to the definition of
the visitor in DemeterJ in Figure
13, except for minor syntactic differences. Therefore,
DemeterJ's syntax for the behavioral files is very close to their Java
equivalents.

Lastly, we need to invoke the traversal with the object
graph, strategy and visitor. The object graph is created by calling constructors
for the classes in the class graph. Also, we need to instantiate an instance of
the CountWeightVisitor
to visit the nodes in the object graph. Then, we call the method traverse() for class ClassGraph with the
"root" of the object graph, the strategy and the visitor. The actual
Java code showing how all of these components come together is shown in Figure 19.

The last AOP tool that we will be discussing is AspectJ.
It extends the Java Language to allow programmers to express crossing cutting
concerns. The major feature of AspectJ that we are concerned with are
introduction, join point, pointcut, and advice. Introductions allow programmers
to define classes, data members, inheritance relationships and methods within
another scope, besides the scope of the class. Thus, it empowers the
programmers to organize the code in a more flexible manner. Join point allows
programmers to specify a point within the execution of an application. Pointcut
specifies a set of join points within an application. Finally, the advice is
executed when the pointcut associated with it holds true. This type of
description of programs using join points is called a Join Point Model (JPM).

We will show these concepts in action with the Basket
Example. As with other examples, we need to present how the data structures,
i.e. the class graph, is specified. We may accomplish this as with the DJ
example using Java, however will use AspectJ's introduction feature to
demonstrate the power of AspectJ.

First, we define empty classes as shown in Figure 20. Then, we use the AspectJ introductions to introduce
the data members and the inheritance relationship as shown in Figure 21. There are no requirements for the location of these
introduction statements, except that they have to be within the scope of an
aspect. These aspects allow the programmer to organize the different aspects of
an application and all of the AspectJ extensions to Java are within the scope
of these aspect statements.

In Figure
21, the declare parent statement allows programmers to
introduce has-a relationships to their class graph. The data members declared
in the aspect have to include the type and the variable name. Thus, all of the
data members are of the form “type classname.variablename;”. This give all of
the information that the AspectJ compiler needs.

Next, we define constructor and accessor methods for the
classes within the Basket Example. In Figure
22, we accomplish this by introducing the constructors
by defining the method new()
for the classes and accessor method for Weight's integer, i. Note that we need to type more, because we need
to specify the scoping for each method introduced by specifying the name of the
class.

Now, we specify the code to count the integer values within
Weight objects in Figure 23. This specification is similar to the CountWeightVisitor for the
Demeter implementations. We declare a static integer to be used within all of
the methods to count the integers within Weight objects. We define the method getTotal() for Basket, Fruit, and Weight. These methods are
used to traverse to the Weight
objects.

In order to add the weights, we have declared a pointcut weightpc(). It specifies
the join points of all method calls to getTotal() and the target of the method call is to
an object of type Weight.
The after advice is executed every time the pointcut holds true. The
"arguments" to the pointcut and the advice allows data passing from
the references accessible at the join point to the advice body. We did not have
to use the pointcut and the advice, but we wanted to demonstrate a simple use
of these AspectJ features. Lastly, we added a before advice to initialize the
weight counter total.

The CountWeight
aspect has the same semantics as the implicit visitor in Figure 14. The methods getTotal() defined for Basket and Fruit are generated by DemeterJ. While in DJ, the
call to traverse()
takes care of this function.

From this example, we can see that in order to use the
join points, we need to have some Java code to have meaningful pointcuts. From
this we can create a conceptual model with two different "planes" of
execution as shown in Figure
25. One plane is the original Java program and the other
is where the bodies of advices in AspectJ are executed. That advice body, in turn,
may contain method calls to the "Java Plane." In this manner, we can
have "ping-ponging" back and forth between the two planes of
execution as shown in Figure
25.

We have introduced the AOP tools Fred, DemeterJ, DJ and
AspectJ. Examples of how these tools are used to specify a program have been
presented. It is important to understand the fundamental concepts behind these
tools for our exploration of the aspect oriented programming tools concepts. In
this exploration we will attempt to understand the strengths of these concepts
in the subsequent chapters.

In the following chapters, we will translate some examples
of Fred to better understand the semantics Fred. Then, we will attempt to
translate Demeter traversals to AspectJ and explore the possibility of
translating AspectJ programs to DemeterJ. This leads us to the analysis of Join
Point Model and the "Program as a Journey" metaphors. Next, we
introduce DAJ that integrates Demeter concepts with AspectJ. Because of the
relatively poor performance of DJ compared to DemeterJ, we analyze the
performance of DAJ relative to DJ and DemeterJ. From the discussions and
experiments presented, we apply a graph theoretical view to develop an analysis
methodology for aspect oriented programming tools with a Four Graph Model of
Programs (4GMP). Finally, we conclude with conclusions and suggestions for
further research.

Fred [1
Orleans02] is an extension to Scheme that allows programmers to
program incrementally using decision points developed by Doug Orleans. We will
attempt to translate some example code to a graphical notation and AspectJ, as
a starting point of this thesis. The translation process from Fred to a
graphical notation will bring out implicit semantics within the language, while
translating it to AspectJ will allow us to explore the power of AspectJ.
Because this is an exercise to learn about Fred's semantics, it is not
necessary to create a perfect graphical notation for Fred.

The idea behind the graphical notation for Fred arose out
of the fact that many people like to visualize their programs. Languages such
as UML arose out of this need for visualization of programs. The purpose of
this exercise is to discover the semantics of Fred that is not immediately
apparent.

In order to describe Fred, we have broken down what
actually happens within each function, shown in Figure 26. We have a circle with a function name to represent
the function. This is a node within our graphical representation. Next, we need
a way to connect these nodes together and we use the arrow to signify a branch
or a function call. Since each branch may have a predicate, a Scheme style
predicate without the parenthesis is one of the labels for the branch. We also
need to deal with parameters and return values. A variable with a box around it
signifies parameters passed to the function. The dollar sign with a box around
it signifies the value returned from a function call. This is used for the
branch that is visited after a return from the original branch. You can think
of this as a "side trip" to another node during the return trip.
Lastly, we need something to signify that the trip has ended and it should
start the return trip. Therefore, a termination branch was added.

As an example, we have translated a simple factorial
example to the graphical notation in Figure 2. The result of this translation
process is shown in Figure 27. The Scheme expressions are shown on the left and the
graphical equivalent is shown on the right. The first Scheme expression, (define-msg fact) defines a
node named fact. The second defines the termination branch on the left with the
predicate (= x 1). If
this predicate is true, the "traveler" should stop and start its
return trip. The last Scheme expression specifies the branch on the right.
Since, this is a recursive function, this branch goes to the function fact back
to itself with (- x 1) as the parameter. The return branch from this recursive
function call goes to the multiplication function with the parameters x and the
value returned from the original branch. This is how we translate code written
in Fred to the graphical notation.

From this translation process, we can make several
observations. First, this simple version of Fred does not have any mechanism to
group the branches that are associated with a message. Fred associates the
branches with messages by using the predicates such as (eq? (dp-msg dp) fact). Because of this
feature, a programmer can reuse branches for different messages or nodes by
or'ing the message name matching predicates.

Another ramification of this feature is that the
programmer is able to place the branches anywhere. There is no requirement or
scoping of the branches as you would in other programming languages such as
C++. Thus, it is up to the programmer to organize these branches and messages in
anyway that is optimal for a particular application.

The second observation to make is that the mechanism to
describe the return value is quite clumsy in the graphical notation. It is not
very intuitive and it is hard to understand what is happening. This is because
the ordering of the return branches is not clear from the graphical notation.
In addition, the dollar sign for the return value is not intuitive. This
awkwardness arises from the fact that features in Scheme are gear towards
describing a process at very specific points, i.e. localized. There is no
simple way to describe global semantics such as “traverse all the items in the
list and retrieve a string” that the programmer want to express in a program.
The programmer has to break this down into steps and explicitly describe what
happens at each step even though this semantic is relatively easy to implement.

The third observation to make is that the function
factorial is a schema for all of the call frames that are generated during
run-time. This is the same relationship as the class graph - object graph
relationship. It implies that the static call graph is a schema for the dynamic
call graph and the CPU is managing the dynamic call graph using the static call
graph and the inputs. Since the behavior of any programs maybe described in
this manner, it maybe possible to describe all programs using the Demeter
concepts.

From these three observations from the simple factorial
example, we can see the usefulness of this experiment. We have hit upon some fundamental
assumptions evident in programming languages and we can explore the semantics
and concepts behind AOP tools further.

We will take a look at a more complex example of the
graphical notation for Fred to explore these observations further. In the next
example, we are translating a Fred implementation of string. We will explore
the function concat, len, and ref that concatenate two
strings, find the length of a string and retrieve the nth character of a string
respectively. For the sake of simplicity, we will assume that other predicates
and methods such as flat-cord?,
make-cord, etc. are
defined and concentrate on the three functions concat, len and ref.

First, we will present and analyze the function concat that concatenates
two strings. In this example, the method define-method is used. This is collapsing the two
methods define-node and
define-branch.
Therefore, it has three parameters: name of the method, predicate for the
branch, and a Scheme expression as the body of the branch. As in the factorial
example, the Fred code that we are translating is shown on the left and the
translated graphical notation shown on the right in Figure 3.

In Figure
28, the first define-method statement handles the case
where the first parameter is of type string. In this case, we make a flat-cord, an internal data
structure, and calls itself recursively. The left branch from concat to make-flat-cord is the
translation of this Scheme statement in the graphical notation. The "string? l" signifies
the predicate that checks for the data type of the first argument "l" to be of type string. The return branch,
with the $ as the first
argument and the "r"
as the second argument, signifies the subsequent recursive call to concat after the
"traveler" returns from make-flat-cord.

The second Scheme statement is expressed by the right
branch of concat.
This is a similar situation to the first statement, except that the second
argument, "r",
is a string. Thus, we
call make-flat-cord
and then a recursive call to concat
with r and $ as arguments. The third
statement is the default case where both of the arguments are cord's. It calls make-concat-cord that
concatenates the two cords
together and this is represented by the middle branch in Figure 28. The function, concat is described by these three Scheme
statements, assuming that make-flat-cord,
make-concat-cord, string?, and cord? are implemented else
where.

The second method that we will be translating is the len function, which
calculates the length of a string. In order to accomplish this task, this
function has to visit every flat-cord
and add the lengths of all the strings stored within the tree of concat-cord's. The base
case for this tree traversal method is the case where the first parameter is of
type flat-cord. It
returns the length of the string stored within it. This case is represented
graphically by the branch with flat-cord?
x predicate in Figure
29 below. Within the body of this Scheme statement, it
calls flat-cord-string,
which is represented by the node by that name. The value returned from this
function call is passed to the function string-length, which is represented by the return
branch with x as the
argument.

More complicated branch on the right is representing the
second Scheme statement in Figure
29. This branch splits to concat-cord-left and concat-cord-right. This means that the calls to
these two functions can be executed in parallel. The return branch is the
subsequent recursive call to len.
However, we need to call +
after this return branch returns. The return branch for the first return branch
represents the call to the function +. The two branches that split originally merge at this point.
This is because the values from the recursive call to len are needed for the
call to +. The resultant value from this + function call is returned as the
result of the original function call to len.

The last function that we'll explore is the function ref that returns the ith
character within a string. There are four cases: the base case where the
argument is a string,
the second case is where the argument is a flat-cord, the third case is where the character is
within the right concat-cord,
and the last case is where the character is within the left concat-cord. The base case
for ref is trivial
and is not shown.

The second case where the arguments are a flat-cord and an integer. We call the method
flat-cord-string and
pass the result to the recursive call to ref. This is shown in the graphical notation in Figure 30 by the left branch to flat-cord-string. The return branch with $ and i as arguments is the
recursive call to ref
after it obtains the string
stored in the flat-cord.
This recursive call is the base case, which is not shown.

The third case is where the character that we are
searching is in the right concat-cord.
Thus, we check for the type of the first argument to be of concat-cord and the second
to be an integer that
is greater than or equal to the length of the left concat-cord string. In this case, we traverse the
node concat-cord-right.
This corresponds to the middle branch with "concat-cord? x" and "integer? x" as the
predicates. The first function call is to concat-cord-left to obtain the concat-cord on the left.
The result from concat-cord-left
is passed to len to obtain the length of the concat-cord. This is represented by the return
branch from concat-cord-left
to len. If the
predicate "i>=$",
i.e. the integer argument is grater than or equal to the result from len, then it calls concat-cord-right and concat-cord-left with x as the argument. The
result from concat-cord-left
is passed to function len.
The results from concat-cord-rightand len are passed to
the recursive call to ref.

This process of translating the more complicated
implementation of strings support the three observations we have made earlier.
No grouping of branches, awkwardness of return branches and the static call
graph as a schema for the dynamic call graph is more evident. These
observations have given us insights into some fundamental nature of programming
languages. The grouping observation points to the scoping of different
programming primitives. The awkwardness of return branches point to the fact
that we tend to program thinking about making progress forward and not thinking
too much about what happens when things return. The schema relationship creates
opportunities for translation of all programs using the Demeter concepts. These
points will be pivotal in creation of AOP Tools analysis methods.

Now, we will translate some Fred examples to AspectJ. The
purpose of this exercise is to understand how Fred and AspectJ are related. We
want to investigate how the observations that we have made in translating Fred
to a graphical notation are manifested in this process.

First, we will attempt to translate the factorial example.
The code in Figure 31 shows how Fred code maps into AspectJ code. The
definition of a message translates to a definition of a method.The branches are split into two parts, the
predicates and the body. The Fred predicates are translated into AspectJ
pointcuts and the bodies of the branches are translated to AspectJ advices.

Notice the return value factReturn for the aspect FactExample. It is used as a means to
propagate the return value calculated. Even though this data member is static,
this program still works because the variable factReturn is set right before it returns from the
method. This could be converted into non-static data member, but we wanted to
make this example as simple as possible.

This explicit handling of the return value is similar to
the way we had to use return branches in the graphical notation. However, if we
used around methods, this explicit handling of the returns values would not
have been needed. In addition, this code does not execute properly as of
AspectJ 1.0. The complier does not handle the case where an execution of an
advice is the result of a method call from another advice.

Next, we will translate the function concat from Fred's
implementation of string. Again, the mapping from Fred to AspectJ is shown in Figure 32. The process is the same as the Factorial Fxample
where we map the branches to pointcuts and advices. Also, we use the same
technique to handle the return values from concat. However, the define-msg call for concat has been folded into the first define-method call. Thus,
the first define-method
call also maps to the definition of the method concat.

In this chapter, we have translated the Factorial and
String Examples in Fred to a graphical notation and AspectJ. These two
translations of Fred examples to AspectJ have been surprisingly trivial.
Explicit and implicit semantics that were evident in Fred and AspectJ were
discovered. Mainly, the values that are returned from a function call are
handled implicitly and this caused difficulty in describing the semantics of
examples using the graphical notation.Also, this relative simplicity in the translation process opens up the
possibility of translating programs written in other AOP tools between each
other.

In this chapter, we will present the process of
translating between Demeter style traversals and AspectJ. First, we will
present the translation process from Demeter traversals to AspectJ, then a
strategy for translating AspectJ code to Demeter traversals. These translation
processes are important in understanding the relationship between the two
different programming metaphors, JPM in AspectJ and "Program as a
Journey" in Demeter. The Join Point Model (JPM) abstracts a program into
join points of programming artifacts, such as classes, methods, member variables,
etc. However, JPM is method centric, i.e. the join points tend to be these
artifacts related to method calls. Thus, the main concern of a JPM is the call
graph within a program. We can see this in the visualization of JPM in Figure 33.

In contrast, "Program as a Journey" metaphor
used in Demeter is concerned with the data structure, i.e. class graph of a
program. In DemeterJ, the programmer constructs a class graph through the class
dictionary. Then, the programmer specifies the strategy in which a visitor
should follow during the traversal of the class graph. The advices, the actual
descriptions of what to do at each node, are invoked during the traversal of
the object graph. Thus, the class graph becomes the "world" in which
the journey takes place, strategy becomes the instructions for the path in the
journey and the visitor becomes the person who is on the journey that does some
work along the way. This concept is visualized in Figure 34.

Despite this contrast of the metaphors, AspectJ and
Demeter both have advices. JPM's advices are descriptions of a process to be
executed when a specified join point is encountered during an execution of a
program. However, Demeter advices are executed when the visitor visits certain
types within the class graph. These two ways of executing advices seem to be
incompatible, until you consider how traversals are implemented in DemeterJ.
DemeterJ combine the strategy and the class graph and creates method calls to
traverse the object graph. Because this implementation is possible, we may use
the same process to translate Demeter traversals to AspectJ.

As an example, we will implement the traversal as a result
of applying the strategy "from Basket to Weight" to the Basket
Example class graph. The traversal graph that we will translate is shown in Figure 11. In this translation process, we will use
introductions to introduce method calls that will traverse the traversal graph
correctly. First, we generate code to traversal all of the has-a edges for each
node that will lead us to class Weight.
Then, we add wrapper methods for each label, i.e. data member variables, so
that we may expose the name of the label to be used within a pointcut. We have
to use method wrappers because there is no other way to distinguish the label
via other types of join points. We also need to take of the inheritance
relationship between Orange
and Fruit by calling super.t1() in Orange.t1(). This will
correctly handle the case where the Fruit reference is referencing an Orange object.The implementation of this traversal and the pointcuts that describe the
relevant join points are shown in Figure
35.

With the relevant pointcuts, we may create Demeter style
visitor to accomplish the task of counting the Weight integers within a Basket as shown in Figure 36 below. The method totalWeight1() that we introduce to the class Basket is there to
initialize the running total, start the traversal, and return the running
total. The pointcut designator t1Weight
uses the pointcut for the Weight.t1()
traversal method and the target()
pointcut is used to pass the reference to the Weight object. Lastly, we add the integer of the Weight object to the
running total in the before advice.

In this manor we may translate Demeter traversals and
visitors using AspectJ features and it was a fairly straightforward process.
Because of this straightforwardness of the translation process, we should be able
to create a program that will accomplish this automatically for us. This new
tool that integrates Demeter concepts with AspectJ became DAJ.

We verified that we may implement Demeter concepts using
AspectJ, but can we implement AspectJ concepts, i.e. using DemeterJ? We believe
that this can be done. All we have to do is to find the correct conceptual
mapping of the Demeter concepts class graph, strategy and visitor. First, we
need some kind of graph that we need to traverse. In AspectJ, the join points
are mostly based on the static and dynamic call graphs. Thus, it would be
natural for us to treat the static call graph as the class graph. Each node
would be a method and labels would be the parameters. This way of describing
the call graph is similar to the graphical notation for Fred. Next, we would
specify the strategy for traversing this call graph to be "from main to
*". This would traverse all nodes reachable from main(). Then, the visitor includes advices
to execute when it reaches a certain node, i.e. a method.

In this manner, we may translate AspectJ code in terms of
Demeter. One might ask, "How can we rationalize why this is
possible?" We may rationalize this by the fact that the CPU/OS is doing
exactly what has been described, except for the advices. The OS reads the
program and start to execute the program. During the execution, the CPU/OS
manages the data structures and the call frames. These are object graphs and
dynamic call graphs respectively. Therefore, the CPU/OS is managing and traversing
the dynamic call graph at the same time.

From this, we can conclude that Demeter concepts can be
implemented using AspectJ and AspectJ concepts maybe implemented using Demeter.
However, the predicated method calls, which are not addressed in Demeter needs
to be addressed. One approach is to merge the ideas from Fred into DemeterJ. We
have shown that Fred maybe translated to AspectJ and we may gain clues for
developing this translation methodology.

In Figure
37, we attempt to translate AspectJ Basket Example to a
modified DemeterJ. First, we create the call graph by using the modified BNF.
This just creates the connections, i.e. method calls between these different
methods. MyVisitor is
defined similarly as the DemeterJ implementation of the Basket Example. Next,
we define a new programming feature called a guide. A guide is defining the
predicates that are used to determine whether we choose to traverse down an
edge in the call graph. This is consistent with the "Program as a
Journey" metaphor in which a local guide makes local decisions about a
trip, while the visitor follows along. The last statement is the case where any
method of the name getTotal()
should have predicated method invocation if its date member is not equal to
null. As you can see, it has some semblance to the AspectJ syntax. Lastly, we
define the traversal with the visitor, guide, and a strategy.

This modified DemeterJ has predicated execution by using
the guide, which is consistent with the metaphor that Demeter is using. This
incorporates the predicate execution from Fred and the pointcut syntax from
AspectJ. Thus, merging of these tools into the modified DemeterJ would be a new
direction in which DemeterJ may explore.

From this experiment of translating between AspectJ and
Demeter, we may conclude that both of these concepts are similar in their
power. Then what is the differentiating factor that an analyst should consider
during AOP tools analysis? We suggest that we examine the usability of the
metaphors and the economy of expression. These two would be paramount in the
success of these tools because of issues from Human-Computer Interaction and Software
Engineering.

We have introduced the metaphors, JPM and “Program as a
Journey”, used in AspectJ and Demeter respectively. By examining the metaphors
and understanding how DemeterJ implements traversals, we were able to translate
the traversal and the visitor from the Basket Example to AspectJ. Since, this
translation was possible, we presented a way to describe the Demeter concepts
in terms of JPM concepts. However, the translation from AspectJ to the current
version of DemeterJ was not possible without modifying DemeterJ. We proposed to
add the concept of guide to DemeterJ that would allow traversal decision to be
made at each node with predicates; similar to the way Fred uses
predicates.Thus, there is no
significant differentiating factor by their descriptive power. However, other
differentiating factors maybe obtained from the field of Human-Computer
Interaction and Software Engineering.

In this chapter, we will discuss and analyze the metaphors
Join Point Model and "Program as a Journey" being used in AspectJ and
Demeter tools respectively. The Join Point Model that is used in AspectJ is a
model in which a program is broken down into connections or join points.
Wherever things connect, we may describe those points within a program and
execute some code before, after or around those join points.

We would call the Join Point Model a
"construction" metaphor. Many things in science and engineering use
this type of metaphor in which things are constructed with building blocks.
Things such as furniture, molecules, and buildings have points in which building
blocks that join together. This is a widely used metaphor for scientists and
engineers. The "join points" for a schematic diagram of an XOR Gate
implemented using AND, OR, and NOT gates is shown in Figure 38. The join points for a caffeine molecule is shown in Figure 39.

As a metaphor that is natural for scientists to use, and
we will attempt to describe Demeter in terms of a Join Point Model. First, we
need things that are connected to create join points. We can use the class
graph for this purpose. Thus, join points are the points in which edges and
nodes are joined. Examples of join points within a class graph are shown in Figure 40.

However, we need to add something to the metaphor in order
to add advices. We need to add traversals for this purpose. In AspectJ, the
join points are points within the execution of a program. In this model,
something is already happening, so adding advices simple. We just attach advices
at certain points during this process. However it is not so simple for the
class graph. There is nothing happening in the graph itself implicitly, until
we add the traversals for the object graph. Then, we may say that the traversal
uses the class graph as a map to the object graph during the traversal as
presented earlier in the ascription of Demeter. In this view, we may use any of
the pointcut designators in AspectJ for describing certain points within a
traversal. Thus, if we wanted to describe the join points between Basket and Fruit, the pointcut would
be "this(Basket)
&& target(Fruit)".

As we can see, the Join Point Model can describe Demeter
perfectly well consistently. In a similar manner, Join Point Model should be
able to describe many of the other programming languages. The reason for this
is that the computer related fields and other scientific fields use this type
of "building" metaphor to describe structures and processes.

The "Program as a Journey" metaphor used in
Demeter is an instance of the Journey metaphors as described in [18 Lakoff & Johnson]. The Source-Path-Goal Schema and the metaphors
"States are Locations", "Change is Motion", "Purposes
are Destinations", "Linear Scales are Paths", "Lovers are
Travelers", and "Love Relationship is a Vehicle" are all listed
and discussed as commonly used metaphors in everyday conversations. All of
these metaphors are instances of the Journey metaphor, where we think of
everyday things as a journey.

The concepts used in Demeter are also an instance of the
Journey metaphor. We may map each of the major components in Demeter to a
person taking a journey. The class graph could be the map in which the person
is using to understand how to conduct his journey. The object graph would be
the actual world or place in which he is traveling. The strategy is the
directions that the person is following in order to accomplish his objective.
The visitor is the person on the journey. The advice in the visitor is the
actions the visitor will perform at each point in the journey. The guides, as
introduced in “Translating Between AspectJ and Demeter,” are the local guides
that will help make localized decisions during the journey. Because of this
perfect mapping between Demeter and a journey, Demeter is a perfect example of
the Journey metaphor at work.

At first glance, it does not seem to be possible that the
"Program as a Journey" metaphor could be used to describe the Join
Point Model. However, the JPM as applied in AspectJ uses the call graph to
specify the join points. Therefore, we may apply the "Program as a
Journey" metaphor to the call graph. We can rationalize this by the fact
that when many things are connected together, the result of these connections
can be abstracted as graphs. In Figure
38, the XOR gate is implemented using the primitive AND,
OR, and NOT gates. The gates are joined together by connecting wires. The
"join points" in this case are the points in which wires and gates
are joined together. These schematic diagrams of logical devices are also
thought of as a network of gates. Thus, we may apply the JPM and the Journey
metaphors to the XOR schematic diagram in Figure
38.

The mapping of roles from the Journey metaphor to the major
concepts in the JPM is similar to the way Demeter was mapped. The static call
graph is the map in the journey. The dynamic call graph is the place in which
the journey takes place. The visitor is the CPU/OS that is on the journey. The
join points describe certain points within in the path of the journey. The
advices are the actions that visitors should perform at these points in the
path. In this manner, we can describe AspectJ's JPM in terms of the
"Program as a Journey" metaphor.

If the JPM and "Program as a Journey" metaphors
can describe each other, is there any advantage of using one verses the other?
In terms of applicability of the Metaphor there does not seem to be any
difference. If we can apply one, then we may apply the other. However, if we examine
other factors such as economy of expression, learning curve, usability, etc.,
there are differences.

Many of these factors seem to favor the "Program as a
Journey" metaphor for the general programming language. It is easily
understood by more people in general, because of its wideuse in everyday language to describe
everyday events and relationships. The ambiguous nature of the strategy allows
programmers to specify only what they need to accomplish a certain task instead
of having to specify more. These are the two major strengths of the
"Program as a Journey" metaphor that points it as the metaphor to be
used in a general programming language.

On the other hand, the Join Point Model seems to be a
programming language for scientists and engineers. The "Building"
metaphor is used through out the scientific community. Lakoff and Johnson [18 Lakoff & Johnson] call it "Organization as Physical
Structure." Because of its precise nature of specifying the join points
and its flexibility in organizing programs it is well suited for a scientist or
an engineer. Thus, the decision to use one metaphor over another would have be
made in a case by case basis.

Even with strengths outlined for the metaphors used in
AspectJ and Demeter, the ability to gain feed back about the way a program is
executing is lacking. The traditional way of debugging with debuggers and print
statements are things that were added on as an after thought. This is similar
to the forward progress thinking of writing programs. The programming languages
were designed to allow programmers to specify processes that allow the program
to make forward progress. There has not been any successes in adding
programming language features that allow programmers to add visibility into
their applications easily. Therefore, the visibility of programs during
execution needs to be integrated in to the design of the programming language
and the metaphor that is used. It would allow programmers to find bugs and fix
them quicker, reduce the cost of development and support, and create more
robust and cost effective applications.

We have analyzed the metaphors used in AspectJ and
Demeter. These metaphors, Join Point Model and "Program as a Journey"
can be used to describe each other. These metaphors are also used in other
fields and places for other purposes. Join Point Model seems to be well suited
for scientists and engineers while "Program as a Journey" would have
a general appeal. However, these two metaphors and their applications in AOP do
not address the issue of visibility in programs. Thus, this should be taken
into account in the metaphor and the programming language feature design of the
AOP tools in the future.

In this chapter, we have analyzed the JPM and “Program as
a Journey” metaphors that are used in AspectJ and Demeter tools. The two
metaphors are very similar and both are present in Demeter and AspectJ.
However, the terminology and features used in AspectJ and Demeter tools
emphasizes one metaphor over the other. We also found that JPM is maybe applied
to many things that are in scientific fields while the “Program as a Journey”
is similar to the different types of Journey metaphor that is used by everyone
in everyday conversations as presented in [18
Lakoff & Johnson]. Because of this, the JPM would be easily adapted by
scientist and engineers, while the “Program as a Journey” maybe easily
understood by the general public.

DAJ, pronounced as "dodge", is an application
that allows programmers to add Demeter traversals to their Java programs. This
is the result of the work outlined in the previous chapter "Implementing
Traversals in AspectJ." DAJ integrates DJ, DemeterJ and AspectJ to
implement a system that allows programmers to specify traversals for their
AspectJ programs. DAJ extends AspectJ incrementally without modifying the
AspectJ compiler. This was possible because of the powerful AOP tools that were
available.

The system architecture was designed such that DAJ will
minimize coupling with the AspectJ compiler. Since, the AspectJ compiler is out
of our control, this was the design decision that we made. We also wanted the
new language to have similar syntax as AspectJ and Java to lower the learning
curve for programmers. Therefore, we decided to create a tool that would use
AspectJ, DemeterJ and DJ to generate the traversals in AspectJ and use
AspectJ's compiler as the backend weaver. Basically, DAJ is a reimplementation
of DemeterJ traversals, but using AspectJ as the weaving language instead of
the DemeterJ weaving language.

There are four phases in DAJ as shown in Figure 41: stub generation, traversal generation compilation,
traversal generation, and traversal compilation. In the stub generation phase,
the traversal files are parsed and stub traversal methods are generated for
compilation in the next phase. Without these stubs, the method calls to the
expected traversal methods that will be generated in the traversal generation
phase, will cause a compilation error. Thus, for every traversal, DAJ will
generate a stub method for the source of the strategy for a particular
traversal.

In the following phase, the generated stub methods,
CreateClassGraph.java and the user code is compiled. The CreateClassGraph.java
is needed in the traversal generation phase to intercept the call to main method, create an
instance of ClassGraph
using DJ, and generate the traversals. The AspectJ compiler is used to generate
the .class files to execute in the next phase.

In the traversal generation phase, DAJ executes the code
that has been compiled in the previous phase.The CreateClassGraph.java includes AspectJ code to intercept the call to
the main method. It then generates a ClassGraph object using DJ and starts the traversal generation
process. Then, DAJ parses the traversal files and generates the AspectJ
traversal implementations as outlined previously.

Lastly, DAJ compiles the generated traversals and the
user's code using the AspectJ Compiler. The traversal compilation phase
generates the .class files that the user is expecting from DAJ. These four
phases are necessary to decouple DAJ from DJ and AspectJ.

These four processes are managed by the DAJ’s main method.
DAJ’s main method processes the command line arguments. Then it uses the
appropriate methods to invoke the four processes for generating the AspectJ
traversal code. First, it calls the appropriate methods to generate the stubs
in the stub generation process. In the next three processes, it create a shell
command line and uses Java’s API to executethat command. DAJ translates the command line given by the user to the
appropriate command line arguments to each of the phases that is executed using
the shell. This relationship between the DAJ main method and the four processes
of the traversal generation is shown in Figure
42 below.

The traversal file has three major components, the class
graph declarations, traversal declarations and aspect definition that enclose
the class graph and traversal declarations. The class graph declaration may
have two different types of class graphs: a default or a class graph slice. The
class graph defined by the default class graph declaration is the class graph
object that is obtained from CreateClassGraph.java using DJ. Thus, it contains
all of the classes and relationships contained within a program.

As shown in Figure
43, the default class graph declarations has the keyword
"ClassGraph"
followed by a variable identifier and ends with a semicolon. This is consistent
with the way in which one would declare a local variable in Java and similar to
the way a programmer would use DJ. This similarity allows Java/DJ programmers
to understand this syntax very easily.

The class graph slice form of the class graph declaration
looks like a DJ class graph declaration with a class graph and a strategy as
shown in Figure 44. Just like the default class graph Declarations,
class graph slice declarations start with the keyword "ClassGraph" and a
variable identifier. Then, it has what looks like an assignment operator,
equals symbol, and a call to the constructor for the class ClassGraph. The constructor
has a ClassGraph
variable and a strategy in string format as the two arguments as shown in Figure 45.

The traversal declaration has two forms as well: default
traversal and traversal with class graph as an argument. The default traversal
declarations allow DAJ to generate the AspectJ traversal implementation using
the default class graph as shown in Figure
45. Its syntax with the "declare" and "traversal" keywords
are consistent with the AspectJ declare statements. These keywords are followed
by a variable identifier, colon, strategy in string form, and a semi-colon.
Again, DAJ uses the default class graph from DJ to generate the traversal
implementation from the default traversal declaration.

The second form of the traversal declaration is the one
where a class graph that was declared earlier is used. The difference from the
default traversal declaration is that there is a class graph identifier within
parenthesis between the traversal variable identifier and the colon as shown in
Figure 46. This has the same conceptual model as calling a
function. Thus, the programmer may think of this type of traversal declaration as
passing a class graph to the traversal. The class graph that is passed would be
used during the traversal generation instead of the default class graph
obtained from DJ. This syntax is shown in Figure
46.

As of version 1.1, DAJ allows programmers to specify
visitors for specific traversals. DAJ uses Java reflection to obtain the method
signatures of the visitor specified by the user. It then generates the
appropriate AspectJ code to call the visitor advices at the right point during
the traversal. In order to use this feature, the programmer must define a class
with advice methods, declare the visitor in the .trv file, and specify the
declared visitor in a traversal declaration. The methods that are process by
DAJ are specified in Figure
47.

The method start()
is called before the traversal starts. The initialization code for the visitor
should be defined in the method start().
The method finish() should contain code that should be executed when the
traversal is finished. The typical advices before, after and around are defined
as methods with one argument. The argument is the type of node that advice
should be executed when the visitor encounters that object type. The around method also includes
a return type. However, this functionality is not very useful, because the
returned value would be lost. This return type is allowed for future addition
to DAJ. The last method allowed is the method returnValue(). This method would be invoked when
the traversal finishes. However, this functionality is not implemented
currently. In the future, the user would be able to declare a behavior that
would generate wrapper method for the traversal such that it would create a new
visitor, execute the traversal and then return the value from the method returnValue(). This is
scheduled to be implemented in DAJ 1.2.

Next, the user may declare visitors as shown in Figure 48. The keyword Visitor is used to signify that this statement is
declaring a visitor. Then, followed by a variable. This variable should be the
class name of the visitor. Finally, it ends with a semicolon. This syntax is
consistent with Java’s syntax. The visitor declaration allows DAJ to use these
visitors for traversals.

Next, we modify the traversal declaration to allow
visitors as specified in Figure
49. This is the same syntax as the traversals with class
graph, except that we have added a second “argument” as the visitor variable
that was declared earlier. DAJ will generate the traversal method for the
strategy, similarly to the other traversal declarations. However, DAJ will
generate another method that has the visitor type as an argument. This allows
the user to use the traversal with or without a visitor, depending on what the
user wants. For example, the first traversal declaration in Figure 49 would produce methods void t1() and void t1(BasketVisitor).

The last language feature in DAJ is the aspect
declaration. It contains class graph declarations and traversal declarations as
shown in Figure 50. The syntax is designed to be similar to AspectJ.
However, programmers may not add AspectJ code within the traversal files. This
capability requires that DAJ be able to parse AspectJ syntax and it would be
outside the scope of this thesis.

Lastly, we use DAJ to implement the traversal for the
Basket Example. The DAJ traversal file in Figure
51 will generate to traversal code similar to the one
shown in Figure 35. Thus, we may replace the traversal code in Figure 35 with the DAJ traversal file in Figure 51 below. The other user code may stay the same.

DAJ is a tool that allows AspectJ programmers to use
Demeter concepts in their programs. We have presented the compilation process,
syntax for the traversal specification files, and an example that implements
the traversal from the Basket Example in DAJ. It is implemented using DJ,
AspectJ and DemeterJ and combines concepts from two aspect oriented programming
tools AspectJ and DemeterJ.Because of
the way DAJ was implemented, it extends the AspectJ compiler by incremental
addition rather than by modification. This is possible because of the powerful
features of aspect oriented programming.

In [24
Orleans], the performance of traversals using DJ was
determined to be 20 to 30 times slower than DemeterJ. We wanted to see how DAJ
implementation of the traversal compared with DJ and DemeterJ. This is
important, since the efficiency of traversals is central to the performance of
the applications using these tools. We will describe the methodology used to
measure the relative performance, describe the results that have been obtained,
and describe the analysis done on those results.

In order to measure the performance of traversals, we
measure the amount of time it takes to perform a certain task with the
traversal. First we define a class graph that allows large object graphs. We
want to vary the size of the object graph to find the relative slope between
the different tools. Next, we define a traversal to accomplish some task, such
as counting the number of leaf nodes within the object graph. This object graph
happens to be a parse tree, because the class graph is implemented using a
class dictionary in DemeterJ. Then, we implement the traversal using the three
tools, DJ, DemeterJ and DAJ. We also implement the visitors to go along those
traversal implementations. After that, we create an object graph and execute
the three implementations of the traversal. Finally, we measure the elapsed
time between start and the end of the traversal.

The class dictionary used to generate the object graph is
shown in Figure 52. The top level class is the class Container.It contains a list of ContainerIterms that is
surrounded by the strings “container” and “end”. Each ContainerItem maybe either a SubContainer or an Item. A SubContainer sentence
starts with the string “sub” followed by a Container. This is the recursive part of the class
graph that allows the object graph to grow to any size. An Item maybe either I1, I2 or I3. Each of these classes does not have any data
members. However, they do define strings that allow the parser to distinguish
between each of the Items.

An example input file for the class dictionary in Figure 52 is shown in Figure
53. It defines a top level container with I2, I3,
SubContainer, I4 and I5 objects. As demonstrated in the example, it is very
easy to create large object graphs with this class dictionary.

The number of nodes in the object graph is determined to
be the number of objects of type Container, ContainerItem,
SubContainer, Item, I1, I2 and I3. These class types were chosen because these are
the node types that a programmer would create advices for. Even though an
object of type I1, I2 and I3 are also of type Item as well. Thus, adding
a node of type I1
would add two nodes in the object graph. Other classes that were generated by
DemeterJ to implement the list used in the class dictionary were not counted.
Since, we only care about relative performance as we increase the object graph,
they should not impact the final analysis.

The traversal that we selected is with the strategy “from
Container to *”. It forces the traversal to touch all of the nodes within the
object graph. The performance of the traversal should be apparent because of
this property. First, we implemented the traversal using inlined visitor in
DemeterJ as shown in Figure
54. The inlined visitor initializes the total to be
zero, then increments the total before I1, I2 and I3 type objects. Then, it
returns the total value after the traversal has completed.

The elapsed time was calculated by obtaining the current
time in milliseconds before and after the traversal. Then, calculating the
difference between the start time and the finish time. The current time was
obtained by calling the static methodSystem.currentTimeMillis()
in the Java API.

The DJ implementation of the traversal is in two parts.
First, the visitor was defined using DemeterJ and the DJ API was used to
calculate and execute the traversal. The DemeterJ statements for declaration of
the DJVisitor and the
definition of the advice methods are shown in Figure
55.
The first statement is a DemeterJ class dictionary statement that defines the
class DJVisitor. It
inherits from the visitor interface defined by DJ. The following statements are
from the DemeterJ behavioral file that defines the advices for the visitor to
count the I1, I2 and I3 objects. Finally, an accessor method to retrieve the
total from the visitor.

Next, we use regular Java code using the DJ API to execute
the traversal given a Container
object c as shown in Figure 56.This Container object c is the root of our object
graph. First we create a new ClassGraph object and a DJVisitor object. Then, we
obtain the current time, calculate the traversal graph, traverse the object
graph, and finally obtain the finish time. The calculation time for the
traversal graph is included in the elapsed time, because this traversal time
has to be calculated by the user at least once. In DemeterJ or AspectJ, the
traversal graph is calculated at compile-time.

Lastly, we implement the traversal in DAJ. The traversal
is implemented similarly to DJ, a visitor is defined, then the traversal is
implemented with specifying it in a.trv file. The DAJVisitor is implemented in
the same manner as DJVisitor. First, the class is defined in the class
dictionary and then the advices and the accessor method for the total is
defined in the DemeterJ behavioral file as shown in Figure 57 below.

The traversal was modified slightly to bypass the
interfaces that the DemeterJ generated list classes implement. Thus, the
strategy changed to “from Container bypassing {java.lang.Object,
java.util.Enumeration} to {I1, I2, I3, Container}”. This should traverse to all
relevant nodes in the object graph. The .trv file to generate the DAJ
implementation of the traversal is shown in Figure
58.

In our experiment, the object graph was varied from 10,000
nodes to 20,000 nodes by 5,000 increments. Each traversal implementation’s
elapsed time was measure on a SunBlade 100 running SunOS 5.8. The result of
this experiment is shown in Figure
59 below.

The values in Figure
59 is graphed in Figure
60. In this graph, we can see that the running time for
the DJ implementation increases linearly as we increase the number of nodes in
the object graph. However, the slope of the increase is much larger than for
DemeterJ or DAJ. The magnitudes of the elapsed times for each object graph is
much lower as well.

The results for DemeterJ and DAJ has been graphed in Figure 60 to compare the results. The elapsed time for both
implementations are pretty much the same. However, there seems to be some
constant overhead for the DAJ implementation verses the DemeterJ
implementation. This must be due to the way AspectJ implements the
introductions and advices. Thus, the DAJ implementation of the traversal has
significant performance advantage over DJ for relatively large object graphs,
while it performs comparatively with DemeterJ.

In this chapter, we have described the methodology for
measuring performance for traversal implementations. We implemented the
traversals and measure the performance using the described methodology. We
varied the object graph in which the traversal was executed on and obtained the
results. From these results, we have found that DAJ performs significantly
better than the DJ implementation of the traversal and performs comparatively
to DemeterJ implementation. Therefore, the performance of traversals
implemented by DAJ should be high enough for most programmers.

An objective method of analyzing any type of tool requires
a model and fundamental rules about how different parts of the model interact.
Currently, there are no such models for analyzing aspect oriented programming
(AOP) tools. However, there has been some mention of this issue in different
publications. In [3
Aldrich], Alderich attempts to provide different types of
concerns and illustrate the types of problems that AOP tools must solve. While
in [4 Chu-Carroll], Chu-Carroll attempts to organize the program in a
novel program organization. A very abstract view of program organization is
shown in [5 Black et. al.] by Black and Jones. Sutton and Rouvellou take a novel
approach by attempting to apply Categorizational Theory in [6 Sutton et. al.]. All of these approaches attempt to come up with a
method for analyzing and thinking about concerns and how we may deal with them.

In this chapter, we propose the Four Graph Model of
Programs (4GMP) by applying a graph-theoretical view of programs and merging
the graphs in Demeter and AspectJ. These four graphs in 4GMP can be analyzed to
formulate fundamental relationships about the graphs within 4GMP and the
different features within an AOP tool. This type of analysis will allow us to
create a map of the features within the AOP tool. This map will allow us to
find the strengths and weakness of an AOP language. Thus, the proposed 4GMP and
its methodology for feature analysis would be useful for feature inclusion
decisions for AOP tools and languages.

First, we will present the 4GMP and how we formulated the
model. We will analyze some of the properties of the graphs to understand why
this model might be useful. Then, the model would be applied on DemeterJ [11 Lieberherr et. al][14
DemeterJ] and AspectJ [9
Kiczales2001][10
Kiczales et. al][12
Kiczales], to illustrate the usefulness of 4GMP for AOP tool analysis.
Finally, finish the proposal with some conclusions and possible future work.

By using a graph-theoretical view (GTV), we try to
abstract everything within in a program into graphs. This allows us to simplify
the program and allow us to find relationships between the different graphs.
The relationships between these graphs will give us more insight into the
different problems evident in writing programs. We believe that we can use this
insight to develop methodologies for analyzing AOP Tools.

First, we try to break up a program and its execution,
into graphs. The most common boundaries are the compile-time/runtime boundary
and the data structure/algorithm boundary.These distinctions come from AspectJ and Demeter concepts of static JPM,
dynamic JPM, class graph and object graph. If you break up a program with these
boundaries, you get four graphs, class graph, object graph, static call graph
and dynamic call graph. These are the four graphs in Four Graph Model of Programming
(4GMP). These four Graphs are mentioned in Demeter and AspectJ.

To understand how the different graphs are related, you
just need to analyze how programs are executed and how programmers make
decisions about data structures and Algorithms. In DemeterJ, the class graph is
used to generate the object graph given some input and the class graph. Another
way of looking at this system to look at the class graph as a specification of
the pattern of some data structure and the object graph is a valid instance of
that pattern.

You can make analogous relationship between static call
graph and the dynamic call graph as well. The static call graph specifies all
valid instances of the dynamic call graph. These relations are analogous to how
grammars specify all possible set of parse-trees that can be generated with the
set of all possible sentences in a particular language. This is the view of
class dictionaries and the object graphs in Demeter.

From this transformation of a compile-time graph into a
runtime graph, we can create a generic model of graph transformation. The basic
model of graph transformation in 4GMP is shown in Figure 63.The basic
components in this basic model are input, specification, and output and each of
these components can be abstracted as graphs. The processor is the processing
logic that uses the specification and transforms the input to generate the
output. This processor may be composed of input, specification, processor and
output. Thus, it is recursively defined.

This model can be applied to the current compiler and
execution process as shown in Figure
64. It illustrates how specification and input combine
to generate output for compiled language such as C. We first start with some
input file, which can be in C, C++ or any other compiled program. Then, we use
the token specification to transform the linked list of input characters into a
linked list or a stream of tokens. The grammar specification then transforms
the tokens into a parse tree. Then, the back end of the compiler converts the parse
tree into an executable program. In each step, the resultant output data
structure tends to be much larger than the specification and the input
combined.

The other boundary in the 4GMP, Data Structures/Algorithm
boundary, is a familiar boundary from the undergraduate data structures and
algorithms class. In many cases, you need to make decisions on what types of
structures you would use to store the information and how you can apply
different algorithms to solve the problem at hand. These decisions are of the
type where the size of the data structures can be increases to lower the
execution time of the program or vice versa. This implies that you can some how
reduce one graph by increasing the other. There is still very little
understanding of this type of relationship between these two graphs within the
4GMP and further investigation is needed.

When we see a repeated pattern, we factor the common parts
out to reduce the amount of code and increase the modularity of the system.
This has the effect of creating a more concise description of the graph. We
call the concerns of this factorization process the factorizational concern.
These factorizations occur at many different levels within a computer system.

Functions that are called multiple times, inherited
methods and data members, parser generator in DemeterJ, wildcards in pointcut
designators, and traversal generation in DAJ are all examples of features that
are used to address the factorizational concern. When a function in C or Scheme
are called multiple times, the programmer has effectively factored out the
commonalities of the code and created on function that may be invoked many
times. The inherited methods and data members are also factored from the
classes that inherit them. The parser generator in DemeterJ is factorization of
parsing. It allows programmers to specify a parser with minimal amount of code.
The wildcard feature for pointcut designators in AspectJ allows programmers to
insert advice bodies to many different points during a program’s execution.
Thus, all of the method calls have been factored. The traversal generator in
DAJ has factored out the regularities of the traversal code. In all of this c

The factorizational concern process pictured in Figure 65 should look very familiar. It is the graph
transformation model of 4GMP presented earlier. The input is the first graph,
the specification the second graph, the output is the graph on the right and
the processor is the plus operator. This relationship between the specification
and the output is called factorizational concern relationship within 4GMP. From
this, we can conclude that there is a factorizational concern (FC) relationship
between the class graph and the object graph and between the static call graph
and the dynamic call graph.

When a graph gets to be very large, it get to be very hard
to find things to modify or understand it. Sorting or organizing is a way to
solve this problem. We can organize the graph into different subgraphs and we
can even create some hierarchy of subgraphs. The factors in which a programmer
needs to take into account when make the decisions for this grouping process is
called organziational concerns (OC) in 4GMP.

The organizational concerns (OC) are important, because it
allows us to create some order. This is necessary for us to divide the program
into manageable chunks that we can create and manipulate. However, this creates
another problem: how do we determine the optimal subdivision of the graphs?
More importantly, how do we know when it is optimal?

For this problem, we can borrow the concept of cohesion
and coupling from software engineering as shown in Figure 67. Under the 4GMP, OC with low cohesion and high
coupling is desirable to minimize the propagation of changes and high degree of
interaction between collaborators in collaborations, whether the collaboration
is a data centric view or an algorithm centric view of the collaboration.

From the FC and OC relationships from the four graphs in
4GMP we can create a concern relationship (CR) diagram. The CR diagram of the
four graphs in 4GMP is shown in Figure
68. In the CR diagram, the four graphs are connected by
either factorizational concern (FC) or organizational concern (OC)
relationships.

From the CR diagram in Figure
68, the factorizational concerns and organizational
concerns seems to be orthogonal, i.e. they do not interfere with each other. As
an example, let us analyze the concepts class and inheritance in object
oriented programming. Classes are grouping of data and the associated
operations on that data. If a object oriented program was re-implemented using
functional programming then one of the major changes would be the way in which
the program is organized. The functions would not be tied to the data structure
except by their arguments and maybe declared or defined anywhere in the source
tree. This major difference brought on by the class concept in OOP enforces
some organization of the functions and the related data structures. Therefore,
the class concept in OOP is an organizational feature, a programming feature
that assists programmers in organizing the program.

The inheritance feature on the other hand, allows
programmers to factor out common data and operations from the base class. By
moving the commonalities from the inherited classes to the base class, the
programmer has effectively factored the data and/or their associated
functionality from the inherited classes to the base class. Thus, this is a
factorizational feature, a programming feature that allows programmers to
factor out commonalities within class hierarchies. Therefore, in object
oriented programming, the class feature have an OC relationship, and the
inheritance feature has a FC relationship.

The OC relationship that the class feature has is with the
class graph and the static call graph. This is because, it allows programmers
to organize data and methods. The inheritance feature has a FC relationship
with the class feature, since OOP allows inheritance only on classes. These
relationships are illustrated in Figure
69.

One interesting observation to make in the CR diagram in Figure 69 is that the class feature without inheritance only
allows the programmer to organize the program in a different way. The class
feature with inheritance allows programmers to factor commonalities evident in
classes, whether they are data members or methods.

From this analysis, one might ask, “What would be the
ideal CR diagram in a programming language?” We propose a conceptual CR diagram
in Figure 70. It is a chain of features with FC relationships
between them. Then, each of these feature would have another feature that allows
the programmer to organize the usage of those features. This ideal CR diagram
maximizes the benefit of factorization with the sequence of features that are
related by FC and allows programmers to organize the code at each
factorizational step.

However, we may factor the organizational feature by using
only one feature that would organize all of the factorizational features as
shown in Figure 71. This new CR diagram would possible be more ideal.
This is only a proposal and we cannot know that for sure until there is more
research is conducted.

AspectJ is an aspect oriented programming (AOP) tool that
was introduced by the AspectJ group at Xerox PARC [9 Kiczales2001][10
Kiczales et. al]. AspectJ extends the Java language to allow
programmers to group crosscutting concerns, i.e. aspects.We will limit our analysis to specific usage
of aspects, introductions, join points, pointcuts and advices in AspectJ. We
will not discuss the relationship between AspectJ and features in Java.

The introductions in AspectJ could be thought of as adding
nodes and edges into graphs. Introduction of methods corresponds to adding
nodes in the static call graph, while introducing data members and inheritances
are adding nodes and edges in the class graph. In Figure 72, two different types of introductions are shown.
First AspectJ statement introduces the data member variables f1 and f2to the class basket and their type is Weight. This introduction adds a has-a edge
in the class graph. The second introduction introduces the method t1() to the class Basket.
This method create a node in the static call graph with conditional edges to
nodes t1_crossing_f()
and t1_crossing_f2().

There are other means of adding methods, data members and
inheritance relationships using pure Java, but this method allows programmers
to group crosscutting concerns in one aspect. From this description of the
introduction feature in AspectJ, we can conclude that introduction is an
organizational concern feature. It allows programmers to organize the code in
different ways that makes more sense to them.

Join points are points where the edges are joined with
nodes in the four graphs of 4GMP. This does not fit into either OC feature or
FC feature, because by itself, it does not allow for organization or
factorization of the program nor its four graphs. We call this type of feature
a specification concern (SC) feature. In general, a join point allows
programmer to specify a specific point within the call graph. In other
programming paradigms such as OOP or Functional Programming, programmers could
not specify these points. They could only modify them by modifying code in
those programming paradigms. Thus, SC features allow programmers to specify
elements in the tool.

There are many different types of join points in AspectJ.
Not only can join points be in the class graph, but it may also be in the class
graph and object graphs as well. Programmers can specify join points for
specific classes that are encountered during the program’s execution. A join
point may even specify specific data values the object of a certain type should
have as well. Therefore, the join point has SP relationship with all four of
the graphs in the 4GMP.

Pointcuts are a set of join points. It allows programmers
to specify the join points that the user is concerned with. Therefore, pointcut
is an organizational concern feature. It allows programmers to organize a set
of join points. However, the programmers may use the wildcard “*” in a
pointcut. This has the effect of factoring similar properties of different join
points within a pointcut. Thus, a pointcut with the wildcard “*” is a
factorizational concern feature since it allows programmers to specify the set
of join points with patterns which is much more compact.

The first point in Figure
73 describes a join point that results from a method
call to method t1()
in Weight. It
describes one join point. The second pointcut describes two join points and it
holds true if the method t1()
in Weight is called
from Fruit. These two
pointcuts are examples of how programmers can organize different join points
together to specify a certain point in the static call graph. The third
pointcut describes all join points in the program have has the string “t1” in
the method name with any return type and no arguments. This is an example of
factorizational feature of pointcuts using the wildcard “*”. Thus, the wildcard
feature of pointcuts have a factorizational concern relationship with
pointcuts.

The advice in AspectJ is used to incrementally add
behavior to an existing program. There are three different advices, before,
after and around. Each of these advices is associated with a pointcut. These
advices does not factorize nor organize the pointcuts, instead the pointcut
allows the programmers to specify the different points in which the advice
bodies should be executed. The example AspectJ before advice shown in Figure 74 shows a simple advice with a pointcut. The semantics
of the pointcut specify the point in which the advice body should be executed.

Lastly, we will analyze the AspectJ aspect feature. The
aspects contain introductions, pointcuts, and advices. Thus, it is a feature
that allows the programmers to organize these other features. By the definition
of the OC feature, AspectJ aspect is an OC feature. As we can see in Figure 75, The aspect FactExample contains introductions, pointcuts, and an around
advices. All of these statements could be defined in any aspect as long as the
pointcut used by the advices are defined within the scope of the aspect.

From this analysis and the resultant relationships that we
have deduced, we may create a CR diagram of AspectJ. This CR diagram is not
complete, as it does not account for other AspectJ features such as,
inheritance of aspects, abstract aspects, etc. It also does not take into
account all of the features available from the pure Java code that is allowable
in AspectJ. The CR diagram of the AspectJ features discussed is illustrated in Figure 76.

One of the things that is apparent in the CR diagram of
AspectJ features discussed shown in Figure
76 is that there are many more OC relationships than any
other relationships. Thus, much of the features in AspectJ are designed to
organize the code in a program. Also, the join point has SC relationship with
the four graphs of the 4GMP. This implies that join point may specify anything
in those four graphs and this fact make the join point feature very powerful
compared to the other features. Not only that, but it is also a bridge that
connects the other features aspect, advice and pointcut to the four graphs.

From this CR diagram, we can see that AspectJ features are
imbalanced towards join points. Because of this imbalance, it would be much
more cost effective to add factorizational features for the other features such
as introduction and advice. It is between to improve your weakest side instead
of fortifying your strongest side.

DemeterJ is a tool introduced by the research group at
Northeastern University [11
Lieberherr et. al][14
DemeterJ]. In contrast to AspectJ that extends Java, DemeterJ
creates a new software development process and a new language that is built on
top of Java. We will analyze the class dictionary, strategy graph, traversal
graph, visitor and advice concepts in DemeterJ.

Class dictionary allows programmers to specify the class
graph in a more concise form than allowed by Java or C++. The class dictionary
is in a modified BNF format that allows an intuitive way of expressing the
class graph. The is-a relationships correspond to alternations for a type,
while is-a relationships corresponds to actual links between different classes.
In an essence, a class dictionary factors out the syntax for class declaration
and the inheritance relationships. It also does double duty as a parser
generator using JavaCC [17
Java CC]. The class dictionary specifying a language that
parses XML specification of the Basket Example is shown in Figure 77.

These characteristics of class dictionary, concise
definition of the class graph using BNF and automatic generation of a parser
make it a factorizational concern feature. It factors out the syntax needed for
specifying the class graph in Java. Therefore, this feature of class dictionary
has a FC relationship with the class graph. The parser generation feature of
class dictionary on the other hand generates methods for parsing the language
defined by the class dictionary. Thus, it adds nodes and edges in the static
call graph by generating Java code. In effect, DemeterJ has factored out the
regularities in the parser code. Therefore, the parser generation feature of
class dictionary has a FC Relationship between class dictionary and static call
graph.

A strategy is a type of graph that specifies how a
traversal should be created given a class graph. A strategy is applied on a
class graph and yields a traversal graph as shown in Figure 78. An example strategy, "from Company to
Salary" is a strategy that has two nodes Company and Salary. The source of
the graph is Company and the destination of the intended traversal would be
Salary. In a way, strategy graph specifies all possible traversal graphs, which
is similar to the way the class graph specifies all possible instances of the
object graph. Thus, a strategy graph is the result of factorization of the
traversal graph and there is a FC relationship between the two concepts.

The traversal graph, result of applying a strategy graph
to a class graph, is actually a subgraph pattern that is evident in the class
graph. Thus, the class graph specifies all the possible traversal graphs,
analogous to the class graph and object graph relationship. Therefore, the
class graph has a FC relationship with the traversal graph. Strategy graph also
has a FC relationship with the traversal graph as well, because of the similar
relationship between strategy graph and the traversal graph.

Another feature of the traversal graph in DemeterJ is that
DemeterJ uses the traversal graph to generate Java code that executes the
traversal. In effect, it factors out the regularity of the traversal methods
and it is described in a more compact form by the traversal graph. Thus,
traversal graph also has a FC relationship to the static call graph.

As illustrated in Figure
34, visitors in DemeterJ can be thought of as entities
that traverse through an object graph using the traversal graph as a map. As
the visitor is traversing, the object graph, it invokes advices on particular
object types. Similar to the way advices are invoked in AspectJ. The body of
the advice specifies the work that the visitor will accomplish during the
traversal. Thus, visitor has a collection of advice.This implies that visitors allow the programmers to organize the
advices within DemeterJ. Therefore, there is an OC relationship between visitor
and advice.

The differentiation between the traversal graph and the
visitor is analogous to the data structure/algorithm differentiation in the
four graphs of the 4GMP. The traversal graph is the particular data structure
in which the programmer wants to traverse and the visitor is the algorithm that
the programmer wants to execute during the traversal. Therefore, there is an OC
relationship between traversal graph and the visitor.

The CR diagram of DemeterJ from the DemeterJ features
discussed is shown in Figure
79. It does not take into account all of the features of
DemeterJ, only the basic features that were discusses in this section.

From the CR diagram of DemeterJ feature shown in Figure 79, we can see that there are many FC relationships. This
seems like an idea situation for a programming language, until one examines the
scoping of the features. The source of the FC relationships is the class
dictionary and DemeterJ only generates traversals using the class dictionary.
There is no DemeterJ feature that allows programmers to factor code that is not
dependent on the class graph. Therefore, adding such feature would fill a gap
in the DemeterJ’s set of features.

We have combined the graphs from AspectJ and Demeter to
create the Four Graph Model of Programs (4GMP) in this chapter.. By analyzing
these four graphs class graph, object graph, static call graph and dynamic call
graphs, we have formulated two type of concerns factorizational concern (FC)
and organizational concern. The organizational concern features allow
programmers to organize the code in different ways. The way Demeter allows
programmers to separate the data structure description from the algorithm is an
example of the organizational concern feature. Meanwhile, the factorizational
concern allows programmers to factor commonalities from the program. Feature
that allows factorization tends to allow programmers to specify a specification
and an input to create large regular output. The relationship between the class
graph and the object graph is an example of a factorizational concern
relationship.

We also presented a third concern, the Specification
Concern (SC). This is a concern that allows programmers to specify different
things within the tool. Things such as values, method names, join points,
function pointers, etc. are all things that maybe specified within programming
languages and are SC features.

With these three concerns, FC, OC and SC we may create a
concern relationship diagram. These diagrams allow AOP tool developer to
visualize how different features address the three concerns. From this
visualization, analysis of the available features is possible. This analysis in
turn can be used for feature inclusion decisions. This proposed feature
analysis methodology shows much promise from its application to the small set
of AspectJ and DemeterJ features. However, there are much research need to be
conducted in this area to make this methodology useful.

In this thesis, we have presented many different
experiments, concepts, analysis and results. First, we included the thesis
proposal to illustrate the purpose of this thesis. Then, we introduced the AOP
tools Fred, AspectJ, DemeterJ, and DJ. After that we presented out first
experiment that translates examples written in Fred to a graphical notation and
AspectJ. The ease in which we were able to translate Fred examples to AspectJ
led us to the possibility that code written in DemeterJ maybe translated to
AspectJ and vice versa. We found that DemeterJ code was translatable to
AspectJ, but we needed to add a new feature called guide and language features
to DemeterJ in order to translate AspectJ code to DemeterJ. From there, we
started to analyze the JPM and the Traversal Model of programs to find out more
about how these two views of programs are related. The analysis concluded that
the two metaphors may describe each other and that the two metaphors could be
applied at the same time. In fact, the programs always had the two metaphors
present, but the features and terminology used in AspectJ and Demeter tools
emphasized one metaphor over the other.

This realization is the theoretical basis for DAJ that
integrates Demeter and AspectJ concepts. The implementation and the traversal
specification language of DAJ were discussed in detail. Then, we did some
performance analysis to compare the relative performance between DemeterJ, DJ
and DAJ traversal implementations. We found that the performance is comparable
to DemeterJ and much better than DJ. Therefore, DAJ is an example of
combinability of AOP concepts from Demeter and AspectJ that implements
traversals that performs well.

From all of these experiments, from DAJ to various
translations, we proposed the Four Graph Model of Programs (4GMP). By
decomposing a program into the four graphs class graph, object graph, static
call graph and dynamic call graphs. From analysis of the relationship between
these four graphs, we proposed factorizational concern and organizational
concern. We postulated that we can use these concern relationships and the 4GMP
to create a concern relationship (CR) diagram that would allow us to visualize
the relationship between different features within an AOP tool. CR diagram was
presented for a small set of AspectJ and DemeterJ feature usage. From the
AspectJ CR diagram creation process, we discovered the third kind of
relationship, specification concern (SC) relationship.

The three relationships, FC, OC, and SC maybe used in
conjunction with the 4GMP to create CR diagrams for features analysis. This proposed
methodology show lost of promise, however, much research is needed in order to
make this feature analysis methodology useful.

This thesis has touched upon many different areas, tools,
and concepts. Nonetheless, all of the work presented thus far has led to the
proposal of a new feature analysis methodology for aspect oriented programming
tools. Because of its relatively young field is gaining momentum, there needs
to be analysis methodologies that will allow designers of the tools to create
useful tools. In order for any analysis methodology to be successful, we
believe that the designers must address the organizational, factorizational and
specification concerns with the features that they add.

Furthermore, there needs to be more research into the
different software development concerns such as the three concerns discussed in
this thesis. Possible new concerns, such as interface concern that deal with
how programs from different organizations interface with each other needs to be
analyzed and discovered. Therefore, there is still much research needed in this
direction.

Jim Hugunin, "The Next Steps for Aspect Oriented
Languages," Workshop on New Visions for Software Design and
Productivity: Research and Applications, 2001,
http://www.isis.vanderbilt.edu/sdp/Papers/Papers.htm