views:

83

answers:

4

Hi there,

I have a piece of code where in there are 2 overloads which differ by data types of parameter and have different number of parameters as well. I am looking to reduce the code duplication. What are the possible ways I can do this?

My code looks like this:

    public void publicMethod(double[,] data, double increment)
    {
        helperMethod1(data, increment);
    }

    public void publicMethod(double[,] data, TimeSpan increment, Enum someEnum)
    {
        helperMethod2(data, increment, someEnum);
    }

    //The helper methods are in a different class
    internal void helperMethod1(double[,] data, double increment)
    {
        //Some 20 lines of common code

        for (int i = 0; i < data.GetLength(0); ++i)
        {
            TargetFunction((double[])GetRow(i, data), increment);
        }

        //Some more common code
    }

    internal void helperMethod1(double[,] data, TimeSpan increment, Enum someEnum)
    {
        //Some 20 lines of common code

        for (int i = 0; i < data.GetLength(0); ++i)
        {
            TargetFunction((double[])GetRow(i, data), increment, someEnum);
        }

        //Some more common code
    }

    public static double[] GetRow(int rowIndex, double[,] array)
    {
        double[] row = new double[array.GetLength(1)];
        Buffer.BlockCopy(array, array.GetLength(1) * rowIndex * 8, row, 0, array.GetLength(1) * 8);
        return row;
    }

UPDATE:

OK. It looks like I am not explaining my code well enough. I will paste the exact code I have so that you guys get a better picture:

    public class PublicClass
    {
        public void PlotXAppendMultiple(double[,] xData, DataOrientation orientation, TimeSpan increment, PrecisionMode precisionMode)
        {
            HelperClass.PlotXAppendMultiple(xData, orientation, increment, precisionMode);
        }

        public void PlotXAppendMultiple(double[,] xData, DataOrientation orientation, double increment)
        {
            HelperClass.PlotXAppendMultiple(xData, orientation, increment);
        }
    }

    internal class HelperClass
    {
        public virtual void PlotXAppendMultiple(double[,] xData, DataOrientation orientation, double increment)
        {
            switch (orientation)
            {
                case (DataOrientation.DataInRows):
                    {
                        for (int i = 0; i < xData.GetLength(0); ++i)
                        {
                            TargetFunction((double[])GetRow(i, xData), increment);
                        }
                        break;
                    }
                case (DataOrientation.DataInColumns):
                    {
                        for (int i = 0; i < xData.GetLength(1); ++i)
                        {
                            TargetFunction((double[])GetColumn(i, xData), increment);
                        }
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }

        public virtual void PlotXAppendMultiple(double[,] xData, DataOrientation orientation, TimeSpan increment, PrecisionMode precisionMode )
        {
            switch (orientation)
            {
                case (DataOrientation.DataInRows):
                    {
                        for (int i = 0; i < xData.GetLength(0); ++i)
                        {
                            TargetFunction((double[])GetRow(i, xData), increment, precisionMode);
                        }
                        break;
                    }
                case (DataOrientation.DataInColumns):
                    {
                        for (int i = 0; i < xData.GetLength(1); ++i)
                        {
                            TargetFunction((double[])GetColumn(i, xData), increment, precisionMode);
                        }
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }
    }

I dont want to modify the enums I am using (so basically I want to add dummy entries to it). Is it even possible/worth refactoring this code?

+4  A: 

How about replacing //Some 20 lines of common code with call to TwentyLinesOfCommonCode() and //Some more common code with SomeMoreCommonCode() in both Methods? You would keep only the non-common code.

EricSchaefer
Yep. Sometimes you just need to see *what* to refactor.
Christian Hayter
Yes, this could have been done if the common code was a simple one. But in my case, the common codes contain lots of If-Else and switch cases which makes it impossible to move it to a different method.
Niranjan
So it is only "somewhat common"?
EricSchaefer
A: 

Hi,

I'd create a TimeSpan object from the decimal parameter and provide this new TimeSpan object with a 'default' Enum value on to the method taking 3 parameters.

HTH robert.oh.

robert.oh.
A: 

Have an entry "NotSet" or "Unknow" in your Enum. TargetFunction2 must be aware of it and adapt it's behavior. Keep only the helperMethod1 with the 3 args signature and adapt first method like this

public void publicMethod(double[,] data, double increment)
    {
        helperMethod1(data, increment, Enum.Unknow);
    }
Fabian Vilers
A: 

Is it possible to create a convertor that converts TimeSpan and Enum into the Double parameter, or vice versa?

If yes, then you can define such a helper method first

public double Convertor(TimeSpan ts, Enum enum)
{
}

and then write the following code:

  //The helper methods are in a different class
    internal void helperMethod1(double[,] data, double increment)
    {
        //Some 20 lines of common code

        for (int i = 0; i < data.GetLength(0); ++i)
        {
            TargetFunction1(data, increment);
        }

        //Some more common code
    }

    internal void helperMethod1(double[,] data, TimeSpan increment, Enum someEnum)
    {
        helperMethod1(data, Convertor(increment, someEnum);
    }
Ngu Soon Hui