Reputation: 5664
Had a discussion with colleagues at work : and we were confused if AOP is somewhat similar to DI as proxy objects come into play @AOP , and read(below) that Spring DI also uses Dynamic Proxies to create objects
http://www.postsharp.net/blog/post/Anders-Hejlsberg-Dead-Body.aspx
All dependency injection frameworks now come with some AOP-like feature: when you require the implementation of an interface, you don’t receive the implementation itself, instead you receive a proxy (called DynamicProxy), and this proxy applies some aspects before invoking the final implementation.
It looks like AOP, it smells like AOP,
but it hardly compares to a fully-fledged AOP framework.
Upvotes: 0
Views: 303
Reputation: 172835
When using DI, AOP will come more natural. You can do this with proxies, but my personal preference is to do this by applying good old decorators.
It looks like AOP, it smells like AOP, but it hardly compares to a fully-fledged AOP framework.
I wholeheartedly disagree with the writer of this statement. In my experience, tools like PostSharp allow you to work around design flaws in your application. That can make those tools very powerful when dealing with legacy applications or with designs that can't be changed (such as dealing with the INotityPropertyChanged
interface for instance). However, while these tools allow you to add AOP features without fixing your design, those design flaws will still haunt you over the lifetime of the project.
One easy example is testability. Tools like these don't address the testability of an application, which is what the Dependency Injection pattern does solve. Since these tools weave in the aspects at compile time, this makes it very hard to test the code without the aspect (which is what you need to do when doing unit testing, and even sometimes when integration testing). You will have to do clever tricks with compiler directives, but this only solves part of the problem, since you still want to test those aspects, but just in isolation, just as you want to test every piece of code in isolation (that's what unit testing is about). And even if you can solve it, your code will still be hard to maintain. That unmaintainable code is caused by flaws in the design.
The author of the article says:
The first issue is that dynamic proxies only allow you to add aspects to the explicit boundaries of a service, the ones you chose to expose as an interface. You can’t add aspects to private or static methods, even if you wanted to.
He's completely right about this, but if you want to add aspects to private or static methods, there's something wrong with your design: fix the design!
The second issue is more dramatic. As you become addicted to some of the benefits of AOP, you start using dynamic proxies even where you don’t need dependency injection, altering the architecture of your code just because of the requirements of dynamic proxy. And this is wrong. AOP does not require you to change the architecture of your code.
And again the author is right: you don't need to alter your architecture for AOP when using PostSharp. But with an incorrect design, applying aspects is still much harder, even with tools as PostSharp. And don't forget that attribute-free AOP with PostSharp is only possible when using the commercial version. Applying AOP using attributes will still lead to high coupling and maintenance problems. All DI tools (for .NET at least) are free to use and attribute-free usage is the default.
There is simply no alternative for good design and when having the correct design tools like PostSharp become redundant for most cases. They can still be beneficial in some edge cases (and can be very beneficial in those cases), but in my experience those cases are rare when your design is SOLID.
Now the question obviously becomes: what is a good SOLID design? There is simply no off-the-shelve, always valid design that you can apply to all applications. Every application I design is different, although for the last few years I’ve seen certain recurring pattern that might be beneficial to you as well. I've written about this in the past here, here and here. The patterns described in these articles have become a fundamental building block in many of the applications I help design and build. The key ingredient of these patterns is SOLID.
Upvotes: 1
Reputation: 26169
No:
1) Dependency injection tools (Inversion of Control containers) often come with AOP/interception tools (e.g. Castle Windsor comes with Castle DynamicProxy), but this is something of a convenience--it's not required for an IoC tool to have this feature.
2) AOP tools can be used without dependency injection. PostSharp, for instance, works on its own, regardless of what IoC tool you use. Another example: You can use Castle DynamicProxy without an IoC container, but I can't imagine many scenarios where you would want to.
(Sorry for using .NET tools in my answer, as I'm not as familiar with Java tools).
Upvotes: 1
Reputation: 692151
I would say that using dependency injection makes AOP, based on dynamic proxies, easier to use, and thus a natural path to follow.
But you can use dependency injection without using AOP at all, and you could use AOP without using dependency injection. BTW, proxies are not used only to implement AOP, but also to resolve circular dependencies or be able to inject smaller-scoped objects (for example, request-scoped objects) into larger-scoped ones (for example, singleton-scoped objects).
Upvotes: 3