Aspect-oriented programming
In software engineering, the programming paradigm of aspect-oriented programming (AOP), also called aspect-oriented software development (AOSD), attempts to aid programmers in the separation of concerns, or the breaking down of a program into distinct parts that overlap in functionality as little as possible. In particular, AOP focuses on the modularization and encapsulation of cross-cutting concerns.
Gregor Kiczales and his team at Xerox PARC originated this concept. This team also developed the first, and still most popular, AOP language: AspectJ.
Older programming methodologies—including procedural programming and object-oriented programming—similarly focus on separation and encapsulation of concerns (or any area of interest of focus) into single entities. For example, procedures, packages, classes, and methods all help programmers encapsulate concerns into single entities. But although these methodologies can successfully encapsulate many software concerns, some concerns defy such easy encapsulation. Software engineers call these crosscutting concerns, because they exist in many parts of the program.
Logging offers the prototypical example of a crosscutting concern, because a logging strategy necessarily affects every single logged part of the system. Logging thereby crosscuts all logged classes, methods, and procedures.
Typically, an implementation of an AOP language seeks to encapsulate these types of crosscutting concerns through the introduction of a new construct called an aspect. An aspect can alter the behavior of the base code (the non-aspect part of a program) by applying advice (additional behavior) over a quantification of join points (points in the structure or execution of a program), called a pointcut (a logical description of a set of join points).
In many AOP languages, method executions and field references all exemplify join points. A pointcut may consist, for example, of all references to a particular set of fields.
Motivation and basic concepts
Aspect-Oriented Programming has at its core the enabling of a better separation of concerns, by allowing the programmer to create cross-cutting concerns as first-class program modules. (Cross-cutting concerns defined as those parts, or aspects, of the program that in standard design mechanisms end up scattered across multiple program modules, and tangled with other modules.)
For example, consider a banking application with a conceptually very simple method for transferring an amount from one account to another:
void transfer(Account fromAccount, Account toAccount, int amount) { if (fromAccount.getBalance() < amount) { throw new InsufficientFundsException(); } fromAccount.withdraw(amount); toAccount.deposit(amount); }
(the examples appear in a Java-like syntax, since at the time of writing, an overwhelming majority of AOP-related research and work takes place in Java or in Java-variants.)
However, in a real-world banking application, this transfer method seems far from adequate. We must include security checks to verify that the current user has the authorization to perform this operation. We must enclose the operation in a database transaction in order to prevent accidental data loss. We must log the operation to the system log. And so on. A very simplified version with all those new concerns would look somewhat like this:
void transfer(Account fromAccount, Account toAccount, int amount) { if (!getCurrentUser().canPerform(OP_TRANSFER)) { throw new SecurityException(); } if (amount < 0) { throw new NegativeTransferException(); } if (fromAccount.getBalance() < amount) { throw new InsufficientFundsException(); } Transaction tx = database.newTransaction(); try { fromAccount.withdraw(amount); toAcount.deposit(amount); tx.commit(); systemLog.logOperation(OP_TRANSFER, fromAccount, toAccount, amount); } catch(Exception e) { tx.rollback(); } }
The code has lost its elegance and simplicity because the various new concerns have become tangled with the basic functionality (sometimes called the business logic concern). The transactions, security, logging, etc. all exemplify cross-cutting concerns.
Also consider what happens if we suddenly need to change (for example) the security considerations for the application. In the program's current version, security-related operations appear scattered across numerous methods, and such a change would require a major effort.
Therefore, we find that unlike the core concerns of the system, the cross-cutting concerns do not get properly encapsulated in their own modules. This increases the system complexity and makes maintenance considerably more difficult.
AOP attempts to solve this problem by allowing the programmer to develop cross-cutting concerns as full stand-alone modules called aspects. In most AOP languages, an aspect comprises one or more pieces of advice (code snippets - like methods) and a list of join points (points in the main program into which the advice should be woven). For example, a security module can include an advice that performs a security check, with instructions to weave this code snippet into the beginning of methods a(), b() and c() of some class. Powerful mechanisms deploy to enable a broad specification of join points, so that developers need not enumerate weaving-destinations manually. These mechanisms are commonly known as pointcut specification languages.
Join Point Models
Fundamentally, the way an aspect interacts with the base program is defined by the join point model (JPM) that the aspect is written in. A JPM defines three things:
- Where the aspect can apply. These are often called join points.
- A way to specify (or quantify) multiple join points. These are often called pointcuts. Pointcuts are effectively a query over all the join points of a program to select a small sub-set of them.
AspectJ has two JPMs: pointcuts and advice, and inter-type declarations. Other aspect languages have different JPMs.
The Pointcuts and Advice JPM in AspectJ
- The join points in this JPM are well-defined points along the execution of a program. This can include: method execution, the instantiation of an object, and the throwing of an exception. Note that these join points are dynamic in nature and can only be discovered at runtime. Hence, the pointcuts and advice JPM in AspectJ is known as a dynamic join point model.
- Pointcuts are specified by a query over the program. One such pointcut looks like this:
pointcut set() : execution(* *.set*(..) ) && this(Point);
- This pointcut specifies all joinpoints corresponding to the execution of any method starting with
set
when the currently executing object is of typePoint
.
- Advice is specified in a way that is similar to a method. However, advice is never explicitly invoked. It is only invoked when the pointcut attached to it is evaluated to true. Here is an example of this:
after() : set() {
Display.update();
}
- It says that after the set() pointcut evaluates to true execute the command(s) specified in the body of the advice.
Inter-Type Declarations in AspectJ
The second JPM in AspectJ is known as inter-type declarations. This is a mechanism that allows an aspect to add extra declarations to an existing class or object. This concept is known as open classes . An inter-type declaration looks like this:
aspect VisitAspect {
Point.acceptVisitor(Visitor v) {
v.visit(this);
}
}
- This code snippet adds the
acceptVisitor
method to the Point
class.
- The join points are all non-anonymous types in the program.
- The pointcuts are the names of classes or interfaces.
- The means of affecting change at the pointcuts are by adding body declarations to the type.
Other Join Point Models
There are other kinds of JPMs. All aspect languages can be defined in terms of their JPM. For example a hypothetical aspect language for UML may have the following JPM:
- Join points are all model elements.
- Pointcuts are some boolean expression combining the model elements.
- The means of affect at these points are a visualization of all the matched join points.
Weaving
Weaving - injecting the advice presented in aspects into the specified join-points associated with each advice - provides the final challenge of any AOP solution.
In the original introduction of AOP, Kiczales and his team listed the following possibilities for weaving:
- a source preprocessor (similar to that in the original implementations of C++ )
- a post-processor that patches binary files
- an AOP-aware compiler that generates woven binary files
- load-time weaving (for example, in the case of Java, weaving the relevant advice as each class gets loaded into the Java virtual machine (JVM))
- run-time weaving (trap each join point at runtime, and execute all relevant advice)
The first two options complicate the development process, whereas the last two options may slow down the program's execution. The last option (run-time weaving) also requires a special aspect-aware execution environment. In the world of Java, this implies a special JVM or other supporting framework.
AspectJ currently uses a dedicated compiler solution. The compiler generates standard Java binary class files, which any standard JVM can execute. Load-time weaving will be added in an upcoming release as the result of the merger of AspectJ and AspectWerkz.
All of the listed weaving solutions (except the last) imply changing the code at some point; the code generated for a given Java class by the compiler (after processing and/or loading) does not equate to what a standard Java compiler would have generated, since it now contains woven pieces of advice code. Many view this as a major drawback of AOP, because it complicates both the programmer's understanding of the program execution model and the use of any standard, existing tools, such as debuggers (see also "Problems", below).
Cohen and Gil have produced a novel alternative: they present the notion of deploy-time weaving. This basically implies post-processing, but rather than patching the generated code, they suggest subclassing existing classes so that the modifications are introduced by method-overriding. The existing classes remain untouched, even at runtime, and all existing tools (debuggers, profilers, etc.) can be used during development. A similar approach has already proven itself in the implementation of many J2EE application servers, such as IBM's WebSphere.
AspectJ: an AOP language
AspectJ is an aspect-oriented extension to the Java programming language.
AOP and other programming paradigms
Aspects emerged out of object-oriented programming and have functionality similar to meta-object protocols. Aspects relate closely to programming concepts like subjects, mixins, and delegation. Other ways of using aspect-oriented programming paradigms include Composition Filters and the hyperslices approach.
Mathematically, aspects form a second-order extension of any programming paradigm: while usual programming paradigms allow reasoning about single functions, messages and so forth by a function/message signature, AOP enables reasoning about entire sets of those entities by using pointcuts with wildcards in their signature. Thus one could view AOP as a powerful, logical extension, rather than as an independent paradigm. Friedrich Steimann, for example, has proposed such a view.
But AOP proponents promote it as an external package shippable along with some application. For example, if a program itself has no support for security, an AOP package can serve as a modular extension to the application, providing security.
Problems for AOP
Debugging can become one of the greatest problems for AOP. While at the syntactic level AOP program code appears separate, at run-time it is not. Concern-weaving can become unpredictable if it is not specified which aspect should dominate. Designers have considered alternative ways to achieve separation of code, such as C#'s partial types. However, such approaches lack a quantification mechanism enabling programmers to reach several join points of the code with one declarative statement.
Another problem for AOP is the unintentional capture of joinpoints through wildcards. For example, suppose we specify a pointcut with associated advice as a wildcard on all methods that have a certain pattern to their spelling. A programmer who creates a new method may unwittingly choose a name to which the advice will - incorrectly - apply. Similarly, renaming a method can completely change its semantics. Must all programmers who modify the codebase over its lifetime learn a complex set of project-specific naming conventions in order to avoid such difficulties? An AOP-aware development environment can make the applicability of advice more visible, but it is an open question how such concerns will play out over the lifecycle of aspect-oriented code.
Implementations
- For Java:
- For Python:
- Lightweight Python AOP
- Logilab's aspect module
- Python/Transwarp AOP Tutorial (Replaced by PEAK)
- PEAK
- Pythius
- For Perl:
- For Common Lisp:
- For Cocoa:
- For ColdFusion:
- For Cobol:
Write your own preprocessing system.
- For More Info (real-world implementations):
See also
Publications
- Kiczales, Gregor (1997). "Aspect-Oriented Programming". Proceedings of the European Conference on Object-Oriented Programming, vol.1241. pp. pp.220–242.
{{cite book}}
: |pages=
has extra text (help); External link in |chapter=
(help); Unknown parameter |coauthors=
ignored (|author=
suggested) (help) The paper originating AOP.
- Filman, Robert E. Aspect-Oriented Software Development. ISBN 0-32121-976-7.
{{cite book}}
: Unknown parameter |coauthors=
ignored (|author=
suggested) (help)
- Pawlak, Renaud. Foundations of AOP for J2EE Development. ISBN 1-59059-507-6.
{{cite book}}
: Unknown parameter |coauthors=
ignored (|author=
suggested) (help)
- Laddad, Ramnivas. AspectJ in Action: Practical Aspect-Oriented Programming. ISBN 1-93011-093-6.
- Jacobson, Ivar. Aspect-Oriented Software Development with Use Cases. ISBN 0-321-26888-1.
{{cite book}}
: Unknown parameter |coauthors=
ignored (|author=
suggested) (help)
External links
- Aspect-Oriented Software Development (annual conference about AOP)
- AOSD Wiki (Wiki specifically devoted to AOP)
- AspectJ (Java implementation)
- The AspectBench Compiler for AspectJ (another Java implementation)
- A detailed series of articles about the basics of aspect-oriented programming and AspectJ
- Introduction to Aspect Oriented Programming with RemObjects Taco
- Constraint-Specification Aspect Weaver
- Aspect- vs. Object-Oriented Programming: Which Technique, When?
- Light-weight Approach to AOP for Python