The Command pattern is one of my all time favorite patterns. I have used it numerous times in programming with great success. Recently, while rearchitecting an application I am reworking for a client I needed a means to encapsulate the logic that called a web service and caught the corresponding error or processed the result if it succeeded.
The principle problem is that these calls must support the ability to retry the call should it fail. The previous developer used loops in each function to support this requirement, flagrantly violating DRY. My approach was a permutation on the Command pattern. Pass a command object into a Executor class. The class would treat the object generically the same, simply calling a command method which would call the particular web service method via a layer of indirection. Here is my first rough implementation of this idea:
1: public T Execute(ICommandRetry command) where T : ResultBase
2: {
3: int attempts = 0;
4:
5: do
6: {
7: try
8: {
9: return Execute((ICommand)command);
10: }
11: catch (CommunicationException)
12: {
13: var retry = FireOnRetryEvent();
14: if (!retry) break;
15: attempts++;
16: }
17: } while (attempts < command.RetryAttempts);
18:
19: throw new Exception("Unable to complete communication");
20: }
In addition, I wanted to make sure I could control the return type of the call so I could maintain type safety, hence I used generics. In a later version of this code, I made the RetryAttempts property virtual and defaulted it to 0, which would yield only one attempt. Derivative command objects could overwrite this as necessary.
For the most part this worked except that it yielded three classes for each web service operation (input, result, and command classes). This is simply too much ceremony and given the team that will support the application would result in being very ornery and error prone. Hence I decided to look for another way. I found it using lambda expressions.
There are three basic lambda expressions in .NET: predicate which is used for Is comparisons, action which is used to simply call a function with no return value, a func which is the same action, save it supports a return value. An analysis of the previous code yielded the stipulation that all service calls will return a class with ResultBase as its parent. Hence we arrived at the following code:
1: static void Main(string[] args)
2: {
3: var function = new Func(i => (new Server()).Print(i));
4: var result = Command.Execute(function, new PrintInput {Name = "Jason"});
5: Console.WriteLine(result.Message);
6: Console.Read();
7: }
This is the structure of Command.Execute:
1: public static TResult Execute(Func theFunction,
2: TInput input)
3: where TResult : ResultBase
4: where TInput : InputBase
5: {
6: return theFunction.Invoke(input);
7: }
So what we have done is used a lambda to replace the original command object. This will operate exactly the same way. (Note: this is a different solution as the solution was reached at a later date). This cleans up our code base and reduces the amount of ceremony we need to go through, no more creating the command objects. However, we really dont like exposing the Func syntax in the main code, if our developers are not as fluent with C# as we are this can cause a great deal of confusion. In my case, the developers left to support this application will not be as fluent and need to have certain things stored away where they can be easily copied. For this, the best pattern is the Factory pattern. Hence we change our code to the following:
1: static void Main(string[] args)
2: {
3: var command = CommandFactory.GetPrintCommand();
4: var result = Command.Execute(command, new PrintInput {Name = "Jason"});
5: Console.WriteLine(result.Message);
6: Console.Read();
7: }
Not really much has changed except the addition of the CommandFactory static class. Here is the implementation:
1: public static class CommandFactory
2: {
3: private static Server _server = new Server();
4:
5: public static Func GetPrintCommand()
6: {
7: return _server.Print;
8: }
9: }
This actually works perfectly for my case. You can see that we were able to remove the crazy lambda that would have caused confusion and instead replace it with a much simpler expression and IN ADDITION, provide a function for it. This helps give our code meaning. This code also reads much easier with all the typing inferred rather then explicitly stated.