I'm working on some code that ended up having some moderately complex helper methods. I don't want to expose these methods on the public API because I want to keep my class's public face as simple as possible. Something I heard Scott Meyers talk about some years back at Software Development Expo has always stuck in my head: “Make your code hard to use incorrectly.”
That’s always in my head as I’m deciding what bits and pieces of functionality should be exposed. Helper methods are generally internal bits, not something your class’s consumers should have to worry about, so why should you then expose them on the public side of an API?
Easy. You shouldn’t.
The issue is how do you create those helper methods when you're doing Test Driven Development? My first approach was that I just had to figure out all the test cases to drive execution through the various paths of the public function plus its helper function. That got too complex, but I really didn't want to change that helper to public visibility in order to test it directly.
A few moments with my Thinking Cap on and I came up with this solution: Use the preprocessor and the DEBUG constant. This lets me have the helper method's signature exposed with a public scope during testing and changed to private when I'm building for release.
public int ProcessGlobalMessages_NoSubscribers(DateTime lastSendTime,
private int ProcessGlobalMessages_NoSubscribers(DateTime lastSendTime,
Now I can surround test cases for that method in similar #if blocks and they'll only appear when I'm building Debug releases:
public void CheckProcessGlobalMessagesNoSubscribersReturnsCorrectCount()
A quick check in Reflector proves things worked as expected in the Release build assembly:
OK, so I’m not 100% happy with this workaround because it’s a fundamental design smell to me in that I can’t get the test coverage I want without a bit of trickery, but this seems like pretty fair compromise between doing my design in a TDD fashion and keeping my class’s public API as simple and clean as possible.