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 #18: The Command Executor

EDIT:  Oops on my part.  This is effectively the Active Object pattern. 

 

The rest of the Build your own CAB series can be found at the table of contents.

 

There's a thread on the altdotnet list this morning about how to unit test background operations originating from a screen Presenter.  I have a strategy for that in StoryTeller that I think has worked out quite well.  Instead of creating a background worker or thread directly in a screen presenter, I run all background actions through what I call a "Command Executor."  When a presenter or a menu command needs to run some sort of asynchronous command I have that class delegate to an instance of an ICommandExecutor interface.  The interface for the ICommandExecutor in StoryTeller is shown below:

    public interface ICommandExecutor : IStartable
{
void Stop();
void ExecuteCommandWithCallback(ICommand command, ICommand callback);
void ExecuteCommand(ICommand command);
}

You'll see that the ICommandExecutor takes in the inevitable ICommand interface because this was written in .Net 1.1 and ported upwards later.  I think for my new project I'm going to something more like this to take advantage of lambda expressions instead of cluttering up the code with extraneous class definitions.

public interface ICommandExecutor
{
void Execute(Action action);
void ExecuteWithCallback(Action action, Action callback);
}

Now, why would you do this?  Using a BackgroundWorker or a background thread isn't that hard, but:

  1. The threading code is noise code that distracts the reader from the real meaning of the code.  The CommandExecutor pattern let's us change the code semantics inside the Presenter into merely a call to "run this in the background."
  2. It's potentially a lot of repetitive code to set up threads or bootstrap a BackgroundWorker.  You have to remember to do the thread synchronization every single time.  By using a Command Executor you can write the multi threaded code once and only once, including the work to synchronize threads (I use a SynchronizationContext in my CommandExecutor for the callbacks.  No need for AOP black magic whatsoever).
  3. You do NOT want any important behavioral or business logic code to be coupled to the UI machinery.  I see a lot of teams absolutely screw themselves over by embedding logic directly into the DoWork event of a BackgroundWorker, rendering that code effectively impossible to reuse or unit test.  The CommandExecutor will help push teams to separate the behavioral logic away from threading infrastructure to make that code both easier to test and reuse.
  4. The background threading is rougher in unit testing.  Not impossible, but it does add some significant overhead to the unit testing effort.

Let's take the testing angle first.  The original problem was how to be able to unit test the background operation.  The easiest way is to simply turn the asynchronous behavior completely off by substituting in a synchronous command executor in the unit tests like this:

    public class SynchronousCommandExecutor : ICommandExecutor
{
public void Stop()
{
// no-op;
}

public void ExecuteCommandWithCallback(ICommand command, ICommand callback)
{
command.Execute();
callback.Execute();
}

public void ExecuteCommand(ICommand command)
{
command.Execute();
}

public void Start()
{
// no-op;
}
}

Now you can simply run your unit test and test the asynchronous behavior without having to setup ManualResetEvent's or other thread synchronization machinery.  In StoryTeller I usually just test that the proper ICommand message was sent to the ICommandExecutor and call it good enough.  I'll then turn around and test the ICommand.Execute() method in isolation in another unit test.

So far, I've found this pattern pretty well eliminates all of my unit testing problems with background operations.  For integration testing one of your challenges for testing a user interface is asynchronous events.  One of the solutions I've found to this problem is to route all background operations through some sort of CommandExecutor so that the test harness has a single place to watch in order to synchronize the test script with the user interface. 

 

 

Anyway, I banged this out fast.  Any thoughts?



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

# February 15, 2008 12:16 PM

Rob said:

Sweet!  This is almost identical to Caliburn's implementation.  I always feel a little better when I see that someone else has independently come up with the same solution as me.

# February 15, 2008 2:31 PM

Jeremy D. Miller said:

Rob,

Well in that case, I'll call it a real pattern.

# February 15, 2008 2:32 PM

David Mohundro said:

I definitely like this pattern (thanks for the help with this a few months back, too). I agree that accepting Action<T> or maybe Func<T> would make it more flexible with the new language features. I don't think enough people know about SynchronizationContext - it really makes threading code easy, too.

# February 15, 2008 4:47 PM

Scott Bellware said:

More banging out posts fast!!  For gosh sakes this was the only post in this series that I was able to finish!

(sez the guy who's writing density has been compared to Heidegger :)

# February 15, 2008 5:06 PM

Udi Dahan said:

You were baiting me, weren't you.

"I use a SynchronizationContext in my CommandExecutor for the callbacks.  No need for AOP black magic whatsoever"

You're solution works great - until you have to support pub-sub, where you get a "response" without ever having sent a "request".

Now that the client knows that "inventory levels for product X have dropped below threshold Y", wouldn't you want to show something to the user? How will you handle the threading concerns around that?

Black magic?

Go ask Udi: "How do you do that voodoo you do so well?"

:-)

# February 18, 2008 1:25 AM

Jeremy D. Miller said:

@Udi,

B.)  Go ask Udi: "How do you do that voodoo you do so well?"  I do have your email address, so yes, I probably would just ask you;)

Why wouldn't you be able to get away with that for pub/sub callbacks as well?  I do the same SynchronizationContext thing with my event aggregator (which now uses the generics trick I stole from you). When you set up the hub in your pub/sub strategy, couldn't you just have it fired up with the current SynchronizationContext to achieve the same ends?  If all of the notifications from the rest of the system and the front end come into that event aggregator, I've solved the thread synchronziation problem.  That does't handle any locking of course, but at least the threading synchronization.

# February 18, 2008 3:19 AM

Dan Ports said:

Yeah, I use a similar design. I have an ITaskFactory with an ITask Create(Action start) method. ITask has a Start method and a Finished event, and the implementation wraps the BackgroundWorker class. I like this option a bit better than yours from the OO perspective, and it also allows for the possibility of running multiple background tasks, which might be YAGNI in your case.

# February 22, 2008 9:59 AM

Jeremy D. Miller said:

@Dan,

In the system I took this from, it was actually important that the background tasks be queued in a single thread of operation.  There's no restriction on multiple background operations from this interface though.  Internally you just track the callback Action objects along with the Action being executed and call the callback.

I could easily see your ITask mechanism being nice if you need to cancel a long operation along the way.

Thanks for the comment.

# February 22, 2008 10:20 AM

Chad Myers' Blog said:

Yesterday was my first day working at my new employer, Bayern Software , with (name drop alert!) Jeremy

# March 4, 2008 8:00 PM

ed said:

you might want to have a look at how your code snippets are rendering. for me the BR tags are being displayed.

(I am using ie7 on vista)

I was trying to work out what the generic BR type was for a good 5 minutes before i realised

# March 5, 2008 3:53 AM

Jeremy D. Miller -- The Shade Tree Developer said:

I spent a week in Redmond in January taking part in a focus group on the vision for the P&amp;P&#39;s

# March 8, 2008 2:22 PM

nblog said:

Od kilku miesięcy nic tu nie pisałem (oczywiście poza poprzednim nieplanowanym wpisem ). Jak łatwo się

# March 11, 2008 7:06 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