Computer Programming/Aspect oriented programming
Aspect Oriented Programming (AOP) is a follow-on development to Object Oriented Programming (OOP), developed with the intention of solving some of the practical limitations of OOP.
OOP aims to manage the complexity of software development by encapsulating data and methods into discrete objects, reducing the dependencies between different software constructs, and polymorphism, or the ability to treat different program constructs as identical for a particular purpose. Overall, the definition of a well-constructed set of objects standing in explicit relationships with each other allows programmers to 'componentize' the software, working at a small, simple, focussed scale, creating constructs that are easily and safely combined into larger constructs for greater functionality.
The practical difficulty with OOP is that, in any large-scale application, there are aspects that are not easily decomposed into objects/components, or easily used as such. "Cross-cutting concerns", or crosscuts, are parts of a larger software project that exist identically in several places, or for multiple objects, where implementing code to answer those concerns effectively breaks encapsulation and increases, rather than decreases, dependencies. AOP aims to reduce dependencies and complexity by moving the code handling those crosscuts into separate programming constructs that can then be woven back into the OOP source code in an automated fashion by a weaver. The result is object oriented code that can then be compiled as normal.
The classic example of an appropriate area for AOP is logging. Often, a programmer will use logging to record the state and flow of a program, both for debugging during development and bug-fixing after deployment. In an OOP program, this takes several possible forms:
- Every object has access to a global logger object, and calls its methods to log events or state.
- All objects requiring logging repeat the same code to write to the log.
- Each object keeps its own log, possibly to a file.
The essential problem here that AOP tries to solve is that the code is repeated in several places, making it difficult to maintain, and increasing dependencies across different constructs. Changing the behaviour of the logger requires, in the second and third cases, rewriting the same code in multiple files; changing the use of the logger requires rewriting the same code in all cases.
By defining logging as a crosscut and using an aspect to solve the problem, the programmer writes the aspect code to handle logging and makes use of a weaver to inject the code into the OOP source, which is then compiled as normal OOP code. The logging function has been removed from the source code for the classes, put into one location, and treated as another single construct that can be locally defined and implemented, and then used discretely in the rest of the program.
In theoretical terms, AOP is the way to implement separation of concerns. Objects are often called upon to handle several conceptually different concerns. An invoice in a sales entry application contains some obvious properties, such as the identity of the purchaser, and the items purchased; but the invoice object may also be required to know how to log its actions, how to persist itself in a database, how to verify the purchaser's credit limit, and how to raise a flag when it is past due. As a result, the invoice class may become large, complex, and difficult to maintain. Each of these concerns is legitimate for the class to handle, but by the principles of OOP must be handled internally and invisibly. If those concerns are shared by other objects with only a distant relationship, then not only do the classes involved have unnecessary complexity, but that complexity is repeated in multiple places.
A few definitions will help:
A cross-cutting concern, or crosscut, is any part of the design of an OOP application that occurs simultaneously in several different parts of the OOP application that are not otherwise related. Logging is the obvious example, but persistence is another one: In a banking application, many different objects must be stored and retrieved in the same way (e.g., a relational database). Persistence is a crosscut on the objects of the application.
A join-point is a semantically definable point in the OOP code that the weaver can identify. For our logging example, the programmer may wish to record the call stack, so the logger should record the entry and exit of every function.
A set of join points are identified, collectively, by a pointcut: The join-points are the actual places in the code that the weaver identifies; the pointcut is the AOP code that defines the join-points to be found.
A pointcut not only identifies join points, but includes code to act on those points. The code is called advice or advices.
An aspect, then, is a set of pointcuts defining a particular crosscut to be handled by the AOP module. In practice, our solution to the logging example is an aspect module that defines pointcuts identifying those join-points where the programmer wants logging to occur. Having identified the join-points, the programmer writes advices into the AOP module, and the weaver injects that code into the OOP source code as a preliminary step to compilation of the code.
At this point, it looks like AOP is nothing more than a way of pulling utility code out of classes and centralizing it; that is one of AOP's virtues. However, AOP can separate much more complex concerns. In our invoice example, we mentioned that invoices have a past due date. Likewise, our own payables might have a past due date. This 'past due' concern could be encapsulated as an aspect that defines pointcuts on the construction or initialization of both invoice and payable objects. At those join-points, a past due date member could be added to both classes, along with code to register the invoice/payable with a past-due monitoring system that generates a daily report of upcoming deadlines. Code for tracking payment deadlines has been moved to a single module, decreasing the complexity of the invoice/payable objects, eliminating a dependency between the invoice/payable classes and the deadline monitoring system, and making maintenance and changes to the system easier.
The most popular platform for AOP is currently AspectJ, an extension to the Java language. It is the language that will be used here for examples.