Let's say you need to find the maximum number in a bunch of places, so you write a max method:
public static float Max(float a, float b) {
if (a < b) {
float t = a;
a = b;
b = t;
}
return a;
}
That might not be the simplest implementation ever, but sometimes the simplest thing is the second one that occurs to you, not the first. Also, that implementation makes the next examples work!
Then you need the minimum number in a bunch of places, so you extend your max method:
public static float Extreme(float a, float b, bool min = false) {
if (a > b) {
float t = a;
a = b;
b = t;
}
return min ? a : b;
}
That seems pretty sensible, until you compare it with the usability of the standard Min and Max methods.
Technically, Min, Max, and Extreme all take parameters, but the last parameter to Extreme is subtly different.
It's harder to use than separate methods because you have to think about more concepts when calling it, and it's harder to maintain because you have to think about more at once in order to modify it.
When you have these sort of switching parameters, a better choice is to make separate methods and pull out code they both need into private methods.
Here is example code demonstrating that. Obviously, the code in this example is worse because C# is too clumsy for composition on a problem this trivial. Fortunately, real world situations are complex enough that better code can result.
private struct Pair {
public float a;
public float b;
}
private static Pair Swap(Pair p) {
float t = p.a;
p.a = p.b;
p.b = t;
return p;
}
public static float Min(float a, float b) {
Pair p = new Pair {
a = a,
b = b,
};
if (a > b) {
p = Swap(p);
}
return p.a;
}
public static float Max(float a, float b) {
Pair p = new Pair {
a = a,
b = b,
};
if (a < b) {
p = Swap(p);
}
return p.a;
}
Ok, I can see the potential here for easier to call methods. My understanding is that shifting priorities from concise code to easy to use code is the main take away here. Would that be accurate?