Welcome to Manicprogrammer Sign in | Join | Help

Presenter Wars: Decorators Strike Back

Continuing on the presenter saga, some people got confused as to why I'm leaning on Attributes instead of Interfaces. The answer couldn't be clearer: I don't want to specify contracts (use of interfaces), I want to bundle functionality. But I'll give you the long version of this.

A friend of mine asked me what was the benefit for the framework of using attributes. I quote:

What's the advantage in decorating the presenter with LogEnabled? What stops someone from placing this attribute and not using the presenter to log (this appears to be one of those cases that we leave a possible breach of design for the users of the framework, allowing them to do wrong things). As for validation, shouldn't it be an interface? If you just place the attribute, who guarantees that the Validate method is implemented?

Let's tackle that one question at a time. I'll start on WHY decorators.

Well the reason I want the user to decorate the presenter with the Plugins is to allow for easy composition of presenters. So if I need my presenter to participate in the Validation lifecycle I just decorate it with a ValidatingPresenter attribute. If I want it to participate in the Persistence lifecycle, I just decorate it with a PersistentPresenter attribute. Now how will this happen inside the NMVP engine? I was not ready to answer this question a few days ago. Maybe I still don't know the exact details, but here is how stuff will happen:

Once the presenter is created (construction), it will initialize all of its plug-ins (attributes) with the parameters they expect (presenter instance, security context, etc.). The Presenter will keep a dictionary of which attributes were initialized. This way when you need to access one of the Plugins just hit GetPlugin<TypeOfPlugin>() and watch NMVP work its magic. By this time the Plugins have all their events wired up.

Now we have 2 scenarios: MVP and Composite MVP.

Since MVP is really simple, and is actually covered by the solution given to Composite, I'll just discuss Composite.

Actually nothing stops the user from decorating a presenter with LogEnabled and not using Log, because that is PERFECTLY valid. The LogEnabled Plugin doesn't need user interference to work its magic. It'll plug in the NMVP Lifecycle and log events "automagically", in a way that to log ALL my presenters events all I have to do is decorate them with the LogEnabled attribute. Please notice that Log is just a sample and NMVP probably WON'T feature Log in release 1.0.0 (unless some kind soul out there implements it as a contribution).

Now for the interfaces issue. Well if I make it an interface you'd HAVE to implement a Validate method, and that won't probably be necessary since NMVP 1.0.0 will feature AOP Validation via Validation Everywhere. This way you'll just decorate your view Contract with whatever validation you need and then mark the presenter as ValidatingPresenter, so he'll know that the View must be validated in the OnBeforeSave event (without the user of the framework even knowing it). As you can see, this is a very clean way of bundling a LOT of functionality with a LOT of extensibility. Besides, if I did use interfaces, the user of my presenter would have at least 5 interfaces implemented in the presenter, and that gets kinda messy.

As I'm sure you all know by now, there's no such thing as a GUARANTEE that the user of the framework won't take the wrong turn. So instead of trying to drive the user, I'm trying to make the bright, soft road look a lot easier than the shadowy, bumpy road. This way we can all spend more time with our families, lol.

But hey that was a great insight. I hope you guys keep it coming, since it helps enhance the framework.

#113

Published Sunday, August 19, 2007 2:58 AM by heynemann

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

No Comments


Enter the text you see in the image:

Leave a Comment

(required) 
required 
(required)