Click here to Skip to main content
Click here to Skip to main content

Model view controller to write easily maintainable and extendable application

, 23 Jan 2012 CPOL
Rate this:
Please Sign up or sign in to vote.
This article explains how to write easily maintainable and extendable application using MVC

Introduction

Well, we all write code every day and many a times we feel we should have a better way to write code. Most probably a code that is easily maintainable and easily extendable. When we write code, we end up writing the code that has tight coupling, so if any new requirement comes in; we have to modify the existing code, this way our code is not closed for modification. One basic line has to be remembered “Code should be closed for modification but open for extension”. So keeping in mind this famous line, I will be writing a small application that will tell what need to be done to get ready for modification and allow extension without changing code. I would be trying to take the famous “MVC” approach to separate the different layers so the reader understands how it can benefit in day to day coding.

Background

Usually when we get requirement we start writing code without looking much on what if new requirement comes in or new customer want something different.

Using the Code

Requirement

Here in I am going to write a small application that shows the benefits of using object oriented concepts. We have got one requirement that says, we need to display employee data based on some department filtration. There is a requirement that this data can be shown in grid and a combo box can be used to filter the record. Also there should be another listbox control that displays only the First column of the grid i.e. in our case Employee Name. So on change of combo box item the grid loads with filtered Employee data and when row of grid selected it load the listbox with employee name belonging to department id.

Solution @ first sight

Well no big deal, let’s create a window application and create a data layer that has the data to load the combo box and also has collection of data to be displayed in the grid based on filter criteria specified by combo box. Drag a combo box, grid and a list box on window form. Load the combo box with data and on SelectedIndexChanged event of combo box load the filtered data in the grid.

  private void cmbEntity_SelectedIndexChanged(object sender, EventArgs e)
  {
            if(null != cmbEntity.SelectedItem){
                int val = Convert.ToInt16(cmbEntity.SelectedItem);
         
                List<Entity> entities = objEntData.GetAllData(val);
// bind the grid with employee belonging to selected department
               dgEntityView.DataSource = entities;
   }
 void dgEntityView_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
             lstBoxEntity.Items.Clear();
            foreach (EmployeeEntity item in entities)
            {
                // add the employee name to lisbox
                lstBoxEntity.Items.Add(item.EmployeeName);
            }
        }

So here you can see when event triggers we load the data based on combo selected item and load the grid and when grid selected row event fire we load the Employee Name in list box.

Tight coupling [not a good sign for extension]

Problem with this approach:

After design is freezes, another customer came in and asks for some new view in web instead of window. Also this customer wants data to be displayed in Chart instead of grid. So again no issue let’s create another web application. Well, definitely there will be lot of redundant code and also maintaining these multiple application will be nightmare [keeping in mind the big enterprise application]. So this will continue with new Customer asking for this feature in WPF and so on.

Well we have to think a better design

The design should be such that we can reduce the cost on maintainability and design should be easily portable to other application type.

Better Approach

Looking at the requirement, it looks it is view that is going to be changed [Could be a webform/WPF page etc.]. So let’s have a design that can be used for these entire requirements.
Our object should be loosely coupled or in other sense there should be separation of one layer from another for future extension and better maintainability.
Do we have any pattern that fit in our requirements?

MVC - Model View Controller

Model

Implement Observer pattern/ notify all subscribers with changed data or with changed states

Model notify the views subscribed to get notification

View

Display to user, Deal with User Action. [Click button/Select item from combo box etc.

Controller

Takes user input and ask Model to act on view request. Change State/Return Data.
Controller can also ask view to change based on view input [like enable/disable controls.]

The view only worried about presentation, the controller worried about translating user input to actions on the model. Model responsible to notify all the subscribers with changed data.

What changes need to be done in Code

Let’s create a class library project named MVC and add new folders named Controller, Data, Interface, model and RequestHandlres.

Data

Add our class that contains the data for demo purpose. Here I have created EmployeeEntity and Department that has certain properties. Another class named EntityDataRepositery creates the collection to be used in demo.

Interface:

/// This interface is used to make an entity Observer for any model state requested
public interface IDataObserver
{
void Update(object data);
string SubscriptionKey { get;}
string ObserverKey { get; }
}
/// This interface is responsible for registering and updating the registered observer with the asked data.
public interface IModel
{
void GetData(int id,string key);
// the below methods register subscriber whoever want to get notified
void RegisterObserver(IDataObserver dataObserver, string key);
// the below methods remove passed registerd subscriber 
void RemoveObserver(IDataObserver dataObserver);
}
/// This interface works as mediator between view and model.
/// It intercepts the request and ask model to provide the information to view.
public interface IController
{
void GetEntity(int entityId, string key);
}

Model

DataModel class is responsible of implementing IModel interface and to notify the registered observer whenever any data is requested.

public sealed class DataModel : IModel

This class has to implement IModel interface:

/// This method is used to register the observer
/// <param name="dataObserver">is the request handler that want to subscribe to key</param>
/// <param name="key">key to which subscription happen</param>
public void RegisterObserver(IDataObserver dataObserver, string key)
{
if (!dataObservers.Contains(dataObserver))
{
dataObservers.Add(dataObserver);
}
}
/// This mehtod is used to notify all the observers who has subscribed to model change for passed key

void Notify(int id, string key)
{
foreach (var item in dataObservers)
{
if (((IDataObserver)(item)).ObserverKey == key)
((IDataObserver)(item)).Update(dataObject.GetAllData(id));
}
}

Controller

EntityController class implements IController interface. It has dataModel object to be used when view request some data and Controller intercept the request and send it to Model to notify the registered observer.

public class EntityController : IController
{
IModel dataModel;

public EntityController(IModel model)
{
this.dataModel = model;
}
// this method call the GetData on model for the specified subscriber.
public void GetEntity(int entityId, string key)
{
dataModel.GetData(entityId,key);
}
}

ReqHandler

It has BaseReqH class, this class is used to have a reference of Model and Controller to be accessed by child classes. This class has a special purpose to avoid creating object of model/controller by sub classes. Any class that derives from BaseReqH doesn’t need to create these instances.

public BaseReqH()
{
model = model ?? new DataModel();
controller = controller ?? new EntityController(model);
}

Now the fun begins after all hard work in base classes.

So how does this help in creating different views without affecting existing base classes or by extending base classes?

Let’s create a new window application and on window form drag and drop a combo box, datagrid and Listbox.

We need to load the combo box with Departments and DataGrid should be loaded with selected department employee only. Also when user select Datagrid row the ListBox should be loaded with respective employee name belonging to selected department id taken from Datagrid cell.

To achieve this DatagridReqH should be subscribed to ComboReqH and ListBoxReqH should be subscribed to controller DatagridReqH. action invokes the model to notify all those subscriber who has matching key.

  1. When user select department on combo, controller pass the departmentId and subscription key.
    void cmb_SelectedValueChanged(object sender, EventArgs e)
    {
    controller.GetEntity(Convert.ToInt16(cmb.SelectedValue), this.SubscriptionKey);
    }
  2. DatagridReaH is the observer of ComboReqH and also implement IDataObserver. It register with model with the Observer Key
    model.RegisterObserver(this, ObserverKey);
  3. EntityController calls datamodel and passed the required data.
    public void GetEntity(int entityId, string key)
    {
    dataModel.GetData(entityId, key);
    }
  4. DataModel getData calls Notify method and check who are the subscribers to update and call all subscribers Update method
    void Notify(int id, string key)
    {
    foreach (var item in dataObservers)
    {
    if (((IDataObserver)(item)).ObserverKey == key)
    ((IDataObserver)(item)).Update(dataObject.GetAllData(id));
    }
    }
  5. The DataGridReqH is one of the subscriber its update method get called and load the datagrid
    public void Update(object data)
    {
    dgView.DataSource = data;
    }
  6. Now you need to instantiate the different request handler in Window form constructor, or in web form constructor or in MainWindow WPF constructor

    In window application constructor instantiate below Reqest Handlers

    BaseReqH bs = new BaseReqH();
    ComboReqH creq = new ComboReqH(cmbEntity);
    
    DataGridReqH dreq = new DataGridReqH(dgEntityView);
    
    ListBoxReqH lreq = new ListBoxReqH(lstBoxEntity);

Run the application and you see the desired functionality achieved using writing few request handlers and MVC approach. Just to add don’t forget the role of Observer Pattern in this application.

See once we have written our MVC framework, how easy to build UI. Let assume now we need to show data in a chart instead of grid whenever department id changed and that too in ASP.NET application.

  1. Create a new web application, drag and drop dropdownlist and chart on webform.
  2. Chart should be derived from WebReqH and also a subscriber to combobox.
  3. Whenever departmentid changes, the request go to controller and controller asks the model to update the matching subscriber i.e. Chart in our case.
  4. Instantiate the required request handlers in web form page load.

I hope you have enjoyed reading this article, if you liked it please don’t forget to rate this and leave your comment.

Happy Programming J

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

malakar.anil
Aspect Technology Center India Pvt. Ltd.
India India
No Biography provided

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Mobile
Web04 | 2.8.141015.1 | Last Updated 23 Jan 2012
Article Copyright 2012 by malakar.anil
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid