Sunday, June 12, 2016

Model-View-Presenter (MVP) Pattern


MVP: Model - View - Presenter
I thought of writing something about MVP design pattern which is one of the major pattern used in SharePoint and many .Net applications.


Most of the time reader(s) feels that it is easy when reading article but during implementation there will be lot of confusion and forget how it works internally. I had created a easy example with a day to day life which will give a very clear understating and implementation knowledge.

Before I proceed to the example, we should know some basic definition used for MVP.
MVP design pattern is evaluation of MVC. MVP pattern providing a clear separation between view, model and controller. As well as improves the the testability of enterprise solution. 

MVP pattern is adding more benefit to decoupling architecture. The model can be used by more than one applications/operations.

Model: It is a domain level or business object. Model accommodates application data and behaviours to systematically access it. Model should be independent and it should not be communicated directly from either View or Presenter. All the time model will be treated as stand alone build business object which can be interacted through an interface.

View: View is nothing but UI where all data/result will be bound. But view should be updated by presenter. View will know the model but not wise versa.

Presenter: Presenter will address all input from view and use them to manipulate the result through Model and update the result back to view.





Below is the example that I created with Restaurant operation with MVP. 

Actions: Customer going to an restaurant for having some food. Waiter will get the order from customer and pass it to kitchen department. Cook will get all input and prepare the food for the order and deliver the food.


Find below the mapping how this action and characters are associated with MVP architecture/elements.


Customer -->  End user

Ingredients--> Model: Place of providing data/manipulating result with help of business logic. Here in this context the kitchen is source for supplying ingredients for preparing food.

Waiter --> View: Read out the menu items and get order from customer

Cook --> Presenter: The one who collect input from waiter and prepare food based on the order and deliver the food back to waiter who will serve to customer.

Menu card --> View Interface : Waiter should know all available items and way of serving the food which is nothing but implementing the interface in view.
Kitchen --> Model Interface:

Kitchen Interface --> Model Interface: Kitchen is the place which provide a facility to prepare food by accessing all ingredients and cooking equipments by cook. 


Logical diagram of MVP pattern association with Restaurant operation.

  • As stated in above diagrams, waiter(view) should knows all available food by implementing the food menu which is nothing but and View interface
  • Waiter can communicate the customer order to cook for preparing food but cannot go to kitchen and prepare food himself.
  • Cook will completely read the order details and access kitchen to get all ingredients and equipments for preparing food
  • Kitchen is an model interface because it is the place providing facility for preparing food.
  • Ingredients is our mode as it is similar to information data. This model can be accessed by PO department, Stack department and many more.
  • Cook will prepare food and deliver it on a plate or cup based on order. This action is nothing but presenter updating the view with result which will be deliver to end user(customer)
Transforming the logic in below diagram

  1. Waiter reading all items available in menu card
  2. Customer ordering one black tea and cup of coffee to waiter
  3. Waiter sending order details to cook for preparing black tea and coffee
  4. Cook access kitchen and collect coffee seed, Tea powder and milk for preparing food.
  5. Cook complete the preparation and pouring it in two different cups. One for black tea another one for coffee.
  6. Waiter serve the black team and coffee to respective customer.

Find below completely transformed class diagram 

Sample C# solution explorer

Sample code:
Model:


namespace Restaurant
{
    public class Ingredients_Model : IKitchen_Interface
    {
        public string VegetableRice(int qty)
        {
            return "Ready :- "+qty + " --> Vegetable Rice."; 
        }
        public string CurdRice(int qty)
        {
            return "Ready :- " + qty + " --> Curd Rice "; 
        }
        public string Tea(string density, bool withMilk)
        {
            if (withMilk)
            {
                return "Ready :- " + density + " --> Tea with Milk ";
            }
            else
            {
                return "Ready :- " + density + " --> tea without Milk ";
            }
            
        }
        public string Coffee(string density, bool withMilk)
        {
            if (withMilk)
            {
                return "Ready :- " + density + " --> coffee with Milk ";
            }
            else
            {
                return "Ready :- " + density + " --> coffee without Milk ";
            }
        }
        public string FishFry(string fishName, int qty)
        {
            return "Ready :- " + qty + " --> Fried " + fishName + " fish ";
        }
        public string ChickenFry(int qty)
        {
            return "Ready :- " + qty + " --> Fried chicken ";
        }
    }
}

Model Interface:


namespace Restaurant
{
    public interface IKitchen_Interface
    {
        string VegetableRice(int qty);
        string CurdRice(int qty);
        string Tea(string density,bool withMilk);
        string Coffee(string density, bool withMilk);
        string FishFry(string fishName,int qty);
        string ChickenFry(int qty);
    }
}

Presenter:


namespace Restaurant
{
    public class Cook_Presenter
    {
        IMenuCard_Interface iMenu;
        IKitchen_Interface iKit;
        public Cook_Presenter(IMenuCard_Interface pImenu)
        {
            iMenu = pImenu;
            iKit = new Ingredients_Model();
        }
        public void  FishFry(string fishName,int qty)
        {
           iMenu.PreparedFood=iKit.FishFry(fishName,qty);
        }
        public void ChichenFry(int qty)
        {
            iMenu.PreparedFood = iKit.ChickenFry( qty);
        }
        public void CurdRice(int qty)
        {
            iMenu.PreparedFood = iKit.CurdRice( qty);
        }
        public void VegerableRice(int qty)
        {
            iMenu.PreparedFood = iKit.VegetableRice( qty);
        }
        public void Tea(string dencity, bool withMilk)
        {
            iMenu.PreparedFood = iKit.Tea(dencity, withMilk);
        }
        public void Coffee(string dencity, bool withMilk)
        {
            iMenu.PreparedFood = iKit.Coffee(dencity, withMilk);
        }
    }
}

View Interface;


namespace Restaurant
{
    public interface IMenuCard_Interface
    {
        void FishFry(string fishName,int qty);
        void ChickenFry(int qty);
        void Coffee(string dencity, bool withMilk);
        void Tea(string dencity, bool withMilk);
        void CurdRice(int qty);
        void VegetableRice(int qty);
        string PreparedFood { get; set; }
    }
}

View:


namespace Restaurant
{
    public class Waiter_View:IMenuCard_Interface
    {
        Cook_Presenter cook;
        public void FishFry(string fishName, int qty)
        {
            cook=new Cook_Presenter(this);
            cook.FishFry(fishName, qty);
        }
        
        public string PreparedFood
        {
            get;
            set;
        }

        public void ChickenFry(int qty)
        {
            cook = new Cook_Presenter(this);
            cook.ChichenFry(qty);
        }

        public void Coffee(string dencity, bool withMilk)
        {
            cook = new Cook_Presenter(this);
            cook.Coffee(dencity, withMilk);
        }

        public void Tea(string dencity, bool withMilk)
        {
            cook = new Cook_Presenter(this);
            cook.Tea(dencity, withMilk);
        }

        public void CurdRice(int qty)
        {
            cook = new Cook_Presenter(this);
            cook.CurdRice( qty);
        }

        public void VegetableRice(int qty)
        {
            cook = new Cook_Presenter(this);
            cook.VegerableRice( qty);
        }
    }
}


Customer:


using System;

namespace Restaurant
{
    class Customer
    {
        static void Main(string[] args)
        {
            Waiter_View order = new Waiter_View();
            
            order.Tea("Black", false);
            Console.WriteLine(order.PreparedFood);

            order.Coffee("Strong", true);
            Console.WriteLine(order.PreparedFood);

            Console.ReadKey(true);
        }
    }
}

RESULT: