tags:

views:

37

answers:

2

Hello,
I just asked a question that helps about using generics (or polymorphism) to avoid duplication of code. I am really trying to follow the DRY principle.

So I just ran into the following code...

Sub OutputDataToExcel()

        OutputLine("Output DataBlocks", 1)
        OutputDataBlocks()
        OutputLine("")

        OutputLine("Output Numbered Inventory", 1)
        OutputNumberedInventory()
        OutputLine("")

        OutputLine("Output Item Summaries", 1)
        OutputItemSummaries()
        OutputLine("")

End Sub

Should I rewrite this code to be as follows using the Action delegate...

Sub OutputDataToExcel()
    OutputData("Output DataBlocks", New Action(AddressOf OutputDataBlocks))
    OutputData("Output Numbered Inventory", New Action(AddressOf OutputNumberedInventory))
    OutputData("Output Item Summaries", New Action(AddressOf OutputItemSummaries))
End Sub

Sub OutputData(ByVal outputDescription As String, ByVal outputType As Action)
    OutputLine(outputDescription, 1)
    outputType()
    OutputLine("")
End Sub

I realize this question is subjective. I am just wondering about how religiously you follow DRY. Would you do this?

Seth

A: 

I wouldn't say I use it all the time, but I have used Action delegate to avoid code duplication. One scenario where I have used it is to wrap WCF calls (inside a client proxy) to avoid the same boiler plate code.

   private void InvokeAndHandleFaults(
        Action<Data, Context> wcfCall,
        Data data,
        Context context)
    {
        bool isSuccess = false;

        try
        {
            wcfCall(data, context);

            if (this.ChannelFactory.State != System.ServiceModel.CommunicationState.Faulted)
            {
                this.ChannelFactory.Close();
            }

            isSuccess = true;
        }
        catch (FaultException ex)
        {
            HandleFault(ex);
        }
        finally
        {
            if (!isSuccess)
            {
                this.ChannelFactory.Abort();
            }
        }
    }

In terms of the example in the question, I would probably not use an Action. I would definitely not refactor to use an Action. Mainly because the actual logic is quite simple so I don't see much benefit. As the "complexity"/size of the repeated code increased I would be more likely to use a delegate.

Tuzo
+2  A: 

I've seen this called the "Hole in the middle" pattern. The "Real World Functional Programming" book mentions it. Here's a link.

http://enfranchisedmind.com/blog/posts/the-hole-in-the-middle-pattern/

See, there’s a pattern I’ve gotten used to in Ocaml- and I’d even used it in Perl, which I think of as the “hole in the middle” pattern. The basic idea is that you have two pieces of code that are almost exactly identical, except for that little middle part there. The idea is that you factor out the common code into a single function, which takes a function pointer as an argument. The middle part in the shared code is replaced by a call to the function pointer, and the two places which are being combined simply call the combined function with a pointer to a function that contains the unique part.

mwilson
Hole in the middle pattern? Could it also be called the donut pattern? mmmmm...donuts.
Tuzo