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

·         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!

Orginally Posted by Simon Ince on Friday, June 06, 2008 here.