Login or Sign Up to become a member!
LessThanDot Sit Logo

LessThanDot

Architecture, Design & Strategy

Less Than Dot is a community of passionate IT professionals and enthusiasts dedicated to sharing technical knowledge, experience, and assistance. Inside you will find reference materials, interesting technical discussions, and expert tips and commentary. Once you register for an account you will have immediate access to the forums and all past articles and commentaries.

LTD Social Sitings

Lessthandot twitter Lessthandot Linkedin Lessthandot friendfeed Lessthandot facebook Lessthandot rss

Note: Watch for social icons on posts by your favorite authors to follow their postings on these and other social sites.

Your profile

    Search

    XML Feeds

    Google Ads

    « You need to know a lot when you want to be a developer.MSDN giveaway winners »
    comments

    Model-View-Presenter is an architecture pattern that defines a structure for behavior and logic at the UI level. M-V-P separates the logic of the presentation, such as interacting with back-end services and the business layer, from the mechanics of displaying buttons and interface components.

    I often build small projects to help understand and grow my skills as a developer, architect, and all-around technologist (as may be apparent from the wide range of topics I post on). Today I worked with a combination of Visio and Visual Studio to build a sample project to play with the Passive View concept and to help grow my own understanding of the concept. This post will cover the Visio side of my learning-curve.

    You can read more about Model View Presenter at Wikipedia and MSDN. Perhaps the best information can be found on Martin Fowler's site, where he has separate write-ups on Passive View and Supervising Controller.

    Note: I know some people were waiting for another Virtual Lab entry this week, and here I am writing about Architecture instead. Don't worry, the virtual lab series will continue, I just felt like doing a write-up while I was playing this past weekend.

    Passive View

    Passive View is a subset of the Model-View-Presenter pattern. In Passive View, the interface is responsible for handling interface-specific logic, such as figuring out how to put a value in a textbox or react to events from button clicks, but all actions and logic outside of the raw UI are sent to the Presenter to execute or manage. The Presenter is responsible for calling business methods in the Business model and updating the data that is available in the View.

    Basic Model-View-Presenter diagram
    Basic Model-View-Presenter Diagram

    From the outside in, the architecture for Passive View looks something like this:

    • UI - The User Interface reflects what is going on beneath it by implementing one or more View interfaces
    • Presenter - The Presenter receives interactions from the UI or Model and updates the Views it is attached to
    • Model - The model is a facade or black box in our diagram, behind which is a business logic layer and data layer

    In a flat architecture we would collect data from the interface, perhaps do some business and data validation, and then save it directly to a database using stored procedures or inline SQL. Defining a data access layer (or data model like entity framework) allows our application to operate on cohesive, defined objects that are meaningful to the application and stored and retrieved consistently. Defining a business logic layer allows us to centralize business rules that operate on entities in our application in a manner that is consistent with the business and internally consistent in the application, minimizing the risk that occurs when making changes to the business flow. Separating the logic of populating inputs and responding to button presses on the UI from the information being communicated to the end user and conceptual responses to their input allows the system to interact with the user consistently across any number of interfaces into the same application.

    The definition of each level increases our ability to automate testing and supports greater Separation of Concerns.

    Implementing a Sample Project

    My learning exercise has been the the creation of an ASP.Net search page that allows an end user (customer) to search for finished products from the AdventureWorks sample database. The architecture and design decisions were done as an exercise in Visio using simple shapes and layouts.

    My example application has several functional and non-functional requirements:

    1. Functional - Display product number, name, list price, and available quantity in tabular format
    2. Functional - Provide a basic search input and button to search product names
    3. Non-Functional - Implement an M-V-P pattern - Obviously the purpose of this whole exercise
    4. Non-Functional - Use a simple model stack that can be easily replaced with a Service-Oriented one at a later time
    5. Non-Functional - Build with the idea that we will later create a Silverlight or WPF front-end
    6. Non-Functional - Make pretty pictures for article

    My unwritten, final requirement was to finish the whole thing in half a day, though luckily I didn't define whether I intended that to mean 4 hours or 12.

    Initial Architecture

    To start I created a diagram of the application architecture:

    More extensive M-V-P Diagram
    More Extensive Model-View-Presenter Diagram

    The purple layer is my presentation layer, which reflects the View. The blue layer is my Presenter layer which contains the logic for interacting between the end user and interface as well as a definition, or contract, of the information available in the View. The Green is the Model (or is behind the model, depending on your viewpoint) and exposes business functions and data entities for the Presenter to interact with.

    Class Layout

    Once the high level diagram was completed, I could approach the task of creating some base classes and interfaces to use in implementing the project.

    • Model.IModel - Generic Model Interface to expose business calls to Presenters
    • Presenter.IView - Generic View Interface that all Presenters can interact with and all screens implement
    • Presenter.BasePresenter - Generic Presenter class that all Presenters will implement

    To keep the project to a single morning but also allow the ability to come back and build a more architecturally sound solution, I implemented the Model in a very basic fashion that was referenced locally by the Presenter project and makes direct calls to SQL Server using ADO and parametrized, inline SQL. This buys me the benefits of having a well-defined Model (via the interface) but allows me concentrate my time and effort on the learning part of the project (ie, the M-V-P interaction and structure). Defining the model interface also leaves me open to come back and replace it with better separated code and the ability to create a model that acts as a facade to a service stack, instead of local DLLs.

    • Model.BasicModel.Model - Basic implementation of a model that will interact with AdventureWorks on SQL Server
    • Model.Entities.Product - A Product Entity that can be communicated between an IModel instance and Presenter
    • Presenter.ProductSearchPresenter - A Presenter to manage product search interface
    • Presenter.IProductSearchView - A view of the data involved in a product search
    • ProductSearch.aspx - A web page that implements the IProductSearchView and interacts with the ProductSearchPresenter

    My final Visio diagram ended up looking like this:

    Example Application Diagram
    Diagram of Example Application

    In this case the left side represents basic components (bases classes and interfaces) that are used to define common structure or contracts on the right side.

    The Code

    For the purposes of the example project, my view has properties for Search Text, a Search Count (number of results), Results (a generic list of the Product entity), and a boolean indicating whether there are results to display. My Web Form implements these properties, tying them to elements on the screen.

    1. public partial class WebForm1 : System.Web.UI.Page, Presenter.Views.IProductSearchView {
    2.  
    3.         Presenter.ProductSearchPresenter _presenter;
    4.  
    5.         protected void Page_Load(object sender, EventArgs e) {
    6.             btnSearch.Click += new EventHandler(btnSearch_Click);
    7.             rptProducts.ItemDataBound += new RepeaterItemEventHandler(rptProducts_ItemDataBound);
    8.             _presenter = new Presenter.ProductSearchPresenter(new Model.LocalModel.BasicModel(System.Configuration.ConfigurationManager.ConnectionStrings["AdventureWorks"].ConnectionString), this);
    9.         }
    10.        
    11.         void btnSearch_Click(object sender, EventArgs e) {
    12.             this._presenter.ExecuteProductSearch();
    13.         }
    14.  
    15.         string Presenter.Views.IProductSearchView.SearchText {
    16.             get { return tbSearch.Text; }
    17.             set { tbSearch.Text = value; }
    18.         }
    19.  
    20.         int Presenter.Views.IProductSearchView.ResultCount {
    21.             set { lblResultCount.Text = value.ToString(); }
    22.         }
    23.  
    24.         List<Model.Entities.Product> Presenter.Views.IProductSearchView.SearchResults {
    25.             set {
    26.                 if (value != null && value.Count > 0) {
    27.                     rptProducts.DataSource = value;
    28.                     rptProducts.DataBind();
    29.                 }
    30.             }
    31.         }
    32.  
    33.         bool Presenter.Views.IProductSearchView.DisplayResults {
    34.             set { tblResults.Visible = value; }
    35.         }
    36. ...

    As the presenter populates properties in the view, the information is automatically reflected on the page. The actual logic of how the business functions are called and populate those properties are neatly packaged up in the Presenter and View interface and very little logic occurs in the actual web form.

    1. public class ProductSearchPresenter : BasePresenter {
    2.  
    3.         protected Views.IProductSearchView _view;
    4.  
    5.         public ProductSearchPresenter(Model.IModel model, Views.IProductSearchView view) : base(model) {
    6.             this._view = view;
    7.             this._view.ResultCount = 0;
    8.             this._view.DisplayResults = false;
    9.         }
    10.  
    11.         public void ExecuteProductSearch() {
    12.             List<Model.Entities.Product> results;
    13.             results = this._model.SearchProduct(this._view.SearchText);
    14.             if (results.Count > 0) {
    15.                 this._view.ResultCount = results.Count;
    16.                 this._view.DisplayResults = true;
    17.                 this._view.SearchResults = results;
    18.             }
    19.             else {
    20.                 this._view.ResultCount = 0;
    21.                 this._view.DisplayResults = false;
    22.                 this._view.SearchResults = null;
    23.             }
    24.         }
    25.     }

    To create a unit test, we define a simple view that implements the view interface, execute the presenter logic, and verify the properties are populated the way we would expect when the same presenter calls are made from the interface.

    Extending the Architecture Further

    Extending the application to display product search in a different manner would only require the addition of a new interface that also implements the Product Search View. A Silverlight front-end would only require creating the basic project, implementing the product search View, and wiring the new interface controls to the view properties. To replace the direct mode reference with a service reference, we could create a service facade that implemented the IModel interface, connected to a local or remote WCF service behid the scenes to handle the real model logic. And finally, instead of counting on our QA department to test all of the application interactions, we can create unit tests directly against the Presenter and Views to ensure that all of the interactions below the top surface of the application are happening consistently and to our expectation.

    Your Turn

    Getting this much of the architecture working is a good first step. I took a number of shortcuts on the BasicModel class in my example, but I now have a functional Model-View-Presenter application to play with. Hopefully there was enough information in the article to interest you in trying this out on your own. I urge you to read the articles linked in the top of the post (or several more in my Model-View-Presentation bookmarks) and come up with your own diagrams and sample project. Even doing a small project will force you to run into questions and considerations you wouldn't have had by simply reading about it, not to mention unrelated tidbits you will pick up along the way (for instance, I also learned about ObservableCollections today).

    About the Author

    User bio imageEli delivers software and technology solutions for a living. His roles have included lone developer, accidental DBA, team lead, and even unintentional Solaris consultant once. With experience in adhoc, Lean, and Agile environments across NSF grants, SaaS products, and in-house IT groups, he is just as willing to chat about the principles of Lean or Continuous Delivery as he is to dive into Azure, SQL Server, or the last ATDD project he created.
    Social SitingsTwitterLinkedInHomePagedeliciousLTD RSS Feed
    Instapaper

    10 comments

    Comment from: Robert Blixt [Visitor] · http://devghost.com
    Robert Blixt Great post, a very interesting read.

    I have been playing with Passive View myself recently and put the result up on github (http://github.com/devghost/skeletor). There are currently two sample applications there using WPF and Passive View. Where one is using the Event Aggregator to send events from the view to the presenter, and the other is using CLR events.
    The major benefit of this, as I can se, is that the view doesn't hold any reference to the presenter. Which makes them more decoupled.

    The sample apps are a work in project, so there are probably plenty of things that needs to be fixed :)
    07/17/10 @ 01:30
    Comment from: Eli Weinstock-Herman (tarwn) [Member]
    Eli Weinstock-Herman (tarwn) I considered (several times) including the sample code, but I had more I wanted to do before releasing it (a few more presenter function, a service and dummy model, some unit tests). It sounds like you managed to add a bit more capability and functions on yours. Headed over to github now to take a look at your project. :)
    07/17/10 @ 05:34
    Comment from: Brian Wilkins [Visitor]
    Brian Wilkins My question is why does the View even pass the model to the Presenter. The Presenter should know the model, the view should be as dumb as possible IMHO.
    08/11/10 @ 12:34
    Comment from: Eli Weinstock-Herman (tarwn) [Member]
    Eli Weinstock-Herman (tarwn) In this case the View is passing an instance/implementation of the Model to the Presenter because I didn't want to add logic to do dependency injection. I want the presentation logic to be uncaring and unaware of whether the model instance it is interacting with is a web service facade, a super-basic quick-and-dirty implementation like I actually used, a domain driven model, or a dummy class to return very controlled outputs for unit testing. Dependency injection using something like StructureMap or Windsor would be among the best solutions, a middle-of-the-road solution might be a handmade DI class to orchestrate creation of the right model(s) without the extra weight of a full framework.
    08/11/10 @ 16:58
    Comment from: Richard Guevara [Visitor] Email
    Richard Guevara Hi Eli,

    Im actually starting to learch MVP and I found your article to be helpful. Ive created a sample project and I dont know if I did it correctly.

    Richard.
    10/13/10 @ 03:03
    Comment from: Eli Weinstock-Herman (tarwn) [Member]
    Eli Weinstock-Herman (tarwn) Richard, if you want you could start a forum post and attach a zip copy of the project (or a URL if the zip is too large) and we could take a look. Or you can look at Robert's linked examples above.
    10/13/10 @ 04:00
    Comment from: Brian [Visitor]
    Brian I was wondering how dumb does the view needs to be, if it's truly passive shouldn't the btnSearch_Click only tell presenter that the search button was clicked rather than being smart enough to have the presenter perform a product search?
    01/03/11 @ 10:03
    Comment from: Eli Weinstock-Herman (tarwn) [Member]
    Eli Weinstock-Herman (tarwn) It could, and I see a lot of examples that do that. Instead of having events like that button push handled locally, the event would be bound directly to a method in the presenter. The downside is that this makes the Presenter aware of the type of interface, since there are interface- or control-specific arguments passed to the Presenter which it not only needs to accept but also operate on. A more pure method would probably be to have events defined for the the view that are more generic, handle the UI or control events and turn them into those view events. But this sounds like more work.

    I think in the end it's up to the author to decide what fits their needs the best, whether they prefer to translate to view events, bind implementation-specific events directly to the presenter, or wire event handlers to a single call in the Presenter.
    01/04/11 @ 04:38
    Comment from: Oliver Watkins [Visitor] · http://www.blue-walrus.com
    Oliver Watkins Hi,

    I have some issues to take up with the MVP pattern. MVP seems to be a valid architecture for only simple GUI interfaces.

    The fact that the model is completely seperated from the view brings up some problems that seem impossible to solve without going back to MVC.

    Consider : I have a table with X columns. I now want to build a component that is a dialog where I can edit the values in the table. In this dialog I want to have X rows (a label and text field), where I can perform editing, close it, then the table updates.

    The problem is, the View needs to know about the model in order to generate the correct number of rows. There is no way to do this without the view knowing about the model.. we could create some intermediary 'model-proxy', but then we are really fluffing things up.



    05/20/11 @ 02:08
    Comment from: Eli Weinstock-Herman (tarwn) [Member]
    Eli Weinstock-Herman (tarwn) Funny, my issue with MVC is that it is so data entity specific that I felt it could only handle a subset of interfaces compared to something like MVP or MVVM, perhaps it depends on our perspective a bit.

    I'm having difficulty understanding why we would need a dynamic number of rows in the dialog when we are editing the equivalent of a record in the database with a given number of columns. Ignoring that, though, I believe what I would do in this situation is pass a an ordered key/value set to the view property that drives the dialog. That way the dialog can dynamically build the proper number of rows to edit my object.

    The major difference between Passive View and MVC model->view communications is that in MVC the controller handles input from the user, but the view retrieves the data to display as output. In Passive View the same decision logic occurs, but handling the input and retrieving the output to display both happen in the Presenter. MVC's view is smarter, but the view exposed in Passive View can easily be implemented by a number of interfaces (json, web service, test class) and a greater portion of the logic is now unit testable.

    05/20/11 @ 04:25

    Leave a comment


    Your email address will not be revealed on this site.

    Your URL will be displayed.
    (Line breaks become <br />)
    (Name, email & website)
    (Allow users to contact you through a message form (your email will not be revealed.)