Anthony, 2012/8/24 Anthony Ferrara <ircmax...@gmail.com>
> Peter, > > On Fri, Aug 24, 2012 at 2:36 PM, Peter Nguyen <pe...@likipe.se> wrote: > >> This is exactly the "problem" that AOP solves. I think the decorator >> pattern is just a solution for the shortcoming of the language itself. > > > Actually, I think it's the other way around. Think about this for a > second. With the AOP functionality proposed, it applies to *all* instances > of a class. That's fine, except when you only want to add the functionality > to one instance. > You should of course use the right tool for the job, there's nothing stopping you from using any OOP pattern together with AOP. > >> What if you want multiple advices at that joint point, do you create >> decorator on decorator, call another class inside the decorator, or use the >> observer pattern? Do you need to decorate all your classes before hand just >> to be futureproof? What do you do if you stumple upon code you need to hook >> into with no decorator? > > > No, you just decorate each piece of functionality onto the class. That's > the point of a decorator. You don't need to worry about it, you just wrap > whatever was there. So you can put decorator on top of decorator. You > compose the functionality in layers. > > And "decorate all your classes before hand just to be futureproof?" tells > me you haven't worked with decorators much, as that's a bit of a silly > comment. You decorate to change behavior in a specific way. Let's take > a canonical example: > I was of course exaggerating trying to make my point. Taking a look at your example, it is not really a use case for AOP. For example, you don't apply the Cream class to the User class or the Company class, because it doesn't make sense. But what do you do, when you want to apply a Logging class to all the database actions? Do you really want to decorate all the classes that uses the database? It's even worst when it's somebody else's project. Another thing is that you need to change the calling code to use your new decorator class, what if that code is scattered in your project? You don't need to worry about that if AOP is available. > interface Coffee { > public function getPrice(); > } > class BlackCoffee implements Coffee{ > public function getPrice() { return 1; } > } > class Cream implements Coffee { > protected $coffee; > public function __construct(Coffee $coffee) { > $this->coffee = $coffee; > } > public function getPrice() { return 0.25 + $this->coffee->getPrice(); } > } > class Sugar implements Coffee { > protected $coffee; > public function __construct(Coffee $coffee) { > $this->coffee = $coffee; > } > public function getPrice() { return 0.50 + $this->coffee->getPrice(); } > } > > $creamAndSugar = new Sugar(new Cream(new BlackCoffee)); > $creamOnly = new Cream(new BlackCoffee); > $sugarOnly = new Sugar(new BlackCoffee); > > I didn't de-deuplicate (by creating an abstract decorator) to illustrate > the concept of what's going on. > > So no, you don't create a decorator for every class. You create one for > each class you need to add functionality to, when you need to add > functionality to it. > > If you want to hook into code without a decorator, you write a decorator. > It's that simple. > > >> AOP solves this in a nice way without the need to "pollute" your code. >> Just think of the possiblities, not having to deal with >> do_action/add_action again or to think about all the possible events that >> you need to support in your code for it to be modular. With AOP, you can >> just write your class and feel safe that there will be a way to hook into >> your methods without modifying it if you ever need to. >> > > Actually, I'd argue this the AOP addition is polluting code more, because > it's always global. And global is the antithesis to flexibility (which is > the entire point of AOP after all). If it worked on a per-object level, I > could see that argument. But seeing as it's global at the class level, I > don't think that argument flies. > Saying that because it's global, it's a bad thing doesn't seem to be a valid point in my opinion. There are many global concepts in programming, like Logging/Authorization/Database connections etc. In fact it is one of the strong argument for AOP, because it will not be of much use if you only can point cut the execution of one class don't you think? But I'm in favor of being able to organize aspects into namespace though, it will be a nice addition to the proposal. > Now, as I said in my prior post, I am actually in favor of this change. I > think it can make patching existing architectures and legacy code much > easier. But I wouldn't write new code with it. And I wouldn't say that it's > a good compliment to OOP. It can help in certain situations, but it also > can cause a lot of pain (due to the global nature, and the fact that it is > really just spooky-action-at-a-distance). > http://en.wikipedia.org/wiki/Action_at_a_distance_(computer_programming) > > Anthony >