Geeks With Blogs
Charles Courchaine Still in search of a compelling title & subtitle

We begin this particular piece of our adventure into functional programming with some WCF code unification.  This same technique can be used with other constructs including database connections and anything that has a setup/tear down template.  I have a small set of example code using WCF which I’ll be using as an example.  The specifics of the WCF calls, syntax, and general discussion is outside of the scope of this particular post; however, there are many good references on MSDN and in other’s blogs.  The projects for this example (which will be available at the end of the series) were written with VS2010 Beta 2, the server WCF piece requires .NET 4, but the functional client bits are all 3.5 compatible.  Without further ado, let’s start in the example code.

   1: private static string GetGreeting(int theID)
   2:  {
   3:      IGreeting aGreetingService = null;
   4:      string aGreeting = null;
   5:      try
   6:      {
   7:          aGreetingService = GetGreetingChannel();
   8:          aGreeting = aGreetingService.Greet(theID);
   9:      }
  10:      finally
  11:      {
  12:          CloseWCFChannel((IChannel)aGreetingService);
  13:      }
  14:      return aGreeting;
  15:  }
  16:  private static int AddName(string theName)
  17:  {
  18:      IGreeting aGreetingService = null;
  19:      int aID = -1;
  20:      try
  21:      {
  22:          aGreetingService = GetGreetingChannel();
  23:          aID = aGreetingService.AddName(theName);
  24:      }
  25:      finally
  26:      {
  27:          CloseWCFChannel((IChannel)aGreetingService);
  28:      }
  29:  
  30:      return aID;
  31:  }
  32:  private static void CloseWCFChannel(IChannel theWCFChannel)
  33:  {
  34:      if (theWCFChannel != null)
  35:      {
  36:          try
  37:          {
  38:              theWCFChannel.Close();
  39:          }
  40:          catch (Exception ex)
  41:          {
  42:              theWCFChannel.Abort();
  43:              Console.WriteLine(ex.ToString());
  44:          }
  45:      }
  46:  }

The two methods of interest are GetGreeting and AddName.  CloseWCFChannel is a helper method to ensure our communication channel gets closed reliably.  [Now, whether or not closing the channel after each call is the appropriate pattern is outside the scope of this discussion, but it is inspired by an actual piece of code at work.]  Notice that the GetGreeting and AddName methods are almost identical.

Since it is considered good practice for one’s codebase to have no duplication (see DRY) let’s see how we can stamp out this duplication. Doing some compare & contrast on the methods shows that the methods vary by parameter & return type and what service method they call.  These are somewhat significant differences but ones we can address.  The both methods do the following:

  • Define an IGreeting variable
  • Set an initial return value
  • Open a try block
  • Call GetGreetingChannel()
  • Call the service and set the return value
  • Close the try block
  • Open the finally block
  • Close the WCF channel
  • Return their value

A first pass at this gives us a method that might look like this:

   1: private static ? name(? parameter, ? initialValue)
   2: {
   3:     IGreeting aGreetingService = null;
   4:     ? aReturnVariable = initialValue;
   5:     try
   6:     {
   7:         aGreetingService = GetGreetingChannel();
   8:         aReturnVariable = aGreetingService.DoSomething(parameter);
   9:     }
  10:     finally
  11:     {
  12:         CloseWCFChannel((IChannel)aGreetingService);
  13:     }
  14:  
  15:     return aReturnVariable;
  16: }

 

With the ? standing in for types it is straightforward to convert those to generic parameters to address the difference in parameter and result types:

   1: private static TResult name<T, TResult>(T parameter, TResult initialValue)
   2: {
   3:     IGreeting aGreetingService = null;
   4:     TResult aReturnVariable = initialValue;
   5:     try
   6:     {
   7:         aGreetingService = GetGreetingChannel();
   8:         aReturnVariable = aGreetingService.DoSomething(parameter);
   9:     }
  10:     finally
  11:     {
  12:         CloseWCFChannel((IChannel)aGreetingService);
  13:     }
  14:  
  15:     return aReturnVariable;
  16: }

 

 

That looks awfully close to being the GetGreeting and AddName method definitions with generic parameters.  The big question is what to do with line 8, the DoSomething call, the last difference between the methods.  What I really want to be able to do conceptually is inject different code into line 8.  One possibility would be to define a delegate and pass that in as a parameter and call it.  If we did that, it should be a generic delegate because we want to allow different parameter and return types.  Lucky for us we can skip that bit of work and use the built in generic delegate Func<T, TResult> which matches the DoSomething signature in line 8 perfectly. Causing an abridged version to look a little something like this:

   1: private static TResult name<T, TResult>(T parameter, Func<T,TResult> DoSomething)
   2: ...
   3: aReturnVariable = DoSomething(parameter);

Except, this really doesn’t help us with making a call to the IGreeting service because we would still need a populated IGreeting to make the delegate call work.  Since we have an IGreeting already populated in our method we can pass that into our DoSomething delegate as a parameter allowing us to make a call to IGreeting with a populated object and giving us a Func<IGreeting, T, TResult> DoSomething parameter.

   1: private static TResult name<T, TResult>(T parameter, Func<IGreeting,T,TResult> DoSomething)
   2: ...
   3: aReturnVariable = DoSomething(aGreetingService, parameter);

With the finished method looking like:

   1: private static TResult ExecuteGreetingServiceMethod<T, TResult>(T parameter, 
   2:     TResult initialValue, Func<IGreeting,T,TResult> DoSomething)
   3: {
   4:     IGreeting aGreetingService = null;
   5:     TResult aReturnVariable = initialValue;
   6:     try
   7:     {
   8:         aGreetingService = GetGreetingChannel();
   9:         aReturnVariable = DoSomething(aGreetingService, parameter);
  10:     }
  11:     finally
  12:     {
  13:         CloseWCFChannel((IChannel)aGreetingService);
  14:     }
  15:  
  16:     return aReturnVariable;
  17: }

 

 

 

That’s all well and good, but not terribly interesting – until we look at how to call this new method.  Let’s first convert the GetGreeting method, all the previous tedious setup/tear down code goes away and can be reduced to a single line (that the blog formatting won’t allow as one):

   1: private static string GetGreeting(int theID)
   2: {
   3:     return ExecuteGreetingServiceMethod<int, string>(theID, null, 
   4:    (theGreetingService, parameter) => theGreetingService.Greet(parameter));
   5: }

 

We can call the ExecuteGreetingServiceMethod with a lambda expression (MSDN has excellent documentation on the lambda syntax and associated rules), with type inference there is no need to specify the type of theGreetingService or parameter.  We get the benefit of a concise way of passing in exactly the code we want to execute without worrying about getting the setup & tear-down code right and in every spot we need to make a call to the service, and a more readable statement of what this method intends without the additional code.

Keen eyed readers may be wondering why the parameter is still being passed to the ExecuteGreetingServiceMethod, and the answer is … there’s no good reason other than to show it as a step in the process, it is entirely appropriate to remove the parameter from the method signatures giving us:

   1: private static TResult ExecuteGreetingServiceMethod<TResult>
   2:     (Func<IGreeting,TResult> DoSomething)
and
   1: private static string GetGreeting(int theID)
   2: {
   3:      return ExecuteGreetingServiceMethod<string>(theID, null, 
   4:     (theGreetingService) => theGreetingService.Greet(theID));
   5: }

 

And that wraps up the code for this piece of the adventure.  So, what have really gained?  A concise way to express what we’re doing in the GetGreeting and AddName methods, eliminated duplication between the methods, and reduced the chances for bugs because the setup & tear-down code weren’t implemented or implemented correctly. 

Where are the functional aspects, you ask?  Well, the passing of functions as code comes from FP, so does allowing the parameter in the GetGreeting method to be used by the lambda expression which is known as a closure (which we’ll talk more about in another part).  As was mentioned in the introduction to this series, functional programming is complementary to your existing tools requiring only an incremental step forward to start using it in your code to eliminate duplication, reduce bugs, and express intent.

Next up, the adapter pattern for methods, delayed execution, and some more code passing.

Posted on Wednesday, January 20, 2010 7:40 PM | Back to top


Comments on this post: Reducing Duplication By Passing Code

# re: Reducing Duplication By Passing Code
Requesting Gravatar...
Say you have AddName(firstName, lastName) instead. What would be the best way eliminate the duplication if the service methods have different number of parameters?
Left by Jan Magne Tjensvold on Jan 21, 2010 1:05 PM

# re: Reducing Duplication By Passing Code
Requesting Gravatar...
Jan, it depends, my next post will cover reducing parameters to make this example a little broader (along with some other general uses). Basically if you have all the parameters at the time you call your ExecuteServiceMethod you only need to take in a Func<IService, TResult>. In the post's example you could do the following:
private static int AddName(string firstName, string lastName){
return ExecuteGreetingServiceMethod<int>(theID, null,(theGreetingService) => theGreetingService.AddName(firstName, lastName));
}

Passing in the first & last name directly through to the lambda expression. Taking this approach it really doesn't matter how many parameters your service call requires because you'll always be passing in a Func<IService, TResult> to your execute method.
Left by Charles Courchaine on Jan 22, 2010 11:10 PM

# re: Reducing Duplication By Passing Code
Requesting Gravatar...
Strikes me as a much better way to do a strategy pattern without all the OO overkill.
Left by Gustavo Keener on Jan 27, 2010 5:00 PM

Comments have been closed on this topic.
Copyright © Charles Courchaine | Powered by: GeeksWithBlogs.net