Aspect Oriented Programming
From Zanecorpwiki
TODO: rewrite existing in terms of "overview", "theoretical underpinnings" and then add "practical applications"; in last, note that some dimensions are often practically entangled. It would, for instance, be possible to persistence a wholly orthogonal concern, but we're not used to thinking in that way so for practical purposes, it might be easier to leave persistence entangled with your domain model (ref: This entangled state is what I call the "business logic"; i.e., domain + entangled concerns = business logic.). Also need tool section.
Aspect Oriented Programming (AOP) is usually described as creating logic around "cross-cutting concerns". I think about it as creating logic around "technical concerns". Either way, it's the difference between business and domain logic vs. technical infrastructure.
To put it concretely: when we design apps, we think about the domain and business logic. If we were building an accounting application, we might think in terms of accounts and transactions. If we were building a prototype or a very simple app, maybe that's all we ever have to think about.
But when we move to "production", we need to think about technical issues that have nothing to do with our domain or business logic. The most important are often logging and error handling, though profiling and other concerns are also typical. It's these technical issues (aka, cross-cutting concerns) that AOP deals with.
Say we wanted (as we would) to log every exception that may be thrown. We would end up writing every method that could possibly throw an exception something like this:
public void someMethod() {
try {
stuff();
moreStuff();
}
catch (RuntimeException e) {
log.error(e);
throw(e);
}
}
Not only would be adding 3-4 lines of code to many methods, if we ever wanted to change how we did logging we'd have that many changes to make. It's a situation that screams for abstraction and modularization, but because we (typically) organize our applications around domain concerns, we have to deal with the technical concerns in this ad-hoc, manual manner.[notes 1]
Aspects essentially allow one to add new modeling dimensions to the code so that you can have two (or more) models operating simultaneously. Though AOP tools often allow you to modify and effect the domain model itself, in most cases you end up working primarily with orthogonal concerns. By which I mean with AOP, you can talk about different aspects of the system (domain model, logging, error handling, etc.) without worrying about any of the other aspects.
Creating these completely independent and orthogonal views of the system simplifies each individual view because you no longer have to jump through contrived hoops to create the desired effects in each of the view. It's the difference between describing a cube within a two-dimensional confine. It's complex and non-intuitive. By adding a new dimension, the cube becomes a simple, intuitive thing.
After adding aspects, our example method is simplified to:
public void someMethod() {
stuff();
moreStuff();
}
and we add an aspect that might look something like:[notes 2]
aspect ErrorLogging {
pointcut allThrowingMethods(Exception e) : select * method throwing exceptions && runtime throw(e);
advice logAllErros() : allThrowingMethods() {
log.error(e);
}
}
Setting up logging for one method was easy, but for 100 methods the AOP approach saves hundreds of lines of code. We can go so far as to precisely quantify the savings.
Without aspects, we are constrained to a single dimensional model. Each additional dimension we need to express in general requires a full cross of features from each dimension. E.g., if we had 10 features in the domain/business dimension, and we needed 2 features in logging, we would require "20 logical work units". If we needed 4 features in another dimension, then that's 80 logical work units. In general, the size of the code grows exponentially with the number of dimensions: O(x^n), where x is a constant (related to the number of features) and n is the number of dimensions in play.
By introducing aspects, we can separate each dimension so that complexity grows linearly: O(n). E.g., with there dimensions of 10, 2, and 4 features we're dealing with only 16 (rather than 80) logical work units.
Notes
- ↑ It's possible in many cases to build in technical conventions, such as running all methods of concern through a dispatcher that implements the cross-cutting concern and uses some kind of reflection to dispatch the actual call. In message passing or loosely bound languages, this approach is not necessarily even that difficult. Aspects are still a more elegant approach, however, because they completely remove the technical concerns from your "regular" code.
- ↑ I'm using a very tortured style based on AspectJ.


