Introduction
After spending quite a bit of time being sucked into the whole Code Behind mess of ASP.Net, I am finally getting some use out of the MVP pattern. There will have been plenty written about what it is, that it is a UI pattern and its many benefits, suffice to say that is what we should be aiming for when designing user, business and data layer components behind a user interface, be it ASP.Net, WinForms, Mobile, etc. Why? Because we are trying to achieve some important tenets of good design that being loose coupling with high cohesion. Cohesion is about robust, reliable, understandable and reusable designs/applications whilst loose coupling is about communicating through a stable interface. Another huge benefit to using this pattern for interface programming is that it allows you write tests that mock the various interface implementations to allow isolated unit testing.
Side Note:
I do have some reservations for using this pattern, particularly as I do a fair bit of work with datagridview controls(WinForms) or DataGrid (ASP.Net) as the intention of the pattern is to use the “View” to represent the data items relating to the user interface which is far more complicated when dealing with collections of datarows. Also, the handling of events and different code paths through the UI code behind make this pattern more cumbersome to implement and use. But more on that in a part 2 posting.
The alternative to MVP seen in many solutions is to use the code behind to assemble serialisable domain classes or xml documents and pass these between UI and user process code ensuring that the user process layer, business and data layer make no reference whatsoever to the original UI presentation data items such as text and combo boxes. This is often also achieved with the use of web services between the layers.
The View
The View shows a representation of the model and is usually distinguished by a stable interface e.g:-
Public Interface IView
Property FullName() As String
Property DateOfBirth() As String
Property ErrorMessage() As String
End Interface
The Model
The Model is responsible for execution of business rules and storage of the data and again is usually distinguished by a stable interface e.g:-
Public Interface IModel
Function StoreDetails(ByVal dets As IView) As String
Function GetDetailsByID(ByVal idx As Integer) As ArrayList
Function GetDetailsByName(ByVal name As String) As ArrayList
End Interface
The model will be supported by the associated concrete implementation. This example is of course highly contrived but the pattern underneath is the key principle here:-
Public Class Model
Implements IModel
Public Function GetDetailsByID(ByVal idx As Integer) As System.Collections.ArrayList
Implements Model.GetDetailsByID
'Code to retrieve form details
Dim res As ArrayList = New ArrayList(New String() {"simon", "Peter", "Jane"})
Return res
End Function
Public Function GetDetailsByName(ByVal name As String) As System.Collections.ArrayList
Implements IModel.GetDetailsByName
'Code to retrieve form details
Dim res As ArrayList = New ArrayList(New String() {"Peter", "Jane"})
Return res
End Function
Public Function StoreDetails(ByVal dets As IView) As String Implements IModel.StoreDetails
'Code to store form details
'...
Return String.Format("Stored details for {0} : {1}", dets.FullName, _
Format(CDate(dets.DateOfBirth), "yyyy/MM/dd"))
End Function
End Class
The Presenter
The Presenters job is to present the view to the model and in so doing communcate between these layers:-
Public Class Presenter
Dim thisView As IView
Dim busLayer As IModel = New Model
Public Sub New(ByVal view As IView)
If view Is Nothing Then
Throw New ArgumentException("view cannot be nothing")
Else
thisView = view
End If
End Sub
Function ValidateDOB() As Boolean
Return IsDate(thisView.DateOfBirth)
End Function
Function StoreDetails() As String
Return busLayer.StoreDetails(thisView)
End Function
End Class
The Code behind file
Finally, the code behind ASP.Net page (could easily be some other UI client type) must implement the view’s interface and store the specifics of the UI controls values in the view and invoke the presenter to mediate between the UI and the model layers using the View data:-
Partial Class _Default
Inherits System.Web.UI.Page
Implements IView
Dim thisView As IView
Public Property DateOfBirth() As String Implements IView.DateOfBirth
Get
Return Me.TxtDOB.Text
End Get
Set(ByVal value As String)
Me.TxtDOB.Text = value
End Set
End Property
Public Property FullName() As String Implements IView.FullName
Get
Return Me.TxtFullName.Text
End Get
Set(ByVal value As String)
Me.TxtFullName.Text = value
End Set
End Property Public Property ErrorMessage() As String Implements IView.ErrorMessage
Get
Return Me.LblResult.Text
End Get
Set(ByVal value As String)
Me.LblResult.Text = value
End Set
End Property
Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnSubmit.Click
Try
Dim pres As Presenter = New Presenter(Me)
Me.LblResult.Text = pres.StoreDetails()
Catch ex As Exception
Me.LblResult.Text = ex.Message
End Try
End Sub
End Class
Conclusion
So, a fairly simple example to start with. The complications to this pattern will arise from the use of gridviews and data containers with many rows as well as how to handle page transitions, session data and page workflow and it may be that other patterns are required to fully implement a neat solution.
In the seond part to this article I will attempt to address these issues.
Filed under: Patterns | Tagged: Architecture, ASP.Net, Design, MVP, VB



Where is the 2nd part of this article? Please let me know.