Adding complexity to remove duplicate code
- by Phil
I have several classes that all inherit from a generic base class. The base class contains a collection of several objects of type T.
Each child class needs to be able to calculate interpolated values from the collection of objects, but since the child classes use different types, the calculation varies a tiny bit from class to class.
So far I have copy/pasted my code from class to class and made minor modifications to each. But now I am trying to remove the duplicated code and replace it with one generic interpolation method in my base class. However that is proving to be very difficult, and all the solutions I have thought of seem way too complex.
I am starting to think the DRY principle does not apply as much in this kind of situation, but that sounds like blasphemy. How much complexity is too much when trying to remove code duplication?
EDIT:
The best solution I can come up with goes something like this:
Base Class:
protected T GetInterpolated(int frame)
{
var index = SortedFrames.BinarySearch(frame);
if (index >= 0)
return Data[index];
index = ~index;
if (index == 0)
return Data[index];
if (index >= Data.Count)
return Data[Data.Count - 1];
return GetInterpolatedItem(frame, Data[index - 1], Data[index]);
}
protected abstract T GetInterpolatedItem(int frame, T lower, T upper);
Child class A:
public IGpsCoordinate GetInterpolatedCoord(int frame)
{
ReadData();
return GetInterpolated(frame);
}
protected override IGpsCoordinate GetInterpolatedItem(int frame, IGpsCoordinate lower, IGpsCoordinate upper)
{
double ratio = GetInterpolationRatio(frame, lower.Frame, upper.Frame);
var x = GetInterpolatedValue(lower.X, upper.X, ratio);
var y = GetInterpolatedValue(lower.Y, upper.Y, ratio);
var z = GetInterpolatedValue(lower.Z, upper.Z, ratio);
return new GpsCoordinate(frame, x, y, z);
}
Child class B:
public double GetMph(int frame)
{
ReadData();
return GetInterpolated(frame).MilesPerHour;
}
protected override ISpeed GetInterpolatedItem(int frame, ISpeed lower, ISpeed upper)
{
var ratio = GetInterpolationRatio(frame, lower.Frame, upper.Frame);
var mph = GetInterpolatedValue(lower.MilesPerHour, upper.MilesPerHour, ratio);
return new Speed(frame, mph);
}