The Bolla Blog

Sponsors

The Lounge

Wicked Cool Jobs

Syndication

News

  • Settling into a new job/life in the Pittsburgh area.
Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Model View Presenter mutated: Observable View

Transgression

One of my crusades of the past year has been to break myself and my team of the habit of embedding domain logic into the code-behinds of our ASP.NET pages. For me, this is a habit that has carried over from the ASP 3.0 days of old. More recently, we have a nice domain layer that is persisted to the database using NHibernate. Classes are created that encapsulate specific functionality, whether through design or refactoring. We have even adopted Dependency Inversion through use of interfaces, which has allowed for unit testing of these classes. But many of our pages still contain too much logic about the process of how to perform a given task. This means a significant portion of code was not being tested.

Repentance

The first source to shed some light about how to extract this remaining logic from the pages was Martin Fowler's Patterns of Enterprise Application Architecture in which he covers the Model View Controller pattern. Much googling lead to my discovery of Model View Presenter. The most enlightening source on this was Jean Paul Boodhoo's Model View Presenter video on dnrTV. We began experimenting with MVP in our designs shortly afterwards.

Transcendence

Finally, extraction and unit-testability of the logic that once existed in our code-behind. But there was still something I didn't like about our implementation of MVP. The code-behind was still responsible for calling the correct method on the presenter whenever a control's event was raised. I felt like we were 90% there. Through experimentation, I eventually came up with what I call the "Observable View" pattern:

The interface:
interface IManageCustomerView
{
string Name { get; set; }
// etc...

void DisplayValidationErrorMessage(string errorMessage);
void DisplaySavedSuccessullyMessage();
// etc...

// The interesting part...
event EventHandler Initialize;
event EventHandler SaveCustomer;
event EventHandler DeleteCustomer;
}
The code behind:
class ManageCustomer : Page, IManageCustomerView
{
protected override void OnInit(EventArgs e)
{
new ManageCustomerViewObserver().Observe(this);

if (Initialize != null)
Initialize(this, EventArgs.Empty);
}

protected void OnSaveButtonClick(object sender, EventArgs e)
{
if (SaveCustomer != null)
SaveCustomer(this, EventArgs.Empty);
}

// etc.
}
The observer:
class ManageCustomerViewObserver
{
public void Observe(IManageCustomerView view)
{
view.Initialize += delegate
{
new ManageCustomerViewInitializationProcess(view).Execute();
};

// repeat for each event
}

}

(Note: The code above probably has typos... wanna fight about it?)

The key element is the use of events. This allows the view implementation to forget about observer after calling the Observe() method. The reference that keeps it from falling out of scope is the observer's subscription to the view's events. The .NET framework's event mechanism hides makes this slightly less than obvious. The events' presence in the interface also assist the implementation in hooking to the presenter observer correctly. The observer simply delegates the logic to a process class (one per event) which is an implementation of the Command pattern. The observer class only contains the Observe() method, which is simply glue code that doesn't warrant unit testing. Each process class can be tested independently or as a group. All in all, I'm pretty satisfied with this design. It does lead to a lot more class files in the project, but unit testing, the Single Responsibility Principle's biggest cheerleader demands most of this anyways.

 


Posted 10-03-2006 6:25 PM by Jim Bolla
Filed under: , ,

[Advertisement]

Comments

Brendan Tompkins wrote re: Model View Presenter mutated: Observable View
on 10-04-2006 10:11 AM

Nice post Jim!  This is definitely something I'm going to experiment with.

davidh wrote re: Model View Presenter mutated: Observable View
on 10-04-2006 4:15 PM

I think this is a great idea.  It means that view doesn't have to know that a presenter even exists.

I was just reading about a very similar form of model view presenter: http://atomicobject.com/media/files/PresenterFirstAgile2006.pdf

Joe Niland wrote re: Model View Presenter mutated: Observable View
on 10-05-2006 5:00 AM

Nicely written, Jim. I think that is an excellent use of events. I've done a similar thing with user controls and their containing page. Not entirely sure if it fits the MVP pattern, but anyway: the containing page hooks onto events exposed by the user control such as Save, Close.

On Save, the containing page knows what to do with the data collected by the user control and persists it to wherever.

This means the containing page is the model and the controller, while the user control is the View.

That may be stretching it a bit :) but the main point is that using events between controls and pages is a very neat way of ensuring "separation of concern"

Alex Dresko wrote re: Model View Presenter mutated: Observable View
on 10-05-2006 7:47 AM

Some time ago, Martin Fowler retired the MVP design and split it into two: The Supervising Controler and the Passive View. I can't tell which your pattern falls under based on the limitted example, but it's worth looking into.

Jim Bolla wrote re: Model View Presenter mutated: Observable View
on 10-05-2006 9:05 AM

David- Thanks for the link. Looks worth a read.

Alex- Thanks for the tip. I will look into those patterns and see if either is the same as mine. I will post a followup if they shed any light on my pattern.

Rob Eisenberg wrote re: Model View Presenter mutated: Observable View
on 10-05-2006 12:55 PM

Jim, you nailed it!  This is a great practical example of using design patterns.  Unit Testing this thing should be a breeze as well.

Peter Mescalchin wrote re: Model View Presenter mutated: Observable View
on 10-06-2006 10:57 AM

Nice article.

Seems similar to an article that Phil Haack wrote a few weeks ago.

http://haacked.com/archive/2006/08/09/ASP.NETSupervisingControllerModelViewPresenterFromSchematicToUnitTestsToCode.aspx

But I think most people agree that use of events to manage control/view button clicks and user input seems to suit the MVP pattern nicely.

Jim Bolla wrote re: Model View Presenter mutated: Observable View
on 10-08-2006 10:40 PM

After doing some research, my "Observable View" seems pretty much the same as Fowler's "Passive View". I can't tell the difference anyways. It comforts me to know that Martin Fowler and Phil Haack are coming up with the same ideas as myself. Maybe I'm not crazy after all. :-) His name just conveys the "why" and mine conveys the "how".

Here's the link to Fowler's "Passive View":

http://martinfowler.com/eaaDev/PassiveScreen.html

Brian Donahue wrote re: Model View Presenter mutated: Observable View
on 01-06-2007 10:41 PM

JP Boodhoo is one of my heroes!  I highly recommend his most recent TDD screencast, which takes an approach very similar to yours:

http://www.jpboodhoo.com/blog/ScreencastAppliedTestDrivenDevelopmentForWebApplicationsPart3.aspx

江南白衣 wrote View to Presenter Communication(转)
on 08-02-2008 7:41 AM

Alright, I've purposely hid the View to Presenter communication in my previous posts on Supervising Controller and Passive View because I thought that subject was worthy of its own post. As I see it, there are 2 1/2 basic ways to communicate screen events

Add a Comment

(required)  
(optional)
(required)  
Remember Me?

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco <-- NEW Friend!
NServiceBus <-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)