WCSF Application Architecture 2: Application Controller


This article is part of a series;


·         WCSF Application Architecture 1: Introduction


So why do we have patterns? I think it is basically to reuse good designs, and to adopt a common terminology when discussing software. But so often the subtleties of patterns are difficult to get right, and this causes confusion when people say “my presenters do X, what do your presenters do?”


I am a little concerned that I’m just going to add to this confusion with these articles. If that’s the case, I never wrote it OK? You didn’t hear it here. It was some other Simon...... J. Joking aside, I think having an open and interactive debate about the different approaches can only help – so please do feel free to comment or blog right back at me!


Anyway, there are two key patterns used in the Web Client Software Factory (WCSF). Application Controller and Model View Presenter. This post examines Application Controller, watch this space for one on Model View Presenter.


 


Application Controller


To quote Fowler, an Application Controller is used as “a centralized point for handling screen navigation and the flow of an application”. The intention is to abstract the complexity of flow through a set of screens into a discrete controller. Fowler does also suggest that “input controllers then ask the Application Controller for the appropriate commands for execution against a model”. This is where I think the variation arises in the implementation of this pattern.


In most systems today “business logic” is a really fancy word for a bunch of .NET classes that take input from the User Interface, validate it, apply some rules (“business rules”), and bung it in a database, or perhaps chuck it over a service boundary *. Occasionally there is a full domain model, but in most cases this logic is pretty straightforward (perhaps a Transaction Script). Therefore I might make a call like this;


MyLogic.SubmitLoanRequest(“Simon Ince”, loanID, loanAmount);


Now this isn’t exactly the Command pattern that Fowler refers to, and although I know some teams use the Command pattern heavily, it is not usually used in .NET land as the primary interface to the business logic.


So if we’re not able (or don’t want) to return the “... appropriate commands for execution...” from the Application Controller, what should we do? Well, I’ve seen three approaches;


1.       Use the Application Controller for both Page Flow and as a facade to the Business Logic


2.       Use the Application Controller for Page Flow and to supervise Business Logic interaction when required


3.       Use the Application Controller purely for Page Flow, effectively as a “slave” class


 


Option 1: Page Flow plus Facade


Consider the implementation below;


class UserInterface


{


    void Page_Load(object sender, EventArgs e)


    {


        List<string> loanTypes = ApplicationController.GetLoanTypes();


        LoanList.DataSource = loanTypes;


        LoanList.DataBind();


    }


 


    void SubmitButton_Click(object sender, EventArgs e)


    {


        ApplicationController.SubmitLoanRequest("Simon", 1, 2);


    }


}


 


class ApplicationController


{


    static List<string> GetLoanTypes() {


        return BusinessLogic.GetLoanTypes();


    }


    static void SubmitLoanRequest(string name, int loanid, int value)  {


        BusinessLogic.SubmitLoanRequest(name, loanid, value);


        Navigate("HomePage");


    }


}


 


Clearly what I have here is as follows;


a)      A business logic class that does the work (implied, not typed out for brevity)


b)      An application controller that conforms to “Option 1” above


c)       A User Interface that uses the Application Controller


Because I am using “Option 1”, my call to get a list of Loan Types from the User Interface must go through the Application Controller to remain consistent with the approach. The submission of the loan request also goes through the controller, which calls the business logic and then makes a decision about page flow.


Let’s try to consider some of the advantages and disadvantages to this approach;













Advantages


Disadvantages


The Application Controller always gets to decide what should happen next. If, for example, a requirements change means a call to GetLoanTypes should redirect the user to a login page, it can do that with ease, and without any other classes changing.


Every business logic method that must be called from the User Interface must have a matching facade method in the Application Controller, even if it doesn’t add any behaviour, and literally just passes on the call (and I’ve seen this a lot). For a large system, this becomes a pain very quickly, from the point of coding effort, lines of code, maintenance effort, unit testing and so on.


There is a very clear pattern of execution – the UI can never short-circuit the approach to call directly into the business logic.


Is it really harder to add a call to the Application Controller if a navigation requirement changes than it is to add a line of code into the controller? I don’t think so, which I personally believe makes this approach overkill.


 


 


Option 2: Page Flow plus Occasional Logic Supervisor


Consider the implementation below;


class UserInterface


{


    void Page_Load(object sender, EventArgs e)


    {


        List<string> loanTypes = BusinessLogic.GetLoanTypes();


        LoanList.DataSource = loanTypes;


        LoanList.DataBind();


    }


 


    void SubmitButton_Click(object sender, EventArgs e)


    {


        ApplicationController.SubmitLoanRequest("Simon", 1, 2);


    }


}


 


class ApplicationController


{


    static void SubmitLoanRequest(string name, int loanid, int value)  {


        BusinessLogic.SubmitLoanRequest(name, loanid, value);


        Navigate("HomePage");


    }


}


 


What has changed? I’ve removed the requirement for business logic methods that do not have a navigation component to go through the Application Controller. Therefore, my User Interface calls directly to the business logic’s GetLoanTypes method. However, because I know SubmitLoanRequest will require a navigation event, I do call through the Application Controller, which in turns “supervises” calling the business logic and then performs the navigation as before.


Let’s try to consider some of the advantages and disadvantages to this approach;
















Advantages


Disadvantages


There is no need for every business logic call to have a facade method in the Application Controller – only those that have a navigation component are needed.


You must decide up front which operations have a possible navigation away from the current page involved.


 


Flow through the code is simplified – it is more obvious which logic components are used by each UI component.


If you want to change an operation so that it involves a navigation event, you must add code to the Application Controller and tweak your UI code.


 


There are now two ways to call business logic – through the Application Controller and from the UI. I think this lacks clarity.


 


 


Option 3: Page Flow Slave


Consider the implementation below;


class UserInterface


{


    void Page_Load(object sender, EventArgs e)


    {


        List<string> loanTypes = BusinessLogic.GetLoanTypes();


        LoanList.DataSource = loanTypes;


        LoanList.DataBind();


    }


 


    void SubmitButton_Click(object sender, EventArgs e)


    {


        BusinessLogic.SubmitLoanRequest("Simon", 1, 2);


        ApplicationController.CompleteSubmitLoanRequest(true);


    }


}


 


class ApplicationController


{


    static void CompleteSubmitLoanRequest(bool success)  {


        if (success)


           Navigate("HomePage");


        else


           Navigate("ErrorPage");


 


    }


}


 


What has changed this time?


We’ve now completely removed any interaction between the Application Controller and the business logic, instead letting the UI handle all of this. The controller is purely responsible for deciding what to do next, or “controlling the flow”. Note that I have also added a Boolean parameter purely to illustrate that the controller may need additional state – which we will discuss further shortly.


Let’s try to consider some of the advantages and disadvantages to this approach;
















Advantages


Disadvantages


The controller’s responsibilities become very clearly defined and encapsulated.


The Application Controller might need some information from the business logic to make a decision. This could complicate the UI code as it may need to fetch extra data to pass into the controller, or might corrupt our approach by having the controller call into the business logic again!


It is easy to change the way page flow works, perhaps by introducing Page Flow components (e.g. Windows Workflow) because the controller is kept simple and free from other responsibilities.


If you want to change an operation so that it involves a navigation event, you must add code to the Application Controller and tweak your UI code.


There is no need for facade methods to any business logic methods.


 


 


So which is best?


This is where I dodge the question. The point is – which do you prefer? I personally prefer Option 3 – I find it keeps the controller’s responsibilities very clearly defined, and when combined with other UI patterns (e.g. MVP) keeps a good balance of code in the right places. I think it also makes testing easier – as you are only testing a controller for flow, not business logic. But I wouldn’t claim this to be the only way.


 


State


It is worth making a point about state too. An Application Controller needs to make decisions – and these need to be based on what the user did, what they previously did (e.g. if they’ve not logged in, they will be treated differently to a user that has logged in), and what their state means (e.g. if they are under 17, the “CanApplyForUKDrivingLicense” setting would be false). This means the controller needs some awareness of state.


There are three ways to deal with this (you’ll be sick of option lists by the end of this series I’m sure!);


1.       Store state in the Application Controller. Expose properties to the UI to get/set state for the current user. This works well, I think, as it centralises your state management. Check out the StateValue<T> and StateDependency features of the WCSF for this.


2.       Pass all required state into your Application Controller when you call a method on it. This can also work, as long as you don’t have too much state to be passing around.


3.       Have your Application Controller call out into your business logic to get the results of rules based on some state. This is only half a solution, as you will need to know some of the “who” and “what” first anyway. I also think it corrupts the model a little, and so I prefer to avoid this where possible.


In reality, I usually use a combination of (1) and (2) – (1) for real user state, and (2) for the results of business rules.


 


What is Page Flow?


The final topic to cover is the definition of Page Flow. This is absolutely not the same as “site navigation”. If you try to model the whole of your web site using some kind of Page Flow mechanism, whether that is an Application Controller or otherwise, you will (in my opinion) be creating a tonne of work for yourself. Instead, use the standard ASP.NET navigation controls, hyperlinks, buttons, menus, etc to navigate around your site. This is what they’re there for – and making use of them should keep your pain levels low!


Page Flow is when you have a process in your site that should be completed from end to end – for example, a hotel booking wizard, or a mortgage application. This process might be reached and initiated by a hyperlink from your home page, but once within the process the “back” and “next” buttons would use an Application Controller to determine the steps through the wizard.


If you now take a step back and consider the options presented above, I find that this understanding of page flow is a natural fit with my preferred option 3. Not all pages will be part of a “flow”, so what do you do with the business logic calls then? Should they go through a controller when there is no need for one to assist with page flow? I don’t think so.


 


Summary


I hope this has helped you think about the Application Controller pattern. Chances are you’ll recognise many of these different approaches, but if you think I’ve missed any shout up – I’m always keen to hear what others are doing, and how successful each approach has been. Stay tuned for a look at MVP!


* over simplification intended!


 

Comments (23)

  1. WCSF Application Architecture 3: Model View Presenter This article is part of a series; · WCSF Application

  2. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  3. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  4. Katie says:

    You have saved my butt on my new project!! You have explained Fowler’s pattern much more simply than the great man himself. Now I have the confidence (am new to Enterprise Architecture patterns) to implement it myself. Thankyou thankyou thankyou!!

  5. Simon J Ince says:

    Katie;

    Great, and thanks – really pleased you’re finding it useful!

    Simon

  6. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  7. This article is part of a series; · WCSF Application Architecture 1: Introduction · WCSF Application

  8. Preguntas como por que se colocan las propiedades en la interfase de la vista, que debe de ir en el Application

  9. Chris Aniano says:

    Hi Simon,

    Since I am kinda new with this one, can/may I have an source code(sample) of the above implementations?

    here’s my email:

    <snip>censored by simon</snip>

    Thanks in advanced.

  10. Simon J Ince says:

    @ Chris,

    I censored your email so you don’t get spammed 🙂 I also just posted this under your other comment, which should answer your question…

    Unfortunately there isn’t any code for the series – purely because the code is either so small to intentionally communicate a point (e.g. for MVP or Application Controller posts), or the post is much higher level and theoretical.

    If you’re after code samples I’d recommend looking at the p&p reference implementations that come with the factory. There are other code samples out there too (I’m sure David Hayden has done some for example).

    Hope that helps!

    Simon

  11. This is the second article of a series written by Simon Ince , to view the first post visit the link

  12. This is the second article of a series written by Simon Ince , to view the first post visit the link

  13. This is part 3 of the WCSF Application Architecture series by Simon Ince this post explores the Model

  14. Jason says:

    that’s an great article, save my time in learn WCSF,thank you very much.

  15. Yoganand says:

    Simon;

    I would really thankful for explanation of Application Controller approaches, which helped me while I was thinking about implementing unique integration technology in the form of generic ApplicationController that can be embedded in any environment.

    Thanks again.

  16. Nilesh says:

    This is really helpful. I was looking for example of ApplicationController to implement in my current project that I am working on. Thanks a lot for wonderful explaination.

    Regards,

    Nilesh Gule

  17. First of all thanks for the great articles about WCSF!

    But I do have a question:

    How do you achieve reusing a view (.aspx page) in a different page flow (process)?

    It seems to me that this is impossible in WCSF. The view receives the presenter from the system and the presenter receives the controller but I don’t see any possibility to decide which controller to use. I have the impression everything is hooked up in the wrong order to achieve reusing a view in an other page flow. In WCSF a user browses to a page and so it’s actually the view that decides which process (page flow) is started. Would the ASP.net MVC framework be better suited for this?

    Steven Hillaert

  18. Simon J Ince says:

    @ Steven,

    that’s a good question. I think it applies equally to the MVC framework as the WCSF – remember the Controller in MVC is not an "Application Controller". Instead the MVC is similar to MVP, so in fact the question is how do we decide which Application Controller (or any page flow implementation) to use from within the Presenter (in MVP) or Controller (in MVC)? I find it curious that not many people have discussed using an Application Controller in MVC yet.

    Anyway, the issue you’re referring to is that in the WCSF most people inject a controller into the presenter using a [CreateNew] attribute… but you needn’t do it that way if you don’t want to. You could instead inject a ControllerFactory of some form, and use that to create a Controller based on further metadata available to the Presenter (perhaps some session data, or a querystring argument). You could also use a Service Locator approach instead of injection to achieve the same thing.

    The other way that view reuse can be achieved is to create a User Control with an MVP trio… although how you compose these can be a complex subject so give it a try and see if it fits your approach.

    Does that help?

    Make sure you check out Blaine’s post & survey here and feedback if this needs further guidance;

    http://blogs.msdn.com/blaine/archive/2009/07/20/patterns-and-practices-wants-you-to-take-the-web-guidance-survey.aspx

    Simon

  19. @ Simon,

    Concerning WCSF:

    During the weekend I came to the same conclusions as you on how to implement this in WCSF. I think the the querystring is the most flexible and practical, the only problem I see with this is that the page could be "injected" into a different process (pageflow) quite easily, some security will be needed here. An other issue is that the controller will have to implement an interface for every step (view) of the process because the presenter might used several controllers that don’t necessarily have the same interface.

    Concerning MVC:

    I had a quick look at it (reading) and I would think that reusing a view is a lot easier here. The controller in MVC is a front controller, the user actually "surfs" to the controller and not directly to a view. So you can make the user surf directly to a process and then the process (controller) decides which view to load.

    Thanks for your help Simon, I will definitely take the survey and give feedback concerning this topic.  

    Steven

  20. Simon J Ince says:

    @ Steven,

    no problem! Let me know how you get on…

    Simon

  21. Hi Simon,

    I created my implementation for reusing views in WCSF. The details can be found on my blog http://blog.hill-it.be‘>http://blog.hill-it.be.

    If you have any remarks or questions feel free to let me know.

    Steven

Skip to main content