Click here to Skip to main content
15,880,967 members
Articles / Programming Languages / C#

Separate Domain from Presentation – Part III

Rate me:
Please Sign up or sign in to vote.
4.20/5 (7 votes)
5 Sep 2009CDDL2 min read 27.6K   14   13
Third post in the series of posts about “Separate Domain from Presentation”

Cross post from IRefactor

This is the third post in the series of posts about “Separate Domain from Presentation” Refactoring.

Previous Posts

Last time, we explained how to refactor towards MVP – Supervising Controller pattern.

We left our project in the following state:

In this post, I will complete the required refactoring steps and will suggest more steps to even deepen the separation of UI and BL concerns.

Refactoring Steps

  • "Extract Interface" – in order to have a better encapsulation and separation of concerns, the CoursesPresenter shouldn’t access CoursesView directly. After all, the only functionality of interest to the CoursesPresenter is the CoursesView Courses property. Therefore, we will extract an interface from CoursesView class as follows: right click on the CoursesView class » Refactor » Extract Interface and select Courses property as shown in the figure below:

  • Compile the Solution and execute the Unit Tests.
  • In the CoursesPresenter class, change all the occurrences of CoursesView to ICoursesView.
  • Compile the Solution and execute the Unit Tests.
  • Last time, we indicated that the presenter should handle complicated user events by subscribing to the view. After introducing the ICoursesView interface, it’s simple. Add to the interface the following code:
    C#
    event Action LoadCourses;
    event Action SaveCourses;
  • Implement the newly added events in the CoursesView class:
    C#
    public event Action LoadCourses;
    public event Action SaveCourses;
  • In the CoursesPresenter class, rename the Load and Save methods to LoadCoursesEventHandler and SaveCoursesEventHandler respectively. Use right click » Refactor » Rename tool to rename it easily.
  • Wire-up the events in the CoursesPresenter constructor as follows:
    C#
    public CoursesPresenter(ICoursesView view)
    {
       this.view = view;
       view.LoadCourses += LoadCoursesEventHandler;
       view.SaveCourses += SaveCoursesEventHandler;
    }
  • Compile the Solution and execute the Unit Tests.
  • In the CoursesView class, add the notification code:
    C#
    private void NotifyObservers(Delegate del)
    {
        Delegate[] observers = del.GetInvocationList();
        foreach (Delegate observer in observers)
        {
            try
            {
                Action action = observer as Action;
                if (action != null)
                {
                    action.DynamicInvoke();
                }
            }
            catch
            {
                // graceful degradation.
            }
        }       
    }
  • Change the CoursesView.Load and CoursesView.Save methods to call NotifyObservers respectively:
    C#
    private void FrmMain_Load(object sender, EventArgs e)
    {
        //...
        NotifyObservers(LoadCourses);
        //...
    }
    private void Save()
    {
        //...
        NotifyObservers(SaveCourses);
        //...
    }
  • Compile the Solution and execute the Unit Tests.
  • Now it is the time to remove all the temporary instantiations of the CoursesPresenter class in the Load and Save methods. Remove all the occurrences.
  • In the Program.cs class instead of Application.Run(new CoursesView()), write the following:
    C#
    static void Main()
    {
       //...
       CoursesView coursesView = new CoursesView();
       CoursesPresenter coursesPresenter = new CoursesPresenter(coursesView);
       Application.Run(coursesView);
    }

This concludes the “Separate Domain from Presentation” refactoring.

We ended with the following:

For next possible steps, consider the following:

  • Go over the CoursesView.Designer.cs and remove all the TableAdapter instances.
  • Create DAL and move Save and Load methods further more, from the presenter to the DAL.
  • Create the CoursesView and CoursesPresenter using Abstract Factory or using Dependency Injection.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Other
Israel Israel
Uri Lavi is a development lead with extensive experience in Data Intensive, Business Compound, Distributed and Scalable Software Systems. Uri specializes in mentoring, coaching and consulting for complex software engineering topics, among which: Software Architecture, Design Patterns & Refactoring.

Comments and Discussions

 
GeneralFrom chaos to order Pin
einy7-Sep-09 20:58
einy7-Sep-09 20:58 
GeneralMessage Closed Pin
7-Sep-09 22:24
lisszhou7-Sep-09 22:24 
GeneralMessage Closed Pin
7-Sep-09 22:25
lisszhou7-Sep-09 22:25 
GeneralRe: From chaos to order Pin
Uri Lavi7-Sep-09 22:28
Uri Lavi7-Sep-09 22:28 
GeneralMy vote of 1 Pin
AhmedMozaly5-Sep-09 21:02
AhmedMozaly5-Sep-09 21:02 
GeneralRe: My vote of 1 Pin
Uri Lavi6-Sep-09 0:30
Uri Lavi6-Sep-09 0:30 
GeneralMessage Closed Pin
7-Sep-09 22:26
lisszhou7-Sep-09 22:26 
GeneralMessage Closed Pin
8-Mar-10 15:10
edhardyhive8-Mar-10 15:10 
GeneralMessage Closed Pin
8-Mar-10 15:10
edhardyhive8-Mar-10 15:10 
GeneralMessage Closed Pin
8-Mar-10 15:11
edhardyhive8-Mar-10 15:11 
GeneralMessage Closed Pin
8-Mar-10 15:12
edhardyhive8-Mar-10 15:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.