CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

Build your own CAB: The Main Players in the Composite Application Neighborhood

I spent a week in Redmond in January taking part in a focus group on the vision for the P&P's new Prism work on composite applications.  Part of the week long exercise was to identify the basic building blocks of building large composite clients. This is my list of the significant parts of an application that I see regularly reoccurring from app to app.  For CAB fans, you'll note that there is no "WorkItem" in my list, but the responsibilities that it fulfills in the CAB framework are all present in other (more logical) places.  if you're moving onto Composite Application Street, these are the classes and in your neighborhood (, in your neighborhood, in your neigh-bor-hood, oh here are... ):

 

The IoC/DI tool of your choice

These tools are good for more than just crowbarring mock objects into your code.  When you're talking about extensibility and modularity, an IoC tool is an easy way to wire up new Views, Presenters, and Services to your existing application.  If you take a long look at the CAB, you'll see that a major portion of it is related to Dependency Injection and (ObjectBuilder) and service location (the WorkItems).  One of the main reasons that I've always been dismissive of the CAB itself is how easy it is to roll your own framework wrapped around an existing IoC tool.   You could build a composite application without an IoC tool, but the responsibilities that were assumed by an IoC tool are just accomplished by something else (or hard coded which would pretty well shoot down the idea of a composite application).  Obviously I'm biased here, but I think that using an IoC tool is a huge shortcut in building any kind of extensible application.  Assuming that that level of extensibility is actually justified of course;-)

 

Application Shell

The main form that contains everything else.  The responsibility of the shell is to hold the main components of the user interface like menus, ribbon bars, and holders (panels, docking managers, etc.) for the screens that get activated later.  This should be fairly thin, and there's some very real danger in the ApplicationShell becoming a catch all that collects way too many unrelated responsibilities.   

 

ApplicationController

The Application Controller pattern identified by Martin Fowler is "A centralized point for handling screen navigation and the flow of an application."  The ApplicationController controls the screen activate lifecycle and the lifecycle of the main form.  In most of my systems other screens are activated by calling methods on the ApplicationController.  In smaller systems the ApplicationController would also control screen workflow.  In larger systems I would break some of that responsibility out into separate collaborating classes.

I should point out that the ApplicationController is probably going to be a full blown subsystem in its own right.  The Single Responsibility Principle will often drive you to split the ApplicationController into some smaller parts:

  1. Screen Conductor -- Controls the activation and deactivation lifecycle of the screens within the application.  Depending on the application, the conductor may be synchronizing the menu state of the shell, attaching views in the main panel or otherwise, and calling hook methods on the Presenter's to bootstrap the screen.  It may also be just as important to deactivate a screen when it's made the inactive tab to stop timers.  My first exposure to a Screen Conductor was an insurance application that was built with web style navigation.  Anytime the user moved away from a screen we needed to check for "dirty" screens to give the user a chance to deal with unsaved work.  On the other hand, we also had to check the entry into a requested screen to see if we could really open the screen based on pessimistic locking or permission rules.  We pulled our a Layer SuperType for our Presenters for methods like CanLeave() and CanEnter().  The Screen Conductor would use these methods and others to manage screen navigation.
  2. Screen Collection -- In applications that have some sort of tabbed or MDI display of screens, you usually need to track what screens are active.  The easiest example I can think of is a TradeCapture application I built last year.  When a user opened a trade from either a search screen or by entering a trade id, the trade ticket window would popup in a separate window.  It was important that there only be one window for each trade up at one time, so if the user happened to request the same trade that was already opened, we would just show the existing screen instead of opening a brand new screen.  We used a Screen Collection class to track the open screens so that we could retrieve the active screen for an individual screen.  I've seen this pop up on at least 3 separate occasions now.
  3. Screen Subject -- I've only used this a couple times, but it's going into my regular rotation from now on.  I've built several applications along the tabbed display motif now.  In many of them there's a need to respond to a navigation request by first checking if the screen exists to either make the already open screen be the active tab or to create a brand new screen and make that the active tab.  I've gone to the idea of a ScreenSubject object that can determine if it matches an open Presenter and knows how to create the new screen if it isn't already open.  ScreenSubject works very closely with Screen Collection.

 

Others

  • Bootstrapper and Registry - The IoC container and the ApplicationShell has to be constructed somewhere.  I like to put all of the "bootstrapping" into a class called, wait for it, Bootstrapper.  It's very useful to keep this separate from the ApplicationShell itself, both to keep the ApplicationShell cleaner and also to enabled integration testing scenarios that test partial application stacks.  Bootstrapper is also responsible for spinning up any services that need to run throughout the application lifecycle (like caching or the event aggregator).  The Registry is an optional piece that contains configuration for a specific module.  It might help configure the IoC container, add more menu items to the shell, or attach new services.
  • Model, View, and Presenter - I won't rehash these pieces here.  See the rest of Build your own CAB for more information.  There's about a hundred different ways to divide and organize these three things.
  • Service - The most overloaded term in all of software development.  Roughly put, it's the classes that you interact with that aren't one of the other things.  I would strongly recommend that
  • Command - Gang of Four Command objects.  "Jeremy's first law of enterprisey systems" -- Every system of sufficient complexity will have an ICommand interface.  This subject deserves its own chapter/post.
  • Event Aggregator / Event Broker - Here and here.  I'm going to include at least three different flavors of this in my book.
  • CommandExecutor - Also known as the Active Object.  I like to use Command Executor to standardize the way my applications use background threading.

 

 

What did I miss?  Comments are open.



Comments

The Build Your Own CAB Series Table of Contents - Jeremy D. Miller -- The Shade Tree Developer said:

Pingback from  The Build Your Own CAB Series Table of Contents - Jeremy D. Miller -- The Shade Tree Developer

# March 8, 2008 2:23 PM

Weston M. Binford III said:

So, how soon can we get that blog post on Command?

# March 8, 2008 2:59 PM

Jeremy D. Miller said:

You know how it works Weston.  Ask me to do it, I say yes, then you pester me for two months until it happens.

# March 8, 2008 4:07 PM

main menu said:

Pingback from  main menu

# March 8, 2008 8:00 PM

Rob said:

I'd love to hear a little more about the Screen Conductor/Screen Collection/Screen Subject.  The other patterns you mentioned are familiar to me, and we used all of them on our last WPF project.  This is when I really began to flesh out Caliburn.  However, the other three all ended up as part of our application controller logic; probably because the system was not complex enough to factor out these classes.  Nevertheless, I'd like to here you talk about some scenarios where this factoring would be appropriate.

# March 8, 2008 10:32 PM

Morten Lyhr said:

Hey Jeremy

Thats for another great post, Just giving me the names of your classes and outlining their responsibilites, makes me re-think the designs I do.

The bootstrapper is a great name ;-) I had a class called ConvesionOverConfiguration. That basically runs through all the types in my assemblies and matches based on different conventions. This makes need for XML or Atributes needless, and you can quickly explain someone how to name classes and interfaces. I think Ayende had a post about it a while back.

- Class postfixed with Presenter and View should implement IPresenter and IView.

- The part before Presenter and View should have a matching part of the other. LoginView - LoginPresenter.

- Interfaces postfixed with Service, should have a matching class that implements it also postfixedwith Service. IAuthenticationService - ADAuthenticationService.

- Class's prefixed with Default has a matching Interface without Default and with an I. DefaultDataBinder - IDataBinder.

The "Bootstrapper" can be run in a test that runs faily fast, and veryfies that everything is in order.

Also wrapping the Presenter/View pair up in a Factory, makes it more clear what happens.

# March 9, 2008 7:48 AM

Trumpi's blog said:

Daily link is back after 2 months. Misc Build your own CAB: The Main Players in the Composite Application

# March 9, 2008 9:27 AM

Dew Drop - March 9, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from  Dew Drop - March 9, 2008 | Alvin Ashcraft's Morning Dew

# March 9, 2008 3:22 PM

jimbono said:

Hi Jeremy,

Great to see you continue the BYOC series. I've been digging StoryTeller for a while now and I've got to tell you, its a a great little piece of software teaching folks how to write clean quality code.

Keep it up!

Cheers

jim

# March 10, 2008 12:17 AM

Tore Andre said:

Hi Jeremy,

I'd love to see a fully working example (VS 2005 solution) for all parts of this series. Working examples are essential to me when I'm learning new stuff like this. Any plans for doing that, or maybe it already exists??

# March 13, 2008 10:48 AM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP