Decoupling Workflow And Forms With An Application Controller

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

Martin Fowler’s PoEAA book says this about Application Controllers:

“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<T> interface, and publish an event via an EventAggregator. Both the ICommand<T> and EventAggregator that I use, are heavily influenced by Jeremy Miller’s Build Your Own CAB series.

using EventAggregator;

using StructureMap;

 

namespace ApplicationControllerExample.AppController

{

 

 public class ApplicationController : IApplicationController

 {

 

   private IContainer Container { get; set; }

   private IEventPublisher EventPublisher { get; set; }

 

   public ApplicationController(IContainer container, IEventPublisher eventPublisher)

   {

     Container = container;

     EventPublisher = eventPublisher;

     

     Container.Inject<IApplicationController>(this);

   }

 

   public void Execute<T>(T commandData)

   {

     ICommand<T> command = Container.TryGetInstance<ICommand<T>>();

     if (command != null)

       command.Execute(commandData);

   }

 

   public void Raise<T>(T eventData)

   {

     EventPublisher.Publish(eventData);

   }

 

 }

 

}

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

{

 public interface IApplicationController

 {

   void Execute<T>(T commandData);

   void Raise<T>(T eventData);

 }

}

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<T> 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.

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.

using ApplicationControllerExample.AppController;

using ApplicationControllerExample.Model;

using EventAggregator;

 

namespace ApplicationControllerExample.App

{

 

 public class MainPresenter: IEventHandler<SomeEventData>

 {

 

   private IMainView View { get; set; }

   private IApplicationController AppController { get; set; }

 

   public MainPresenter(IMainView mainView, IApplicationController appController)

   {

     View = mainView;

     AppController = appController;

     View.Presenter = this;

   }

 

   public void Run()

   {

     View.Run();

   }

 

   public void DoSomething()

   {

     AppController.Execute(new SomeCommandData());

   }

 

   public void SomethingElseIsHappening()

   {

     AppController.Raise(new SomeEventData("Something done here"));

   }

 

   public void Handle(SomeEventData eventData)

   {

     View.SaySomething(eventData.Message);

   }

 }

 

}

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<T> And Workflow Service

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

namespace ApplicationControllerExample.Model

{

 public class SomeCommand: ICommand<SomeCommandData>

 {

   private ISomeWorkflowService WorkflowService { get; set; }

 

   public SomeCommand(ISomeWorkflowService workflowService)

   {

     WorkflowService = workflowService;

   }

 

   public void Execute(SomeCommandData commandData)

   {

     WorkflowService.Run();

   }

 }

}

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.

namespace ApplicationControllerExample.App

{

 public class SomeWorkflowService: ISomeWorkflowService

 {

   private IPartOfTheProcess PartOfTheProcess { get; set; }

 

   public SomeWorkflowService(IPartOfTheProcess partOfTheProcess)

   {

     PartOfTheProcess = partOfTheProcess;

   }

 

   public void Run()

   {

     PartOfTheProcess.DoThatThing();

   }

 }

}

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.

using ApplicationControllerExample.AppController;

using ApplicationControllerExample.Model;

 

namespace ApplicationControllerExample.App

{

 public class SecondaryPresenter: IPartOfTheProcess

 {

   private ISecondaryView View { get; set; }

   private IApplicationController AppController { get; set; }

 

   public SecondaryPresenter(ISecondaryView view, IApplicationController appController)

   {

     View = view;

     AppController = appController;

     View.Presenter = this;

   }

 

   public void DoThatThing()

   {

     View.Run();

   }

 

   public void Whatever()

   {

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

   }

 

   public void ThatThingHappened(string s)

   {

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

   }

 }

}

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:

http://github.com/derickbailey/appcontroller/tree/master


Post Footer automatically generated by Add Post Footer Plugin for wordpress.

About Derick Bailey

Derick Bailey is an entrepreneur, problem solver (and creator? :P ), software developer, screecaster, writer, blogger, speaker and technology leader in central Texas (north of Austin). He runs SignalLeaf.com - the amazingly awesome podcast audio hosting service that everyone should be using, and WatchMeCode.net where he throws down the JavaScript gauntlets to get you up to speed. He has been a professional software developer since the late 90's, and has been writing code since the late 80's. Find me on twitter: @derickbailey, @mutedsolutions, @backbonejsclass Find me on the web: SignalLeaf, WatchMeCode, Kendo UI blog, MarionetteJS, My Github profile, On Google+.
This entry was posted in .NET, AppController, C#, Design Patterns, Git, Model-View-Presenter, Principles and Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Marcos

    Thanks a lot, looks really interesting.

  • Rei

    Isn’t this more typically called MVC?

  • Jeremy Wiebe

    @Rei: I think in this case, the ApplicationController is not an MVC controller, but truly is an Application Controller as per Fowler’s definition which Derick mentioned near the beginning. The presenter’s that are mentioned in this post are often synonymous with controllers from MVC (please correct me if that’s not true..)

    @Derick: fantastic post! Really enjoying your blog since I’ve found it. Since we’re doing WinForms development it’s nice to see some great blog posts about WinForms in the age of WPF and Silverlight. :-)

  • http://www.indiecodelabs.com Enrique Ramirez

    Interesting post. I’ve been looking for something along these lines for a while since coupling problems in WinForms development is my major pain point right now. I didn’t get this 100% since the example is really abstract, but I’ll jyst try to read through it and the code over and over until I get it.

    Again, (like Jeremy said) thanks for writing about Winforms in this age of Web/Silverlight/WPF.

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    @Enrique,

    Glad the post helped at least a little! I’m currently writing a much more elaborate, closer-to-real-world example app and presentation based on this blog post, and am hopefully going to be giving a presentation on it at the upcoming Austin Code Camp, on May 30th.

    I know you’re not in the Austin area (saw your Twitter location), but I’ll be posting the complete presentation and solution on my blog some time soon after the code camp. Hopefully it will be a little more enlightening. :)

  • http://www.indiecodelabs.com Enrique Ramirez

    Oh man, I really wish I could make it to the code camp. I made it a priority to make budget for next year to try to make it to at least one code camp (hopefully somewhere I can get a cheap flight to).

    In any case, I really hope to get an “Ah-ha!” moment out of your presentation. Right now I’m using the MVP pattern as described by Craig Shoemaker in his site. The separation of logic is nice, but I still run into a lot of coupling problems when one form has to instantiate and call another and depends on what the user did or entered in that other form.

    Something that I missed the first time around (I think I was speedreading through it just before leaving work), was the idea of using an IoC container to achieve this level of decoupling. I’m yet to use an IoC container, but putting it in context, your code makes a bit more sense now. Time to go read up on IoC containers…

  • http://www.lostechies.com/members/derick.bailey/default.aspx derick.bailey

    @Enrique,

    I’ve basically completed the “real world” example application for my upcoming presentation. I decided to use a very simple Org Chart as the sample app. There are a few key pieces of the sample app that I’ll try to outline further, in another blog post: on the main form, I’m using the EventAggregator to get notification of employees being added, and employees being selected from the org chart to display their info. I’m also using an ICommand to kick off the add new employee wizard, and using a workflow service object to run the add new employee wizard.

    I hope that this app, being a little more “real world”, will help to shed some more light on the AppController and the other patterns that are in play, for you.

    You can get a copy of this app from my Github repository, at:

    http://github.com/derickbailey/presentations-and-training/tree/

    under the “Decoupling Workflow With App Controller” folder.

  • David

    I know its been a while since this was first posted, but thank you very much for this excellent example. It’s almost 6 months ago that I went through your example with a fine tooth comb and it was the first time I finally had my “a-ha” moment and understood the power of dependency injection, and this post was the starting point.

    I have gone on to build great things since then, and I have a question:

    In your example, in order to allow the presenters to use the user controls created by the designer, you inject into the container the control instance in the constructor.

    public MainForm(IContainer container)
    {
    InitializeComponent();
    container.Inject(ViewEmployeeDetail);
    }
    My problem is, what do you do when you have a user control that contains another user control? You cannot put IContainer as a parameter, since user controls can’t handle this.

    There is now a BuildUp() function in structuremap, but setter injection seems to solve a different problem …

    My current work around has been to reference structure map statically like so

                  public MyControl()
                  {
                            InitializeComponent();
                            ObjectFactory.Inject(ChildControl);
                   }

    however I’d love to know if you have a way to solve this and still be able to use IContainer rather than the static instance.

    thanks again
    Dave

    • http://mutedsolutions.com Derick Bailey

      the sample code that i link to at the bottom of the post shows how to use IContainer. You can see it at https://github.com/derickbailey/appcontroller/blob/master/src/SimpleOrgChart/View/MainForm.cs#L15-19

      if I remember right (it’s been 3 years), IContainer is added to the container automatically, by StructureMap.