Using delegates to eliminate duplicate code

Here’s a simple technique you can use to easily eliminate duplicate code. Try not to let the word “delegates” scare you away from learning the technique and I’ll try to refrain from using the word “delegate” as much as possible.  I’ll start small and then work my way towards a more complex example that really demonstrates its power.

Before I go any further, I’d like to point out that my post about Using IDisposable objects responsibly contains a more extravagant example of how this technique is useful. This post goes further to explain HOW we use the technique.

A simple example

Let’s look at two overly simplistic methods that do different things with a connection object. Whereas the yellow code is identical across the two method, the blue and green code illustrates the differences between the two methods.

image

There may not be much duplicate code here, but that’s not important right now. When thinking about how we can make this code better, consider these things:

  • What if we decide one day to use try/catch statements instead of using statements? Doing so would allow us to catch and process specific exception types.
  • What if the code required to create the connection changes one day?
  • What if there were dozens of places throughout our application where this type of code is used?!?!?!?!

In order to make any of those changes, you’ve got to touch the code in every single place where the pattern exist. That’s the problem we want to fix. We want to be able to make those change, or any other changes, in one place, and have it affect the entire application.

Looking the blue and green code above, you can see that the only dependency those methods have is in the connection object. If you think about it, the blue and green methods don’t care where the connection object comes from or what happens to it afterwards – they just need a connection object. Our code would be much better if we could prevent from showing how the connection object is created or disposed.

So let’s change our two methods to see how we can better accommodate change in our application.

image

image

I can just hear my boss complaining about that strange => syntax, but bare with me. :) For the most part, this new code looks the same as our original code. Look back at the first code example to verify the differences between the two. As you’ll soon see, they definitely do the same thing, while, at the same time, providing a great deal more flexibility.

Creating the UsingConnection method

Here’s a different example that, whether you realize it now or not, illustrates the concept. Look at it closely, and then look at the CallIndirectly method even closer. If you can grasp this, the rest is relatively easy.

image

Here’s the same thing with a bit of color coding to try and help illustrate what’s happening:

image

Hopefully, you’ve determined that this should be the output of such a program:

image

In the example above, CallIndirectly takes a method (Action) as a parameter and stores that parameter in a variable called methodToCall. Just as we write WriteHelloWorld() to execute WriteHelloWorld, we write methodToCall() when we want to call the method that was passed to CallIndirectly. You can immediate see from the output of the program that using CallIndirectly provides us with an opportunity to do things both “Before” and “After” our desired method gets called. Essentially, CallIndirectily is a method that calls another method. The trick is, we have to pass a method as a parameter to CallIndirectly so it will know which method to call.

Again, if you can grasp that much, the rest is pretty simple.

UsingConnection is pretty much the exact same thing as Callindirectly. If we wanted to, we could use UsingConnection in the exact same way that we used CallIndirectly above! Here’s proof:

image

And again with the color coding (let me know if it helps – I’m curious).

image

What’s that Action stuff?

Notice how the method signatures for DoSomething and DoMoreStuff are identical with the exception of their names.

image

For our UsingConnection method to work, the first thing we need to do is figure out a way to generalize those signatures.  In other words, we need a way of defining a method signature that could have any name (or even no name, as we’ll eventually see), and that takes a single OleDbConnection parameter. We can represent that last statement with Action<OleDbConnection>. You can pretend “Action” represents the name of the method and OleDbConnection represents the first parameter. If our methods took three parameters – An OleDbConnection, OleDbCommand, and an OleDbDataReader, for example, we could represent the method by using Action<OleDbConnection, OleDbCommand, OleDbDataReader>.

I find the easiest way to do this is to imagine placing the words DoSomething and DoMoreStuff with the word Action. What’ you’d then have is:

image

While that’s close to the desired result, there’s still a bit more we have to do. It turns out, the name of our OleDbConnection parameter isn’t important either, so let’s get rid of that:

image

Also, the void return type isn’t important to us…

image

Finally, to really use the Action keyword , we have to replace the ( and ) with < and >.  The end result looks like this:

image

Because UsingConnection takes a parameter of type Action<OleDbConnection>, that tells us we can pass any method to UsingConnection, so long as it takes a single parameter of type OleDbConnection. In other words, just as void DoSomething(OleDbConnection connection) tells us that we can pass an OleDbConnection object to DoSomething, we can see that void UsingConnection(Action<OleDbConnection> action) tells us that we can pass any action (read: method) to UsingConnection so long as the method we’re passing accepts an OleDbConnection parameter.

What about that pesky lambda syntax?

The Test1 and Test2 methods below do the exact same thing, yet it’s apparent that Test2 uses a syntax that isn’t exactly intuitive at first.

image

To understand that => syntax, let’s expand on our understanding of Action. As you should recall, the Action<OleDbConnection> parameter tells us that we can pass any method to UsingConnection so long as it accepts an OleDbConnection parameter. Okay, so let’s copy/paste the entire contents of our DoSomething method into our call to UsingConnection and see what happens.

image

Well, that’s basically what we want to do, but it’s obvious that code isn’t going to compile. To make it compile, we only have to make TWO changes.

Remember, Action<OleDbConnection> means that the name of the method and its return type do not matter. So the first thing we can do is remove the void DoSomething part.

image

The ONLY other thing we have to do now is separate the parameters from the method body with the two characters =>.

image

That’s technically it. The code above compiles and works fine, but there are a couple of things we can do to clean the code up a bit. The main thing is that we don’t have to explicitly declare the type of our connection object. Let’s get rid of that declaration and tidy things up.

image

Look how clean that is!

Just to make sure you understand how to make use of this technique, here’s a more concrete example of using the connection:

image

Conclusion

Again,  you’ll probably want to look at my last post on Using IDisposable objects responsibly to get a better understanding of why we want to use this technique in the first place.

I’ve been on a mission lately to eliminate duplicate code, so there’s a good chance my next two or three posts will be on the same subject.

  • http://Website Rosdi

    Excellent explanation!.. I have heard of delegates for quite some time but never seems to grasp what it is.. your explanation makes it clear.

  • Pingback: Using IDisposable objects responsibly – the easy way | AlexDresko.com()

  • http://Website nursing schools

    nice post. thanks.

  • http://www.csharpbydesign.com Matthew M.

    Great article. While I knew everything here — I had not quite thought of it in such a “global” setting. After reading this I realized that I had many such calls like:

    try {
    using(DataContext dc …) {
    // Do Stuff
    }
    } catch (SqlException sqlEx) {
    AutomaticHandlerManager(sqlEx);
    // Optional
    //return false; e.Cancel = true; etc.
    }

    It hadn’t occurred to me that that’s a lot of duplicate code floating around, everywhere. So I refactored a few hundred files into:

    MyDataContext.Execute(dc => doStuff(dc));
    or
    if (!MyDataContext.Execute(dc => {
    var results = dc.spDoSomething().ToList();
    })) {
    return false;
    }

    Sweet! Thanks for the idea. :)

    – Matthew

  • http://Website Mark Northup

    Excellent article. This really helped me get comfortable using delegates. I saw this when you first posted, but am only now getting around to commenting on it.

    Wouldn’t your ADO.NET methods be improved by using IDbConnection in place of OleDbConnection?

    See you at GSP Developers Guild.

    I really enjoyed your presentation on the same topic as well.

  • David

    I always read the => operator as “such that”… makes it easier to understand.