22

I've come across the idea of Aspect Oriented Programming, and I have some concerns with it.

The basic idea seems to be that we want to take cross-cutting concerns which aren't well modularized using object and modularize them. That is all very fine and well.

But the implementation of AOP seems to be that of modifying code from outside of the module. So, for example, an aspect could be written that changes what happens when a particular object is passed as a parameter in a function. This seems to go directly against the idea of modules. I should not be able to modify a module's behavior from outside of that module, otherwise the whole point of modules are overturned. But aspects seem to be doing exactly that!

Basically, aspects seems to be a form of code patching. It may useful for some quick hacks; but, as a general principle perhaps its not something you want to do. Aspect Oriented Programming seems to me taking a bad practice and raising to a general design principle.

Is AOP a good practice? Are certain programming problems solved more elegantly with AOP?

3

3 Answers 3

21

Aspect-Oriented Programming makes it possible to do certain types of programming that are difficult to do without unnecessarily scattering code throughout your application or library that is unrelated to the primary functions of your software (i.e. cross-cutting concerns). Examples include:

  1. Logging and Monitoring
  2. Performance analysis
  3. Debugging and Tracing
  4. Undo Functionality
  5. Validation of inputs and outputs
  6. Morphing the behavior of existing objects
  7. Object Filters
  8. Security Implementation
  9. Managing transactions

By confining such cross-cutting concerns to a single part of the application, and then referencing these features in the code via attributes, method call interception, or dynamic proxies, you allow the encapsulation of the cross-cutting behavior; this has all of the benefits (i.e. a single modification point) encapsulation would provide anywhere else in your application.

The key point here is that AOP encapsulates behaviour that is 1) common throughout the application, and 2) peripheral to the application's primary functionality.

9

Coming in late to the game, but I provide this for later developers who might stumble across this question.

I would strongly advise against AOP if your application depends on it to operate correctly. Aspects work like this:

  • Advice (additional behavior) is applied to
  • Join points (places where the extra code can be attached, such a method start or end, or when a given event triggers)
  • ... where pointcut (a pattern that detects whether a given join point matches) patterns match

For anyone who's been doing computers for a long time, the fact that patterns are used might be something to look at closely. So to here's an example of a pointcut that matches any method named set regardless of the arguments:

call(* set(..))

So that's a fairly sweeping pointcut and it should be clear that handling this with care is advised (no pun intended) because you're applying advice to many things.

Or heck, let's apply advice to everything, regardless of name or signature!

execution(* *(..))

So clearly we should be careful because there's a lot of power here, but this is not an argument against aspects — it's an argument for caution because there's a lot of power here and pattern matching can easily go awry (just hit your favorite search engine for aop bugs and have fun).

So here's what looks like a relatively safe pointcut:

pointcut setter(): target(Point) &&
                   ( call(void setX(int)) ||
                     call(void setY(int)) );

That explicitly provides advice if methods named setX or setY on a Point object are found. The methods can only receive ints and they must be void. Looks pretty safe, right? Well, that's safe if those methods exist and you've applied the correct advice. If not, too bad; it silently fails.

To give an example, a friend was trying to debug a Java application where everyone once in a great while, it would return incorrect data. It was an infrequent failure and didn't appear to be correlated with any particular event or data in particular. It was a threading bug, something that is notoriously difficult to test or detect. As it turns out, they were using aspects to lock methods and make them "thread safe", but a programmer renamed a method and a pointcut failed to match it, thus causing a silent breakage of the application.

Thus, I tell people that if they must use AOP, to treat aspects like exceptions: in a well-designed system and if nothing goes wrong, they can be removed and the software still functions correctly. However, if the functionality of the program depends on AOP, you introduce a fragility to your program that is unwarranted.

Thus, logging, debugging and tracing are great examples of behaviors that are perfect for aspects, but security? Nope. Thread safety? Nope.

For a robust alternative to AOP, see traits. Rather than being bolted onto the language, they are integrated into it directly, don't need a "trait aware" IDE (though it can help) and have compile-time failures if the methods you require are not present. Traits do a much cleaner job of handling separation of concerns because the problem was better defined from the start. I use them extensively and they're fantastic.

2
  • Rather than arguing that AOP shouldn't be used for core functionality, it may be more appropriate to say that pointcuts which rely on method names are a bad idea. I'd probably argue that locking and synchronization are not good use cases for AOP, either.
    – Codebling
    Mar 14, 2014 at 6:36
  • Nine years later, this answer is still applicable. AOP is a fantastic tool, but use it with caution. Another simple illustration is taking the perspective of a developer in a system with no knowledge of current or future advices. How comfortable should that developer be that new functionality will work, both immediately and in the future? When using AOP, consider ways to minimize that impact and concern. Another related answer: stackoverflow.com/a/8607821/1941654
    – Mike Hill
    Jun 10, 2022 at 16:49
3

One situation in which AOP might be the only decent as well as practical solution is when you don't have access to the source code. To use the tired old example of the Logging cross-cutting concern:

Let's say you want to log the flow of control in a third party library you consume. You have your own code fully instrumented with logging statements. However, for this library you don't have the source, making it impossible to add your logging statements. Since you do have the bytecode, AOP allows you to instrument that third party library anyway.

And if you're creating a Logging aspect anyway, you might as well consider implementing Logging with AOP troughout your own code as well.

4
  • Logging is for "interesting" things. How can you do other stuff than "entering with these parameters" and "exiting" with AOP logging?
    – user1249
    Nov 16, 2010 at 5:41
  • @Thorbjorn: Logging/debugging/tracing is just one of many areas of functionality AOP can help with. I used it as an example to illustrate my point. The point I am trying to make is that AOP gives you more control over third party bytecode. Nov 16, 2010 at 5:49
  • sure, but I really wanted to know if AOP logging can do more than just enter-exit logging?
    – user1249
    Nov 16, 2010 at 8:15
  • It depends on the AOP tool you use, but there are certainly limits to what you can do. It might very well be impossible to go beyond enter-exit logging. Nov 16, 2010 at 13:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.