A query operation. In one aspect, you describe how to delegate the query to other queries. In another aspect you describe the evaluation strategy: early evaluation (i.e. add a member attribute), cached or late evaluation. Writing queries this way allows you to ignore questions of efficiency and concentrate on the function. A DFD can be useful for viewing the query chain in the absence of any evaluation strategy. -- Dave Whipp
The presentations at www.parc.com , which present AOP and AspectJ together. They combine good illustrations with source code and screenshots of, for instance, how AspectJ allowed them to add a debugging "trace" to a Java-based videogame. Shows how AspectJ integrates with IDEs, javadoc, etc. -- Larry Obrien
The examples of aspects the slides use are (a) concurrency properties--e.g. whether deadlock occurs is not a property of any one line of code; (b) bandwidth requirements--specifically, they want to treat large (parts of) objects differently from small ones irrespective of any other modularization criteria. They draw analogies with static versus dynamic properties of a wooden bridge, and time/voltage versus frequency spectra in Fourier analysis. -- Dave Harris
A bean aspect. dev.eclipse.org . The connection aspect is what you'd want to be looking at. -- Brian Bray, Anonymous Donors
See aosd.net for a list of projects working on different variations of AOP. -- Stanley Knutson
Perhaps we could use an easy, canonical example of why someone might need AOP. Here's my attempt:
Three months into a project, the user asks for highly specific logging. For some reason, they want to log instantiation of a bunch of different classes, but these classes are spread out across all sorts of domains. You can't use inheritance, since they all inherit from different objects.
The AOP way to solve this is:
Write your logging code in a sort-of meta-language.
Have your build process include a code-weaver, which parses your meta-language and changes the necessary parts of your source code before compilation.
This way, you've solved the problem without abusing inheritance, and without having to change 50 classes by hand.
The canonical examples are pretty compelling (logging, synchronization, billing, security access across class boundaries) but there are any number of possibilities. I realized a need for something like this approximately two years ago when developing a SmartProxy and SmartSkeleton class for a family of servers but didn't have a name for what I was looking for. These classes would handle dynamic failover completely transparently to the calling code. It worked but involved wrapping and maintaining the interfaces over time which became a real pain.
With an aspect, I could have defined before() and after() advice (using AspectJ-speak) that caught and re-routed any failed attempt whatever method was being called, return to the primary server when it was restarted, etc. It would have taken about 20 lines of code compared to 20 lines of code * the number of interfaces * the number of methods in the interfaces. It would move with interface changes over time and support evolution of the advised behavior(perhaps adding rolling back of transactions if no server were available to satisfy the call).
Another example: If you are creating an ASP-based service, you could easily instrument your code to charge certain rates for time spent in value-added code and different rates or nothing at all for time spent in JDK core code. Whatever your billing policy was it could easily change over time with minimal impact.
-- BrianSletten
Let me try to make this a bit more concrete. I have written a text editor which have around 20 "transformations" which the user can apply on the selected text. If no text is selected, it often makes sense to apply the "transformation" to the current character, word or line.
So instead of having each of these transformations start by checking if text is selected, and if not, select the proper unit, I would prefer to put this in as a BEFORE() -- likewise, if text wasn't selected, not text should be selected after the transformation, this however require that some state info can be transferred from my BEFORE() to my AFTER(). Furthermore, the BEFORE()-code somehow needs to know which buffer the transformation is supposed to work on (so that it can select in this buffer).
This, I'm sorry, this is exactly where OOP and AOP come from and lead to. You shouldn't be repeatedly writing the selection-checking code inside each transformation object, it should be called before you do a transformation. You can do this easily (and cleanly) with the most simple of imperative languages, you do not need a new paradigm. You never did.
There are other examples where BEFORE()/AFTER()-code becomes useful. For example, normally the run-loop is running, it gets e.g. some input from the user, which results in a method being invoked on my controller -- this may lead to all sorts of nested method invocations, but whatever method is the first, should "merge" the undo stack on exit, so that all the work done, is undone as a single event.
There are many different entries to my controller, so this would require some sort of nesting counter which was incremented in BEFORE() and decremented in AFTER(), and if zero, it would "merge" the new entries on the undo stack.
So all in all I am very hooked on this AOP, but so far I have not figured out if it will ever work in real life (for other than add debug traces to each function or other relatively "simple" stuff, which I can more or less already do by defining "{" to "{ BEFORE();" and "}" to "AFTER;}" :-)
So could something comment on what the expected state of AOP is in e.g. 2010, and if it will ever see its way into existing languages like Cee Plus Plus? -- Anonymous Donor
Could someone provide different examples to clarify AOP? I am writing from the perspective of one who knows absolutely nothing about AOP but a little about OO patterns. Having only the above examples, I do not see why AOP is new or advantageous, at least in environments that support inner classes. Consider the SmartProxy example above. Couldn't you do the following (in Java or .NET, anyway)?
Declare an abstract class with a public foo() method.
Write the foo() method to be three calls:
before(), foohook(), and after().
Make foohook() an overridable method that acts just like foo(), i.e., it has the same signature, and the arguments to foo() are passed through to foohook().
The class contains implementations of before() and after().
Then, each time you need something to be wrapped by calls to before() and after(), create an anonymous inner class that subclasses foo's class and overrides foohook(). The override will be wrapped. [There's a little more work to be done to give foo() a general signature, but I think the point stands.]
Thus, the problem of "20 lines of code * the number of interfaces * the number of methods in the interfaces" doesn't motivate me to investigate AOP, since it seems a solvable problem.
You're halfway there; for the rest, rather obviously, "the only difference is that there is no cat."
Perhaps there are subtleties of the deadlock problem, or some other example? -- another Anonymous Donor
This sounds an awful lot decorators (somewhat related to the Decorator Pattern) in Python Language. Short example (not from the Real World):
def makeDec(bar): def _decorator(func): def _wrapper(*args, **kwargs): print "pre", func.__name__, bar, args ret = func(bar, *args, **kwargs) print "post", func.__name__, bar, args, ret return ret return _wrapper return _decorator
#following is the same as: #def decorated(...): #...code here #decorated = makeDec(42)(decorated)
@makeDec(42) def decorated(a, b): return a * b
print decorated(5) #prints "pre decorated 42 [5]\npost decorated 42 [5] 210"
The way I see it, add metaclasses and/or some other hacks to the mix, and you basically have AOP. -- yet another Anonymous Donor
See original on c2.com