In computing, Aspect-oriented software development (AOSD) is an emerging software development technology that seeks new modularizations of software systems in order to isolate secondary or supporting functions from the main program's business logic. AOSD allows multiple concerns to be expressed separately and automatically unified into working systems.
Traditional software development has focused on decomposing systems into units of primary functionality, while recognizing that there are other issues of concern that do not fit well into the primary decomposition. The traditional development process leaves it to the programmers to code modules corresponding to the primary functionality and to make sure that all other issues of concern are addressed in the code wherever appropriate. Programmers need to keep in mind all the things that need to be done, how to deal with each issue, the problems associated with the possible interactions, and the execution of the right behavior at the right time. These concerns span multiple primary functional units within the application, and often result in serious problems faced during application development and maintenance. The distribution of the code for realizing a concern becomes especially critical as the requirements for that concern evolve — a system maintainer must find and correctly update a variety of situations.
Aspect-Oriented Software Development focuses on the identification, specification and representation of crosscutting concerns and their modularization into separate functional units as well as their automated composition into a working system.
Aspect-Oriented Software Development describes a number of approaches to software modularization and composition including, in order of publication, Composition Filters, developed at the University of Twente in the Netherlands, Subject-Oriented Programming (later extended as Multidimensional Separation of Concerns) at IBM, Feature Oriented Programming at University of Texas at Austin, Adaptive Programming at Northeastern University, USA, and Aspect-Oriented Programming (AOP) at Xerox Palo Alto Research Center. The term aspect-oriented was introduced by Gregor Kiczales and his team at Xerox Palo Alto Research Center who also developed the AOP language called AspectJ which has gained considerable acceptance and popularity within the Java developer community.
Currently, several aspect-oriented programming languages are available for a variety of languages and platforms.
Just as object-oriented programming led to the development of a large class of object-oriented development methodologies, AOP has encouraged a nascent set of software engineering technologies, include methodologies for dealing with aspects, modeling techniques (often based on the ideas of the Unified Modeling Language, UML), and testing technology for assessing the effectiveness of aspect approaches. AOSD now refers to a wide range of software development techniques that support the modularization of crosscutting concerns in a software system, from requirement engineering to analysis and design, architecture, programming and implementation techniques, testing and software maintenance techniques.
Aspect-oriented software development has constantly gained in popularity, and is the subject of an annual conference, the International Conference on Aspect-Oriented Software Development, held for the first in 2002 in Enschede, The Netherlands. AOSD is a rapidly evolving area. It is a popular topic of Software Engineering research, especially in Europe, where research activities on AOSD are coordinated by the European Network of Excellence on Aspect-Oriented Software Development (AOSD-Europe), funded by the European Commission.
The motivation for aspect-oriented programming approaches stem from the problems caused by code scattering and tangling. The purpose of Aspect-Oriented Software Development is to provide systematic means to modularize crosscutting concerns.
The implementation of a concern is scattered if its code is spread out over multiple modules. The concern affects the implementation of multiple modules. Its implementation is not modular.
The implementation of a concern is tangled if its code is intermixed with code that implements other concerns. The module in which tangling occurs is not cohesive.
Scattering and tangling often go together, even though they are different concepts.
Aspect-oriented software development considers that code scattering and tangling are the symptoms of crosscutting concerns. Crosscutting concerns can not be modularized using the decomposition mechanisms of the language (object or procedures) because they inherently follow different decomposition rules. The implementation and integration of these concerns with the primary functional decomposition of the system causes code tangling and scattering.
Figure 1 illustrates a decomposition into classes of the Apache Tomcat web container. The vertical bars in the diagram correspond to different packages in the Tomcat distribution. The length of these bars corresponds to the size of the code of these packages. In Figure 1, the code that corresponds to the classloading concern of the application have been highlighted in red. Classloading in Tomcat is a modular concern with respect to the system decomposition. Its implementation is contained in a small number of classes and is not intertwined with the implementation of other concerns.
Figure 2 represents the implementation of the logging concern in Tomcat. Logging in Tomcat is a crosscutting concern. Its implementation spreads over many classes and packages and is intermixed with the implementation of many other concerns.
Figure 3 represents the UML architecture diagram of a telecom component. Each box corresponds to a process that communicates with other processes through connectors.
Figure 4 illustrates the impact of a coordination concern on the architecture of the system, such as When the system starts up, all parts must initialize successfully, otherwise the system must shut down.
The highlighted box corresponds to a coordinator process. This concern has an impact on the implementation of each process in the diagram. Its implementation crosscuts the implementation of the other processes.
Examples of concerns that tend to be crosscutting include:
Scattering and tangling of behavior are the symptoms that the implementation of a concern is not well modularized. A concern that is not modularized does not exhibit a well defined interface. The interactions between the implementation of the concern and the modules of the system are not explicitly declared. They are encoded implicitly through the dependencies and interactions between fragments of code that implement the concern and the implementation of other modules.
The lack of interfaces between the implementation of crosscutting concerns and the implementation of the modules of the system impedes the development, the evolution and the maintenance of the system.
A module is primarily a unit of independent development. It can be implemented to a large extent independently of other modules. Modularity is achieved through the definition of well defined interfaces between segments of the system.
The lack of explicit interfaces between crosscutting concerns and the modules obtained through the functional decomposition of the system imply that the implementation of these concerns, as well as the responsibility with respect to the correct implementation of these concerns, cannot be assigned to independent development teams. This responsibility has to be shared among different developers that work on the implementation of different modules of the system and have to integrate the crosscutting concern with the module behavior.
Furthermore, modules whose implementation is tangled with crosscutting concerns are hard to reuse in different contexts. Crosscutting impedes reuse of components. The lack of interfaces between crosscutting concerns and other modules makes it hard to represent and reason about the overall architecture of a system. As the concern is not modularized, the interactions between the concern and the top-level components of the system are hard to represent explicitly. Hence, these concerns become hard to reason about because the dependencies between crosscutting concerns and components are not specified.
Finally, concerns that are not modularized are hard to test in isolation. The dependencies of the concern with respect to behavior of other modules are not declared explicitly. Hence, the implementation of unit test for such concerns requires knowledge about the implementation of many modules in the system.
The lack of support for the modular implementation of crosscutting concerns is especially problematic when the implementation of this concern needs to be modified. The comprehension of the implementation of a crosscutting concern requires the inspection of the implementation of all the modules with which it interacts. Hence, modifications of the system that affect the implementation of crosscutting concern require a manual inspection of all the locations in the code that are relevant to the crosscutting concern. The system maintainer must find and correctly update a variety of poorly identified situations.
The focus of Aspect-Oriented Software Development (AOSD) is in the investigation and implementation of new structures for software modularity that provide support for explicit abstractions to modularize concerns. Aspect-Oriented Programming approaches provide explicit abstractions for the modular implementation of concerns in design, code, documentation, or other artifacts developed during the software life-cycle. These modularized concerns are called aspects, and aspect-oriented approaches provide methods to compose them. Some approaches denote a root concern as the base. Various approaches provide different flexibility with respect to composition of aspects
AOP can be understood as the desire to make quantified statements about the behavior of programs, and to have these quantifications hold over programs written by oblivious programmers.
AOP is the desire to make statements of the form: In program P, whenever condition C arises, perform action A over a conventionally coded program P.
Obliviousness implies that a program has no knowledge of which aspects modify it where or when, whereas quantification refers to the ability of aspects to affect multiple points in the program.
The notion of non-invasiveness is often preferred to the term obliviousness. Non-invasiveness expresses that aspects can add behavior to a program without having to perform changes in that program, yet it does not assume that programs are not aware of the aspects.
Filman's definition of aspect-orientation is often considered too restrictive. Many aspect-oriented approaches use annotations to explicitly declare the locations in the system where aspects introduce behavior. These approaches require the manual inspection and modification of other modules in the system and are therefore invasive. Furthermore, aspect-orientation does not necessarily require quantification. Aspects can be used to isolate features whose implementation would otherwise be tangled with other features. Such aspects do not necessarily use quantification over multiple locations in the system.
The essential features of Aspect-Oriented Software Development are therefore better characterized in terms of the modularity of the implementation of crosscutting concerns, the abstractions provided by aspect-oriented languages to enable modularization and the expressiveness of the aspect-oriented composition operators.
Aspect-oriented approaches provide explicit support for localizing concerns into separated modules, called aspects. An aspect is a module that encapsulates a concern. Most aspect-oriented languages support the non-invasive introduction of behavior into a code base and quantification over points in the program where this behavior should be introduced. These points are called join points.
Join points are points in the execution of the system, such as method calls, where behavior supplied by aspects is combined. A join point is a point in the execution of the program, which is used to define the dynamic structure of a crosscutting concern.
The join point model of an aspect-oriented language defines the types of join points that are supported by the aspect-oriented language and the possible interaction points between aspects and base modules.
The dynamic interpretation of join points makes it possible to expose runtime information such as the caller or callee of a method from a join point to a matching pointcut. Nowadays, there are various join point models around and still more under development. They heavily depend on the underlying programming language and AO language.
Examples of join points are
A method call join point covers the actions of an object receiving a method call. It includes all the actions that compose a method call, starting after all arguments are evaluated up to return.
Many AOP approaches implement aspect behavior by weaving hooks into join point shadows, which is the static projection of a join point onto the program code.
Figure 5 illustrates possible join points in the execution of a small object-oriented program. The highlighted join points include the execution of method moveBy(int, int) on a Line object, the calls to methods moveBy(int, int) on the Point objects in the context of the Line object, the execution of these methods in the context of the Point objects and the calls and execution of the setX(int) and setY(int) methods.
The quantification over join points is expressed at the language level. This quantification may be implicit in the language structure or may be expressed using a query-like construct called a pointcut. Pointcuts are defined as a predicate over the syntax-tree of the program, and define an interface that constrains which elements of the base program are exposed by the pointcut. A pointcut picks out certain join points and values at those points. The syntactic formulation of a pointcut varies from approach to approach, but a pointcut can often be composed out of other pointcuts using the boolean operators AND, OR and NOT. Pointcut expressions can concisely capture a wide range of events of interests, using wildcards. For example, in AspectJ syntax, the move pointcut
pointcut move: call(public * Figure.* (..))
picks out each call to Figure's public methods.
cflow poincuts identify join points based on whether they occur in the dynamic context of other join points. For example, in AspectJ syntax cflow(move()) picks out each join point that occurs in the dynamic context of the join points picked out by the move pointcut.
Pointcuts can be classified in two categories:
An advice body is code that is executed when a join point is reached. Advice modularizes the functional details of a concern. The order in which the advice bodies contributed by aspects (and by the base) may be controlled in a variety of ways, including:
More general ways to describe the ordering of advice bodies in terms of partial-order graphs have also been provided.
When the execution of a join point satisfies a pointcut expression, the base and advice code associated with the join point are executed. The advice may interact with the rest system through a join point instance containing reflective information on the context of the event that triggered the advice, such as the arguments of a method call or the target instance of a call.
Inter-type declarations allow the programmer to modify a program's static structure, such as class members and classes hierarchy. New members can be inserted and classes can be pushed down the class hierarchy.
An aspect is a module that encapsulates a concern. An aspect is composed of pointcuts, advice bodies and inter-type declarations. In some approaches, and aspect may also contain classes and methods.
Aspect weaving is a composition mechanism that coordinates aspects with the other modules of the system. It is performed by a specialized compiler, called a weaver.
Figure 6 illustrates a classic example of a crosscutting concern in a figure editor example taken from the AOSD literature. The example describes an abstract Shape class that can be moved in the editor. Whenever a shape is moved, the display needs to be refreshed. Figure 6 also depicts two Shape subclasses, Line and Point that implement the Shape functionality. The display refresh concern is scattered across the implementation of both subclasses. Figure 7 represents an aspect-oriented implementation of the same system, where an aspect encapsulates the display updating functionality.
The move pointcut descriptor of Figure 7 captures all the executions of the moveBy methods of a subclass of Shape and invokes the display refresh functionality after the execution proceeds. The concern is modularized, which makes it easier to evolve and maintain.
Aspect-oriented requirement Engineering (also referred to as "Early Aspects") focuses on the identification, specification and representation of crosscutting properties at the requirement level. Examples of such properties include security, mobility, availability and real-time constraints. Crosscutting properties are requirements, use cases or features that have a broadly-scoped effect on other requirements or architecture components.
Aspect-oriented requirements engineering approaches are techniques that explicitly recognise the importance of clearly addressing both functional and non-functional crosscutting concerns in addition to non-crosscutting ones. Therefore, these approaches focus on systematically and modularly treating, reasoning about, composing and subsequently tracing crosscutting functional and non-functional concerns via suitable abstraction, representation and composition mechanisms tailored to the requirements engineering domain.
Specific areas of excellence under the denominator of AO Requirements Analysis are:
Aspect-oriented system architecture focuses on the localization and specification of crosscutting concerns in architectural designs. Crosscutting concerns that appear at the architectural level cannot be modularized by redefining the software architecture using conventional architectural abstractions. Aspect-oriented system architecture languages propose explicit mechanisms to identify, specify and evaluate aspects at the architecture design level.
Aspect-oriented architecture starts from the observation that we need to identify, specify and evaluate aspects explicitly at the architecture design level. Aspectual architecture approaches describe steps for identifying architectural aspects. This information is used to redesign a given architecture in which the architectural aspects are made explicit. In this regard, specific areas of excellence are:
Aspect-oriented design has the same objectives as any software design activity, i.e. characterising and specifying the behavior and structure of the software system. Its unique contribution to software design lies in the fact that concerns that are necessarily scattered and tangled in more traditional approaches can be modularized. Typically, such an approach includes both a process and a language. The process takes as input requirements and produces a design model. The produced design model represents separate concerns and their relationships. The language provides constructs that can describe the elements to be represented in the design and the relationships that can exist between those elements. In particular, constructs are provided to support concern modularization and the specification of concern composition, with consideration for conflicts. Beyond that, the design of each individual modularized concern compares to standard software design.
Here, specific areas of excellence areas are:
AOP includes programming techniques and tools that support the modularisation of concerns at the level of the source code.
Just like any other programming language, an aspect-oriented language typically consists of two parts: a language specification and an implementation. Hence, there are two corresponding areas of excellence: support for language developers and support for application developers.
Support for application developers
An aspect-oriented approach supports the implementation of concerns and how to compose those independently implemented concerns. While the specification of such a language is the primary manual for application developers, it provides obviously no guarantee that the application developer will produce high-quality aspect-oriented programs. Specific areas of excellence:
Support for language developers
Excellence on support for constructing aspect languages includes the following areas:
Formal methods can be used both to define aspects semantically and to analyze and verify aspect-oriented systems. Aspect-oriented programming extends programming notations with aspect modules that isolate the declaration of when the aspect should be applied (join points) and what actions should be taken when it is reached (advice). Expertise in formal semantic definitions of aspect constructs is useful for language designers to provide a deep understanding of the differences among constructs. Aspects potentially can harm the reliability of a system to which they are woven, and could invalidate essential properties that already were true of the system without the aspect. It is also necessary to show that they actually do add intended crosscutting properties to the system. Hence, numerous questions of correctness and verification are raised by aspect languages. Among the kinds of expertise are:
Each of the above approaches can be used to
Although some approaches are already used in aspect languages, others are still subject of research and are not ready for routine industrial application. Nevertheless, awareness of these issues is essential for language designers, and for effective use of aspects, especially in safety-critical contexts.
Middleware and AOSD strongly complement each other. In general, areas of excellence consist of