Optional parameters are a great tool for building flexible APIs. In most languages, they're not strictly necessary- if you have function overloading, the difference between optional parameters and an overloaded function is just the quantity of boilerplate- but they're certainly a nice to have.
Well, they're a nice to have in the right hands.
Scattered through their code base, Ian P saw many, many calls to dutData.GetMessages()
. As they explored the code base, they used Visual Studio's "go to definition" feature to jump to the implementation- and found they were sometimes ending up in different spots.
public static IEnumerable<string> GetMessages(this ScreenScraper screenScraper)
{
//Do some stuff to get the messages
}
//snip 100+ lines
public static IEnumerable<string> GetMessages(this ScreenScraper screenScraper, long timeSpane = 30000, int timeInterval = 500)
{
//Do some different stuff to get the messages
}
Frankly, I'm a little surprised that this is even possible. It offered warnings, but no errors, presumably because this is an odd bit of syntactic sugar in C# called "extension methods", which are C#'s answer to "monkey patching". Neither GetMessages
is actually a member of ScreenScraper
, but if you call GetMessages
on a ScreenScraper
object, C# will call GetMessages
and pass an instance of ScreenScraper
into it.
The C# compiler is the real WTF. As for Ian, the fix was simple: rename some methods for clarity, and convert extensions to instance methods as appropriate.