Search code examples
c#methodsrefactoringdry

How to refactoring similar but not identical methods where one method extends the functionality of the other? C#


I have two methods which are very similar apart form the fact that the second method partially extends the functionality of the first method. For example the methods are below:

private void ExtendTable(FileInfo file, string columnToCopy, string columnNewName) 
{
    var data = File.ReadAllLines(file.FullName).ToArray();
    if (data[1].Contains(columnToCopy)) 
    {
       var content = data[0] + Environment.NewLine + data[1] + columnNewName + Environment.NewLine + data[2];
    }
}

private void ExtendTable(FileInfo file, string columnToCopy, string columnNewName, string secondColumnToCopy, string secondColumnNewName) 
    {
        var data = File.ReadAllLines(file.FullName).ToArray();
        if (data[1].Contains(columnToCopy) && data[1].Contains(secondColumnToCopy)) 
        {
           var content = data[0] + Environment.NewLine + data[1] + columnNewName + secondColumnNewName + Environment.NewLine + data[2];
        }
    }

As can be seen the second method slightly extends the functionality of the first. I plan on adding functionality which will print this back into a file, however my question is that this is quite repetitive and breaks DRY principle. How can I refactor these methods so there is less duplication while still ensuring they both work as intended.

Thanks


Solution

  • As has been suggested you could use optional arguments to combine your method. Another option might be to refactor the parameters into a class then pass an IEnumerable of that class to ExtendTable. This allows you to provide any number of columnToCopy and columnNewName to the method without having to modify it.

    This snippet is untested, but it might look something like this...

    public static void ExtendTable(string[] data, IEnumerable<ExtendTableData> extendData)
    {
        if (extendData.Any() && extendData.All(ed => data[1].Contains(ed.ColumnToCopy)))
        {
            var content = data[0] + Environment.NewLine + data[1] + string.Join("" , extendData.Select(ed => ed.ColumnNewName)) + Environment.NewLine + data[2];
        }
    }
    
    public class ExtendTableData
    {
        public string ColumnToCopy { get; set; }
        public string ColumnNewName { get; set; }
    }
    

    Or if you don't want to create a class and the version of .NET you're using supports it you could just use an IEnumerable of ValueTuple<string, string>...

    public static void ExtendTable(string[] data, IEnumerable<(string ColumnToCopy, string ColumnNewName)> extendData)
    {
        if (extendData.Any() && extendData.All(ed => data[1].Contains(ed.ColumnToCopy)))
        {
            var content = data[0] + Environment.NewLine + data[1] + string.Join("" , extendData.Select(ed => ed.ColumnNewName)) + Environment.NewLine + data[2];
        }
    }