3. Static and Dynamic Reference Environments.
Apart from access to global and dynamically allo-
cated local variables, programing languages with
dynamic-free variables, such as Pascal, OCAML
and dialects of Algol, provide function closures
where a function can make direct reference to val-
ues in its closing environment, even when it has
been passed off for remote execution as an upcall
(see following note).
4. Computed Branches and Upcalls. Languages
that enable function pointers to be stored in vari-
ables, which is all modern languages, enable dy-
namic dispatch and remote invocation of these
functions. Where one component stores an entry
in the data-structure of another (often providing a
so-called up-call), this is a cross-cutting feature.
5. Object Static and Dynamic Hierarchy. The static
module inheritance graph of an OO language and
the dynamic, actual instantiation of an object mesh
at run time are both forms of cross-cutting. We note
that Java decided not to provide access to dynamic
function variables that are free in a method be-
cause it instead provides access to the fields in the
surrounding object that may be dynamically allo-
cated almost as easily. Programmers used to SML,
OCAML, Haskell and so on often find this a nui-
sance, but the overhead of providing both a static
chain and an object context, with the former not
likely to be used by contemporary mainstream pro-
grammers, was seen as too great by the Java design-
ers; hence they traded one form of cross-cutting for
another.
6. Long Jumps and Exceptions. Long jumps and ex-
ceptions form another cross-cutting aspect (by our
definition) whose usefulness is well proven.
7. Macro Pre-Processing. The C pre-processor is
used to provide a whole gamet of cross-cutting
facilities, which we list separately below. Pre-
processing is often deprecated because it is crude,
being not type-safe and offering the potential to
make a program unreadable. This paper will hold
that pre-processing should be replaced with a well-
designed, yet simple, ‘meta-programming’ facility
that is a primary part of any compiled HLL.
8. Constructors, Access Functions and Overload-
ing. OO languages allow the user to insert their
own code at points where abstract datatypes are
created, read or otherwise operated on, by writing
constructors and methods bound to overloaded op-
erators. These are useful joinpoints.
9. Templates and Generics. Some would argue that
C++ templates and other similar HLL generics are
these languages that enforces a totally different program-
ming style from that used in all (other) software.
artifacts to overcome antiquated, non-parametric,
type systems, and would suggest using HM (Mil-
ner, 1978) typing instead. However, in whatever
way the type system works, the facility to insert
additional code in the template libraries provides a
form of cross-cutting. Provision of some form of
polymorphism, even just through ‘void
*
’ casts,
is a required cross-cutting form for any HLL used
in a large system.
We assert that the tacit motivation for AOP (aspect-
oriented programming) is that those languages that
do not normally use a pre-processor are restricted be-
cause the remaining parts of the above list are insuffi-
ciently expressive. The sandwich diagram, figure 1,
shows that some cross-cutting requirements can be
met by the facilities of the HLL per se, whereas the
remainder are implemented using some form of meta-
programming. Two forms are shown. Either a pre-
processor is used, by which we imply to include the
operations of this nature performed by an IDE (inte-
grated development environment). This is the upper-
crust approach. Otherwise, customisation of the com-
piler/interpreter is needed. This is the lower-crust
approach. We believe that only one crust is needed
to provide sufficient additional cross-cutting. In our
terms, Aspect-J (Kiczales et al., 2001) is a lower-crust
approach, where modification of the compiler serves
this purpose and the modifications are sufficiently
flexible to provide fairly generic meta-programming.
One can also argue that the lower crust represents a
frequent, major motivation for developing specialised
HLL’s, such as database languages. In the author’s
personal experience, where a project team has worked
on an ML program some 100,000 lines long, occa-
sional customisations to the ML compiler have proved
invaluable when certain cross-cutting requirements
have arisen. These all fall into one of the application
categories listed below.
The C/C++ preprocessor embodies many individ-
ual functions and is defined in terms of multiple
passes of the source files. However, a small and well-
known core of operations is all that is commonly re-
quired. Although most readers of this paper will be
well-familiar with the C preprocessor and its typical
uses, it is worth listing those specific uses here, so
that the reader can consider our assertion, in terms of
each use, that AOP has been an attempt to re-provide
these facilities when a pre-processor is not routinely
used or is deprecated, or the run-time system cannot
be customized. The list also serves as the basis for our
evaluation criteria in the results section of this paper.
The C/C++ pre-processor is commonly used for the
following (cross-cutting) functions. We note that the
majority
2
of these functions can be provided using the
2
When we say the ‘majority’ we could have put ‘all’ be-
cause the residual language is, of course, Turing complete.
ICSOFT 2006 - INTERNATIONAL CONFERENCE ON SOFTWARE AND DATA TECHNOLOGIES
72