Decoupling Workflow And Forms With An Application Controller

18 April, 2009. It was a Saturday.

One of the big problems I’ve been trying to solve recently, is in my current WinForms application that using a Model-View-Presenter setup. I have my workflow between forms coupled to the forms directly. That is, in order to get from MainForm to SubForm, I have code inside of MainForm instantiate SubForm and it’s Presenter. The nightmares of changing any part of the workflow because of this, are astounding. I won’t go into great detail on the problems. It should be sufficient to know that my form codebehind would often contain several hundred lines of code to create all the needed views and presenters for a workflow, per workflow.

Building A Solution

There are two parts of the solution that I’m trying to use now, that are relatively new to me.

1) Use a good IoC container. I’m using StructureMap at the moment. I’ve used Windsor in the past and don’t like some of the default conventions it has. StructureMap’s conventions fit very well with my personal style of development (at least in part because I’ve considered Jeremy Miller to be a mentor – via his blog, etc – for several years now). Although I have done IoC / DI / DIP before, I’ve not used a good IoC container in quite some time. I’ve primarily been using a ServiceLocator and manual Dependency Inversion.

2) Set up an Application Controller to hide most of the coordination and infrastructure needs, including the IoC container, from the rest of the application.

Application Controller

“Some applications contain a significant amount of logic about the screens to use at different points, which may involve invoking certain screens at certain times in an application. This is the wizard style of interaction, where the user is led through a series of screens in a certain order. In other cases we may see screens that are only brought in under certain conditions, or choices between different screens that depend on earlier input.

To some degree the various Model View Controller input controllers can make some of these decisions, but as an application gets more complex this can lead to duplicated code as several controllers for different screens need to know what to do in a certain situation.

You can remove this duplication by placing all the flow logic in an Application Controller. Input controllers then ask the Application Controller for the appropriate commands for execution against a model and the correct view to use depending on the application context.”

For the last month or two, I’ve been trying to find as much information as possible, on Application Controller, with little to no luck in finding any information on WinForms development. Then Dino Esposito posted an article on “The Presenter in MVP Implementations” over at DotNetSlackers where he discusses the idea of introducing an Application Controller into an MVP application, to control the workflow. This was exactly what I was looking for… or so I thought. After playing around with the structure that he introduces, I found myself wanting more – specifically wanting a better decoupling of the workflow from the AppController.

My Application Controller Implementation

After working with various ideas for the last month, I finally have an example implementation that I’m happy with. The core of the sample is the Application Controller, of course. Surprisingly, it is a very simple implementation. The primary functionality that I ended up needing in my Application Controller, is the ability to execute an [ICommand](http://www.lostechies.com/blogs/derickbailey/archive/2008/11/19/ptom-command-and-conquer-your-ui-coupling-problems.aspx) interface, and publish an event via an [EventAggregator](http://martinfowler.com/eaaDev/EventAggregator.html). Both the ICommand and EventAggregator that I use, are heavily influenced by Jeremy Miller’s [Build Your Own CAB](http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx) series.

I also included an IApplicationController interface definition, for easy Dependency Injection, etc. This interface is a core part of my complete solution, and is referenced by all of my Presenters.

namespace ApplicationControllerExample.AppController

{

publicinterface IApplicationController

{

void Execute<T>(T commandData);

void Raise<T>(T eventData);

}

}

</div> </div>

Reference IApplicationController From The Presenters

With this in place, I can now set up my Presenters to use the IApplicationController instead of having direct references to ICommand objects, or the IEventPublisher object. This allows me to simplify the dependency list in many of the presenters that I have – especially the “Menu” presenter that has 20 or 30 menu commands… one command for each menu item.
</p>

When a Presenter needs to kick off a workflow or raise an event, all it needs to do is call out to the IApplicationController. This allowed the individual presenters and WinForms to be decoupled from the workflow.

The call to AppController.Raise() will use the EventAggregator to publish an event of type SomeEventData. In this case, I have the very same presenter registered to handle the event, which isn’t terribly exciting – but it does illustrate the point of it working.

Building An ICommand And Workflow Service
</h3>

The call to AppController.Execute(), in the above Presenter example, will load up the ICommand object from StructureMap and execute it. The ICommand interface is implemented by an explicit object. This is where I would include any workflow definition that I need to start up and run.
</p>

namespace ApplicationControllerExample.Model

{

publicclass SomeCommand: ICommand<SomeCommandData>

{

private ISomeWorkflowService WorkflowService { get; set; }

public SomeCommand(ISomeWorkflowService workflowService)

{

WorkflowService = workflowService;

}

publicvoid Execute(SomeCommandData commandData)

{

WorkflowService.Run();

}

}

}

</div> </div>

Since I am using StructureMap to instantiate this object, it will inject the ISomeWorkflowService registered instance for me, which depends on a role specific interface called IPartOfTheProcess.

</p>

namespace ApplicationControllerExample.App

{

publicclass SomeWorkflowService: ISomeWorkflowService

{

private IPartOfTheProcess PartOfTheProcess { get; set; }

public SomeWorkflowService(IPartOfTheProcess partOfTheProcess)

{

PartOfTheProcess = partOfTheProcess;

}

publicvoid Run()

{

PartOfTheProcess.DoThatThing();

}

}

}

</div> </div>

Looping Back To The App Controller

The IPartOfTheProcess interface is implemented by another Presenter. This Presenter depends on the IApplicationController interface. By having that dependency, I can start the chain all over again. The "SecondaryPresenter” can call out the AppController and execute another command or raise another event to be published.

private IApplicationController AppController { get; set; }

{

View = view;

AppController = appController;

View.Presenter = this;

}

publicvoid DoThatThing()

{

View.Run();

}

publicvoid Whatever()

{

AppController.Raise(new SomeEventData("you did what?"));

}

publicvoid ThatThingHappened(string s)

{

AppController.Raise(new SomeEventData("click-o-that menu"));

}

}

}

</div> </div>

Conclusions

I think you get the idea by now… by including the IApplicationController dependency in my presenters, I no longer have to worry about coupling my specific presenters to any part of the workflow, or my workflow to any specific presenters. And notice that I haven’t even mentioned the WinForms that I’ve implemented for the I(whatever)View interfaces. I don’t care anymore. I implement a view interface however I want to, and register that Implementation with StructureMap.

The combination of a good IoC container (pick the one you like; it doesn’t have to be StructureMap), an Application Controller, and some good old Dependency Inversion and Interface Separation (with a healthy dose other SOLID principles), can really help to decouple a system, very quickly.

I’m quite happy with this little example, at this point. It is helping me to solve some of the most painful coupling problems that I’ve had in the last 9+ months of my current project. I’m sure I will run into situation in the future, where this simple ApplicationController needs to be extended, though.

Download The Example App

As a side note – I used this example app as an opportunity to not only learn the ApplicationController pattern, but also to learn Git source control, using msysgit. With that in mind, I decided to push the sample app out to GitHub.

If you would like to download the entire codebase for this sample, and see how it all comes together to create a working program, you can get it here: