Monday, February 28, 2011

Model View Presenter Supervising Controller

Problem
 When I create windows application forms, I find it really hard to test it and if I want to change the form design or change the form altogether, I will have to rewrite my code again. So that make my application really rigid and reduce the scalability and testability.

Impact

  • Maintenance is really difficult and can't really test my code.
  • Its very hard to separate business logic from the view.


Solution
Model view Presenter pattern is the solution to this problem. First we need to understand what Model view Presenter is.

Model: Model is our class where we write our business logic.
View: View is user interface, in our case windows form.
Presenter: Presenter is where we write code to connect our view to our model.


Now the whole purpose of this pattern is to use our view for only the viewing, and all the code should go to presenter class.

suppose we have windows form, called StudentView, and have a model Student, and we are using StudentView to get the information about the student from the user.



this is what our model looks like.
namespace ModelViewPresenterExample
{
    public class Student
    {
        public Student(string name,string address, int age)
        {
            Name = name;
            Address = address;
            Age = age;
        }

        public string Name { get; set; }
        public string Address { get; set; }
        public int Age { get; set; }
    }
}

now that we have our model and view, we need our presenter. we need to create a class name StudentViewPresenter. StudentViewPresenter class implements IStudentViewPresenter interface. We also need to create another interface IStudentView and implement that interface on our Student form. for the time being IStudentViewPresenter has one method and one property. 

namespace ModelViewPresenterExample
{
    public interface IStudentViewPresenter
    {
        IStudentView View { get; set; }
        void AttachPresenter();
    }
}


as you can see we are exposing our form by using IStudentView property. Here is the code for our IStudentView interface.

namespace ModelViewPresenterExample
{
    public interface IStudentView
    {
        void Message(string message);
        void AddPresenter(IStudentViewPresenter presenter);
    }
}

this interface contains only two methos, one to pass our presenter and one to pass simple messages from our presenter. I know its alot to take in, it will make more sense when we write rest of our code.

so first lets write our presenter class.

namespace ModelViewPresenterExample
{
    public class StudentViewPresenter:IStudentViewPresenter
    {
        private IStudentView _view;

        //pass student view when user instantiate presenter.
        public StudentViewPresenter(IStudentView view)
        {
            _view = view;
        }

        public IStudentView View { get; set; }

        //here we are passing this presenter to our view.
        public void AttachPresenter()
        {
            _view.AddPresenter(this);
        }
    }
}



this purpose of all this is, that using this presenter we could easily switch our view, for example when we create our presenter, we pass the form, presenter does't care what kind of form it is as long as that form implements IStudentView, our presenter will happily accept it.

IStudentViewPresenter presenter = new StudentViewPresenter(new StudentView());

so as you can see, we are forcing the user to inject the view when we instantiate the presenter.

now that we have our presenter, I am going to show you what I have for our form. Here is the code that goes in StudentView.

namespace ModelViewPresenterExample
{
    public partial class StudentView : Form,IStudentView
    {
        private IStudentViewPresenter _presenter;
        public StudentView()
        {
            InitializeComponent();
        }

        public void Message(string message)
        {
            MessageBox.Show(message);
        }

        public void AddPresenter(IStudentViewPresenter presenter)
        {
            _presenter = presenter;
        }
    }
}

in student view we have IStudentViewPresenter, we then use AddPresenter method and pass our presenter to this local variable. as you can see that in our presenter class we had a method AttachPresernter and in that method we used our view to call AddPresenter method and passed the presenter to our view, this way presenter can now have connection with view.

now since this form is about saving the student information, when user click on Save button, so we need to write code for that and you will see how our presenter take care of all the code.

private void SaveButton_Click(object sender, EventArgs e)
{
      _presenter.Save(NameTextBox.Text, AddressTextBox.Text, AgeTextBox.Text);
 }

as you can see we simply created a method named Save and passed all the value to it, infect we just write the code in form and visual studio will create the method for us in the interface, since we are using interface to communicate. we might need to change the names of the parameters though. Now we go to presenter and implement that method. 

 public void Save(string name, string address, string age)
 {
        _student = new Student(name,address,Convert.ToInt16(age));
 }

as you can see that I am saving all the value to student class, assuming that all the values that were passed in are valid. or we could simply validate the values and then pass it to student class, if the values are not valid then return a message to student view. 

public bool Save(string name, string address, string age)
        {
            if(valid(name,address,age))
            {
                _student = new Student(name, address, Convert.ToInt16(age));
            }
            else
            {
                _view.Message("Invalid values, please enter correct values.");
            }
        }

as you can see once we have the basic model or MVP, we could add methods or properties to it as per requirements, we could easily test our code as well.

Example of test case using nunit testing.
[Test]
public void ShouldSaveValueToStudent()
{
     bool saved = false;
     string name = "faraz";
     string address = "12Alice road";
     string age = "29";
     saved = presenter.Save(name,address,age);
     Assert.IsTrue(Saved);
}

in this test when we save the data, our method should return true, to conform that every thing went smooth and there was no problem.




Address Access Denied Exception

Problem
I was developing WCF application where I had to use basic http binding, I was trying to host it in the console application and for some reason I was getting Address Access Denied Exception.

Impact
Application won't run.

Solution
After much of research I found out that since the release of vista, windows has implemented new security feature and because of that most people won't be running with Administrator privileges and since http protocol requires the Admin rights so application won't run. Now to solve this issue we need to do 2 things

1. Run netsh command on console.
Go to start, enter netsh, windows will find the netsh.exe file, right click and choose run as admin. Console will run the utility. and we will get the netsh>
now enter the following command

netsh>http add urlacl url=http://localhost:8080/test user=FARAZ-PC/faraz and enter.

now user name should be the name of your machine, in my case it was faraz-PC. after running the command you should get some message telling you that http has been added.

2. Restart visual studio and start it as Administrator.

and run your application again and it should now work.

Monday, February 14, 2011

Factory Pattern

Problem
I had a situation where I had to instantiate a class based on the condition, so I used if else if statements and was done with it, but after some time I had to add another condition to it, I had to go back and look for that code. What Should I do that in future I don't have to go through this process again.

Impact 
Code was hard to debug, and was less scalable.

Solution
I have alway been fascinated by Design patterns since I found out about them, but they are not easy to understand. There is a lot of material on the web about design patterns but I could't get my head around them, Most of the material that I found was too advance for my level so I start reading books, and believe me books are not that easy either. I found Headfirst design pattern, which seemed much better book than the other books, and in there I found the solution to my problem. Factory pattern. So when we have a situation where we need to instantiate a class based on a situation we should use factory pattern. Advantage of using factory pattern is that we know where to when we need to add another condition, plus we don't make any changes to our logic, all we have to do is ask the factory to create a class based on the situation.

IProduct  product  = ProductFactory.Create("Gucci Bag");

and factory should return the product.

I am going to create simple example so we could understand it better.

We understand the problem now and this is how we deal with it.
first of all alway try to work with the interface rather than concrete class. Coding to an interface is always better, you don't expose the whole class, only those parts that were implemented  by the interface.

public interface IProduct
    {
        string Name { get; set; }
    }

Now that we have an interface, we implement it to our classes.
Make sure the constructor of the class in always internal, otherwise client is free to instantiate concrete class then using factory.

    public class CalvinKlein:IProduct
    {
        public string Name { get; set; }

        internal CalvinKlein(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return string.Format(Name);
        }
    }

public class GucciBag : IProduct
    {
        public string Name { get; set; }

        internal GucciBag(string name)
        {
            Name = name;
        }

        public override string ToString()
        {
            return Name;
        }
    }


In our store class we want to use our factory class to create our product, factory will produce item based on the product type that we are passing to the factory.

    public class Store
    {
        private IProduct _product;
        private IProductFactory _factory;

        public IProduct Buy(ProductType productType)
        {
            _factory = new ProductFactory();
            _product = _factory.Create(productType);
            return _product;
        }
    }

    public enum ProductType
    {
        GucciBag,
        CalvinKlein
    }

We use factory that will create the item for you. How does it work you say, well here first we create an interface name IFactory which contains one method called Create() that take one argument and return IProduct type. Now the argument that it takes will be enum type, and based on that type we will create our object. so here we go.

public interface IProductFactory
{
     IProduct Create(ProductType productType);
}

    public class ProductFactory:IProductFactory
    {
        private IProduct _product;

        public IProduct Create(ProductType productType)
        {
            if(ProductType.CalvinKlein == productType)
            {
                _product = new CalvinKlein("Calvin Klein");
            }
            else if(ProductType.GucciBag==productType)
            {
                _product = new GucciBag("Gucci Bag");
            }
            return _product;
        }
    }


Now finally we will use Main method to buy the items from the store and then display the name of the item we bought.

class Program
    {
        static void Main(string[] args)
        {
            Store myStore = new Store();
            IProduct product;
            product = myStore.Buy(ProductType.GucciBag);
            
            Console.WriteLine(product); // this will show we bought Gucci bag.
            product = myStore.Buy(ProductType.CalvinKlein);
            Console.WriteLine(product); // this will show that we bought Calvin klein product.
            Console.ReadLine();
        }
    }