7

I have three C# methods that almost perform identically. More specifically there is a large amount of code repetition but at the end, they perform different functions.

This is obviously very inefficient, so what's the best way to cut down on code duplication? Should I place it all in one method and use a switch & enum for the different functionality at the end? Alternatively, is there some kind of way you can have 3 separate classes and inherit the shared bit from another? I've done a fair bit of reading about this and from what I can gather, this is only used to gain properties from a whole different class.

pb2q
  • 58,613
  • 19
  • 146
  • 147
Jonathan
  • 13,947
  • 17
  • 94
  • 123
  • 1
    (I substituted "reuse" => "duplication", as it seemed to fit your meaning more clearly) – Marc Gravell Dec 03 '10 at 09:15
  • "Should I place it all in one method and use a switch & enum for the different functionality at the end?" Please don't do this! – SingleNegationElimination Dec 03 '10 at 09:17
  • You will not get a useful answer to this question, try posting a quesion that contains the code to the 3 methods, then people may be able to help you. There is no one solution to refactoring code. – Ian Ringrose Dec 03 '10 at 09:23
  • Thank you Marc. TokenMacGuy, can you provide a little more detail as why this is wrong? I previously used to have an int parameter to set 'modes' in methods but I was advised in an article to be using an enum instead. – Jonathan Dec 03 '10 at 09:23

9 Answers9

5

Without seeing the code its hard to give a concrete example, but it sounds like you want to pass a delegate instance into the method.

Steven Keith
  • 1,789
  • 15
  • 23
  • Thanks Steven, turns out that's exactly what I was looking for. Apologies that I didn't provide a code example, I'll be sure to next time. – Jonathan Dec 03 '10 at 14:18
4

From my point of view you should sit down with a piece of paper and a pen. Draw out every piece of functionality your methods perform. Remember that a function/method should do one and only one thing.

After you brake down every piece of functionality you will start to see things that are repeated, these should be grouped together in one function.

Luca Matteis
  • 29,161
  • 19
  • 114
  • 169
  • 1
    +1 for mentionning the Single Responsibility Principle: Classes and Functions should do few things, but do them well. http://en.wikipedia.org/wiki/Single_responsibility_principle – Stephane Rolland Dec 03 '10 at 10:12
4

I have three C# methods that largely do identical things. There is much code repetition but at the end, they both perform different functions.

by reading this line , i am thinking your three methods are having different implementation based upon some different scenarios.

so i would suggest to see Stratgey Pattern once which may be of useful. See here

TalentTuner
  • 17,262
  • 5
  • 38
  • 63
3

It's a good sign that it bugs you.

This is obviously very inefficient

The inefficiency (a little extra memory usage) is the least important part these days. What's crucuial is that it's a maintainence nightmare. For instance, if you find a bug in the routine and fix it, you need to remember to fix the duplicate code, too. You definitely want to factor out duplicate code when you can.

Alternatively, is there some kind of way you can have 3 separate classes and inherit the shared bit from another? I've done a fair bit of reading about this and from what I can gather, this is only used to gain properties from a whole different class.

A subclass can directly access all public and protected members of it's superclass. For instance, if you had an Animal class with a Poop() method, Dog and Cat subclasses could share that pooping code.

But there are a lot of ways of skinning this cat. Hard to say what's best without more detail.

Mud
  • 28,277
  • 11
  • 59
  • 92
2

Can you do something like the following :

    public void MethodBase()
    {
        Console.WriteLine("1");
        Console.WriteLine("2");
        Console.WriteLine("3");
        Console.WriteLine("4");
        Console.WriteLine("5");
    }

    public void Method1()
    {
        MethodBase();
        Console.WriteLine("Method 1");
    }

    public void Method2()
    {
        MethodBase();
        Console.WriteLine("Method 2");
    }

    public void Method3()
    {
        MethodBase();
        Console.WriteLine("Method 3");
    }
decyclone
  • 30,394
  • 6
  • 63
  • 80
  • Thank you decyclone. I forgot to mention that the MethodBase() is setting a number of variables, all of which need to be accessed from Method1, Method2 and Method3. Does this mean I need to use a delegate instance as Steven has advised? – Jonathan Dec 03 '10 at 09:25
  • I think, yes you should. – decyclone Dec 03 '10 at 09:30
2

There is no solution that would work in all cases, show us the code.

The problem is that when you put the code into one function and switch a little part of the behaviour somewhere inside, you raise the code complexity, and sometimes it’s better to keep some duplicated code than that.

Almost the same argument works for inheritance. You can easily stuff the common code into a common ancestor class, but if you start routinely use inheritance as a code-reuse tool, your design may slip into a world of pain. Inheritance means that code in one piece of code can affect behaviour in other pieces of code and before you know it, you will have an interlinked ball of code that’s almost impossible to change without breaking.

It’s usually best when you can extract or abstract some meaningful common part of the code from those three functions. Something that makes sense, like a high-level pattern, instead of just a few common lines that do no coherent work. A simple rule that may help you is naming the extracted code: Is there an obvious, natural way to name the chunk? Does it obviously fit into one of your classes? If it does, it might be a good solution. If you have hard time naming it and it could go pretty much anywhere, you might want to think a bit more.

zoul
  • 102,279
  • 44
  • 260
  • 354
2

You can try to generalize the method by making it a higher-order or a generic function. Other approaches that comes to mind are design patterns like Template method which lets you define the skeleton of the algorithm, and let subclasses redefine certain steps.

Nömmik
  • 494
  • 4
  • 11
1
public MyCustomObject MethodBase(MyCustomObject myObj) 
{ 
    myObj.Name="FixedName";
    myObj.Surname="FixedSurname";
    myObj.Type = Types.Human;
    return myObj;
} 


public MyCustomObject SetOld(MyCustomObject  myObj) 
{ 
    MethodBase(); 
    myObj.IsOld = True;
    return myObj;
} 

public MyCustomObject SetYoung(MyCustomObject myObj) 
{ 
    MethodBase(); 
    myObj.IsOld = False;
    return myObj;
} 

public MyCustomObject SetIsDead(MyCustomObject myObj) 
{ 
    MethodBase(); 
    myObj.IsDead = True;
    return myObj;
} 
public void MainMethod(enum OperationType)
{
    MyCustomObject myObj = new MyCustomObject();
    switch(OperationType)
    {
        case OperationTypes.Old:
            myObj = SetOld(myObj);
            break;
        case OperationTypes.Young:
            myObj = SetYoung(myObj);
            break;
        case OperationTypes.Dead:
            myObj = SetDead(myObj);
            break;
    }
}
Pabuc
  • 5,528
  • 7
  • 37
  • 52
0

Nobody mentioned lambda-functions, they are must to know for .NET 3.5 developers:

public MyCustomObject SetYoung(MyCustomObject myObj) 
{ 
    GeneralMethod(myObj => myObj.IsOld = False);
    return myObj;
} 

public void GeneralMethod(Func<TSourceObjectType,TResultObjectType> func)
{
    MyCustomObject myObj = new MyCustomObject(); // MyCustomObject implements 'TSourceObjectType'
    TResultObjectType res = func(myObj);
}
Budda
  • 18,015
  • 33
  • 124
  • 206