Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
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?


Posted Fri, Feb 15 2008 12:13 PM by Jeremy D. Miller
Filed under:

[Advertisement]

Comments

The Build Your Own CAB Series Table of Contents - Jeremy D. Miller -- The Shade Tree Developer wrote The Build Your Own CAB Series Table of Contents - Jeremy D. Miller -- The Shade Tree Developer
on Fri, Feb 15 2008 12:16 PM

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

Rob wrote re: Build your own CAB #18: The Command Executor
on Fri, Feb 15 2008 2:31 PM

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.

Jeremy D. Miller wrote re: Build your own CAB #18: The Command Executor
on Fri, Feb 15 2008 2:32 PM

Rob,

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

David Mohundro wrote re: Build your own CAB #18: The Command Executor
on Fri, Feb 15 2008 4:47 PM

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.

Scott Bellware wrote re: Build your own CAB #18: The Command Executor
on Fri, Feb 15 2008 5:06 PM

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 :)

Udi Dahan wrote re: Build your own CAB #18: The Command Executor
on Mon, Feb 18 2008 1:25 AM

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?"

:-)

Jeremy D. Miller wrote re: Build your own CAB #18: The Command Executor
on Mon, Feb 18 2008 3:19 AM

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

Dan Ports wrote re: Build your own CAB #18: The Command Executor
on Fri, Feb 22 2008 9:59 AM

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.

Jeremy D. Miller wrote re: Build your own CAB #18: The Command Executor
on Fri, Feb 22 2008 10:20 AM

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

Chad Myers' Blog wrote Ping-pong Pairing, it's not just for breakfast anymore
on Tue, Mar 4 2008 8:00 PM

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

ed wrote re: Build your own CAB #18: The Command Executor
on Wed, Mar 5 2008 3:53 AM

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

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB: The Main Players in the Composite Application Neighborhood
on Sat, Mar 8 2008 2:22 PM

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

nblog wrote Tfs Spotlight – buduję własny CAB
on Tue, Mar 11 2008 7:06 AM

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

Andrew wrote re: Build your own CAB #18: The Command Executor
on Thu, Apr 9 2009 12:28 PM

Hello Jeremy,

Great article, how would you go about handling exceptions that are generated in the Command's execute method?  How would you go about displaying that error message to the user? (in a way that can be unit tested)

Thanks,

Andrew

repair credit wrote repair credit
on Fri, Sep 18 2009 5:23 AM

Long- time followers of this blog - you rule - the people make the blog!

Add a Comment

(required)  
(optional)
(required)  
Remember Me?