Aspect-Oriented Programming

Gregor Kiczales

Xerox PARC
3333 Coyote Hill Road
Palo Alto, CA 94304
Tel: (415)812-4888
Email: gregor@parc.xerox.com
http://www.parc.xerox.com/gregor

Abstract

To date, the primary idea for organizing software systems has been to break the system down into functional modules such as subroutines, procedures, objects, clients and servers etc. But many issues of concern to programmers don't cleanly follow these modularity boundaries-they don't "fit" naturally into these abstractions.

We propose a new programming paradigm, called Aspect-Oriented Programming, that allows programmers to express each of the different issues they want to program in an appropriately natural form. A special kind of compiler called an Aspect Weaver(TM) then automatically combines those separate descriptions into a final executable form.

By enabling engineers to reason and program using the natural aspects of concern for a system, even when those cross-cut both each other and the resulting executable code, we believe that Aspect-Oriented Programming can make it possible to program future extremely complex systems, as well as significantly improving software reusability.

Keywords: Abstraction, modularity, concrete components, repositories, complexity, cross-cutting, generation, transformations.

Workshop Goals: To discuss the issues that arise in real software systems, and what kinds of language and tool support can best support dealing with them.

Working Groups: Validation of Reuse Economic Models: Issues and Actions, Domain Engineering Tools, Reuse of the Earliest Life-Cycle Artifacts, Object Technology, Architectures, and Domain Analysis: What's the Connection? Is there a connection?

1 Background

The goal of my work is to enable programmers to develop clean expressions of how they intend a system to work. I want to be able to write programs that clearly capture all of the design decisions the programmer makes. I want those decisions to be captured in a way that allows the programmer to think about them together or in relatively isolation, and to change them as separately as is inherently possible.

My work is positioned between the traditional programming language, software engineering and systems communities. I am interested in programming language solutions, but only those that address the reality of real systems, including not only technical programming concerns (i.e. performance), but also social design and life-cycle concerns (i.e. integration with existing methods, ability of existing technical staff to learn the new approach).

With Danny Bobrow and Jim des Rivieres I developed the concept of metaobject protocols. As presented in [1], a metaobject protocol is an auxiliary interface to a programming language that allows programmers to adjust the language's semantics and implementation to better suit their needs. (I say concept because some languages with metaobject protocols existed before our work. Our contribution was to make the nature and crucial properties of a metaobject protocol more clear.)

I developed the concept of Open Implementation, a set of design principles that support the design of reusable modules that need help from their clients in choosing their implementation strategy [2]. (Again, some examples of such systems predate our work, our contribution was to develop the general design principles.)

My recent work on Aspect-Oriented Programming is an outgrowth of the prior projects, and is my most aggressive effort to date to make programs clearly capture all of the important design decisions in a system.

2 Position

To date, the primary idea for organizing software systems has been to "functionally decompose" systems into modular units such as subroutines, procedures, objects, clients and servers etc. The composition model inherent to this kind of modularity is that application or "glue code" can call the different units, which it tailors by passing parameters. (Biggerstaff, in a WISR-7 position paper, calls this kind of modularity "structurally static components" [3].)

We claim that this style of modularity is an obstacle to widespread software reuse, and in fact to the development of many systems where reuse is less of a concern. The reason is that this approach forces all aspects of the software's behavior to be handled using the same modularity mechanism. But, unfortunately, it is often the case that not all of the important system aspects have the same natural modularity-whereas one decomposition might work well for capturing the basic functionality of an application, another might be best to capture the failure handling mechanism, or the distribution strategy, or the power consumption strategy.

As an initial simple example, consider a simple database application. Traditional functional decomposition of such a system is simple-the application code builds on top of the database system, which in turn builds on top of an operating system. But now consider the working set of the application, or rather the working set of the application as it performs a simple task. The same functional decomposition is not a good way of thinking about, much less controlling, the working set. The working set isn't localized in any of the existing modules. Rather, working set is an issue that cuts across the traditional module structure.

As a solution to these kinds of problems, we are proposing the notion of Aspect-Oriented Programming (AOP) [4, 5]. AOP works by allowing programmers to first express each of a system's aspects of concern in a separate and natural form, and then automatically combine those separate descriptions into a final executable form using a tool called an Aspect Weaver(TM).

Example

As an example of the kind of problem we are intending AOP to address, consider a simple distributed digital library. Such a system would consist of scanners, printers, disk farms and workstations, distributed around local and remote networks. The functionality of such a system is to allow users to maintain and work with a large collection of documents, stored in a variety of digital forms.

In such a system, the basic functionality is quite amenable to being captured using object-oriented technology. The objects would be things like the individual documents, their representation in different formats (.doc, OCR ouput, scanned, pdf etc.), users, workstations, printers, scanners etc. The messages would be operations like print a given document on a given printer, run an OCR on a given document etc.

But now consider the communication strategy for the system. In a distributed system like this one, it is crucial that the programmer ensure that the network is used efficiently. In particular, the programmer must be sure that when large objects are passed as parameters to remote message sends, they aren't copied needlessly. Instead, a remote pointer to the object must be created and passed instead.

The abstract design of such a strategy is a relatively straightforward task. But, implementing that strategy together with the basic functionality is much more problematic. The code ends up being full of conditionals that test for cases like "if I'm a library, and a printer just asked me for a book, send the PDF along because I know it will want it."

What is going on is that the programmer is trying to work with both modularities, but because these two different aspects of the system's behavior cross-cut each other the code ends up being a tangled mess. It ends up being very difficult to understand the functionality and communication strategy separately from each other, or even to understand whether a given line of code is concerned with one or the other.

One way to picture the cross-cutting here is shown below. The solid blue circles represent the objects and the containment relationships among them. (Messages are not shown explicitly in this picture.) The other lines enclose all the objects that should be copied to a particular machine. Note that some objects are copied to multiple machines and some objects have some of their sub-objects copied but not others-the copying is related to, but doesn't line up neatly with the object containment structure at the heart of the basic functionality.

Aspect-Oriented Programming

The are two key differences between AOP and programming technologies based on functional decomposition:

* AOP allows the different aspects of a system's behavior to be expressed separately and in their most natural form, even when they cross-cut each other. Examples of the kinds of aspects we believe AOP should allow programmers to think and program in terms of include:

Domain:    distributed             image processing        operating          
           computing                                       systems            
Aspects:    what the objects do    operations on pixel      resource          
                                  maps                     utilization        
                                                                              
            their location         control structure        caching           
                                                                              
            communication          memory usage             security          
                                                                              
            synchronization        sharing                                    

* In AOP, the different source program modules, which we call Aspect Description Programs (ADPs) do not have the strong correspondence to blocks of executable code that the different kinds of modules in functional decomposition have.

3 Comparison

Work on Program Slicing is similar to AOP in that it recognizes the way that a given segment of program text may actually be a cross-cutting tangle of different issues. Program slicing makes it possible to tease out some of these different aspects of a program's functionality. Work on program slicing differs from AOP in two important ways: (i) it works with programs written entirely in the same language, and (ii) it is analytic rather than constructive in nature. One result of this is that the slices program slicing tools make available tend to be defined in terms of the common language, i.e. accesses to a given variable, callers of a specific function, dependents of a given module etc.

There are systems that are more like our concept of AOP, in that the aspectual decomposition is constructive rather than analytical. Much of the work in the area of reflection can be viewed in this way. In this work, there is partial aspectual decomposition between "base" code, which looks like a program written in a traditional high-level language and "meta" code, which affects how the base code is implemented. Whereas the subject matter of the base code has to do with the specific domain of the program (i.e. paychecks, scanned document images), the subject matter of the meta-code has to do with the semantics and implementation of the language the base code is written in. The effect of the meta-code inherently cross-cuts the base-code[[arrowhorizex]]the two kinds of code deal with a different cut on the overall system's behavior. This is what give reflective techniques their appeal. For example, meta-code can have easy access to every message send, or every message send across machine boundaries. The base code on the other hand only has easy access to particular message sends (actually only to the initiation and receipt of the message, not its actual transmission). Different researchers have explored a wide variety of different metaobject protocol architectures to provide different relationships between the base- and meta-levels [6,7,8].

Biggerstaff's notion of second order reuse libraries [3] is quite similar. The emphasis of his research is on general-purpose transformations of a base program to tailor it to specific needs.

Adaptive Programming (AP) is an example of an AOP-like system [9]. AP is focused on separation between algorithm and data structure, but it allows greater separation than traditional ADT techniques. The operations are written in a highly data-structure neutral way, by having them access the object structure (class graph) using a kind of relational query language. This allows the same operation to be reused with different concrete data-structures. There is an explicit weaving step, in which the operations are tailored to a specific set of data structures, making sure there is no remaining runtime overhead from the strong separation.

Composition Filters (CF) [10] can also be seen as a specific case of AOP. In CF, the filters provide separate control over typical cross-cutting aspects such as communication, synchronization etc. Work on composition filters (like work on adaptive programming) has focused on the OO domain. The filters work by intercepting messages that an object receives and "filter" these messages to allow for compositionally.

The Synthetix[11] project, led by Pu and others, can also be seen as an example of AOP. Synthetix improves operating system performance by specializing OS code based on application invariants that only become known at run-time. The effect of individual invariants very much cross-cut the specialized code. Knowing, for example, that a file is being opened read-only cuts through the entire file system structure. The weaving in Synthetix makes extensive use of partial evaluation technology, much like some of our weavers do.

References

[1] Kiczales, G., J.d. Riveres, and D.G. Bobrow, The Art of the Metaobject Protocol. 1991: MIT Press.

[2] Kiczales, G., et al. Open Implementation Design Guidelines. in Proceedings of the International Conference on Software Engineering. 1997. (Forthcoming).

[3] Biggerstaff, T. The Library Scaling Problem and the Limits of Concrete Component Reuse. in Proceedings of the Third International Conference on Software Reuse. 1994. Rio de Janeiro, Brazil.

[4] Kiczales, G., et al. Aspect-Oriented Programming. in Proceedings of the 7th POPL Workshop on Domain Specific Languages. 1997. Paris.

[5] Kiczales, G., et al., Aspect Oriented Programming, . 1996, Xerox PARC: http://www.parc.xerox.com/spl/projects/aop/position.htm.

[6] Yokote, Y. The Apertos Reflective Operating System: The Concept and its Implementation. in Proceedings of the 8th Conference on Object-Oriented Programming: Systems, Languages, and Applications. 1992.

[7] Okamura, H., Y. Ishikawa, and M. Tokoro, Metalevel Decomposition in AL-1/D, in Proceedings of the International Symposium on Object Technologies for Advanced Software, N.a. Yonezawa, Editor. 1993, Springer-Verlag. p. 110-127.

[8] Okamura, H. and Y. Ishikawa, Object Location Control Using Meta-level Programming, in Proceedings of European Conference on Object-Oriented Programming (ECOOP), T.a. Pareschi, Editor. 1994, Springer-Verlag. p. 299-319.

[9] Lieberherr, K.J., I. Silva-Lepe, and C. Xaio, Adaptive Object-Oriented Programming Using Graph-Based Customization. Communications of the ACM, 1994. 37(5): p. 94-101.

[10] Aksit, M. and e. al. Abstracting Object Interactions Using Composition Filters. in Proceedings of the European Conference on Object-Oriented Programming, Workshop on Object-Based Distributed Programming. 1993: Springer Verlag.

[11] Pu, C., et al., Optimistic Incremental Specialization: Streamlining a Commercial Operating System, in the 15th ACM Symposium on Operating Systems Principles (SOSP'95). 1995.

Biography

Gregor Kiczales is a Principal Scientist at the Xerox Palo Alto Research Center. He is the manager of the Embedded Computation Area, whose long-term goal is to learn how to program smart matter. At present, his primary focus is on Aspect-Oriented Programming. Prior to that, he invented the concepts of open implementation and metaobject protocols. He is the author (with Jim des Rivieres and Danny Bobrow) of ``The Art of the Metaobject Protocol,'' a book describing metaobject protocols, their design and use, and the de-facto standard CLOS Metaobject Protocol. He was the developer of PCL, a portable implementation of CLOS that ran on over 12 different Common Lisp platforms. Before coming to PARC he attended MIT, where he worked with Hal Abelson on computing environments for educational systems.