We have found many programming problems for which neither procedural nor object-oriented programming techniques are sufficient to clearly capture some of the important design decisions the program must implement. This forces the implementation of those design decisions to be scattered throughout the code, resulting in “tangled” code that is excessively difficult to develop and maintain. We present an analysis of why certain design decisions have been so difficult to clearly capture in actual code. We call the properties these decisions address aspects, and show that the reason they have been hard to capture is that they cross-cut the system’s basic functionality. We present the basis for a new programming technique, called aspect oriented programming, that makes it possible to clearly express programs involving such aspects, including appropriate isolation, composition and reuse of the aspect code. The discussion is rooted in systems we have built using aspect-oriented programming.
Aspect Oriented Programming (AOP) is intended to enable software engineers to isolate secondary or supporting functions from the main program’s business logic. This can be achieved by focusing on the identification, specification and representation of cross-cutting concerns and their modularisation into separate functional units. Simply put, a cross-cutting concern is the requirement to have some common code (e.g. logging, caching, authentication etc.) executed against a variety of classes without “polluting” those classes with the code required to action such requirements – the aspect code can be maintained outside of the classes it affects. AOP provides the ability to intercept code execution with the purpose of inserting a process before, in place of, or after the code that would normally execute.
An Aspect is the association of a Concern, a Pointcut and a Joinpoint.
- The implementation of a cross-cutting concern is called the Concern.
- The well defined location within a class where a concern is going to be attached is the Joinpoint.
- The place where the joinpoint(s) are specified, either through configuration or code, is the Pointcut.
A Concern is something that is important to one or more stakeholders. Concerns can conceptually be divided into two categories (the implementation for each can be the same):
A side effect: a concern which is not changing the behaviour at the pointcut, they introduce additional actions.
A logging concern is a good example of a side effect:
E.g. each call to the targeted method
will first call the concern
which will be able to run before and after the
Execute method logging such things as start time/end time/total time/in parameters/out parameters etc.
A side effect can:
- Inspect/capture the input parameters at the targeted pointcut as required and action any additional processing
- Inspect/capture the output result at the targeted pointcut as required and action any additional processing
An advice: a concern which will potentially change the input and/or output of the targeted method.
A caching concern is a simple example:
E.g. whenever the run-time executes the targeted method
will be run configured to run first and only allow the call to continue on to the
Repository.Find() method if the value is not found in the cache.
An advice can:
- Inspect the input parameters at a targeted pointcut and modify them if needed
- Cancel or avoid the execution of the targeted method and replace it with a different implementation
- Inspect the output result of the targeted method and modify or replace it as required
Within .NET there are a number of established techniques for implementing AOP:
- Post build IL weaving/PostSharp
- Dependency Inversion (Inversion of Control (IoC) and Dependency Inversion (DI))
PostSharp is undoubtedly the best option for established architectures that have late on realised the need to add cross cutting concerns to a multitude of different interfaces/classes/implementations. It does of course depend on how much of the “aspects” logic are already woven into the existing code base.
PostSharp is also a great option when the aspects need to be applied to a lot of classes/methods/properties. The classic example of this is the infamous
INotifyPropertyChanged. But, again IMHO this is only truly necessary for existing/established code bases.
For new build/green field projects AOP can easily be done with:
- A data dictionary
- Code generators
- A few carefully crafted interfaces
- An IoC Container.