« Soft Sciences | Main | Video Interview I did for InformIT »

September 20, 2007

Comments

Elliotte Rusty Harold

Right question. Wrong answer. Making the method testable by making it public is a mistake. Now you have a method you don't need in your API. Making the method testable by making it public in another public class is two mistakes. Now you have a method and a class you don't need in your API.

Private methods are implementation details that can and should change routinely at the convenience and whim of the programmer. Writing explicit tests for them locks down your design and makes it harder to refactor and optimize.

The right answer is to test the method through the public methods that call the private method. If you can't make the public method call the private method, then the private method is dead code and should be eliminated.

Elliotte Rusty Harold

One more thing, that may explain why we frequently disagree on this point. Looking through your other posts you seem to think that the worst possible thing is a bulky class. You're willing to bulk up the public API if it makes the individual classes smaller and more manageable. I'm not willing to make that tradeoff. I think a bulky API is much worse than a bulky class, and I will hide a lot of private complexity inside a class if it makes the public API of the entire system simpler.

Al Mellor

My favourite half-way house solution when I feel lazy is to add

boolean isPrivateMethodWorkingOk( expected params, test driver params )
{
results = callPrivateMethod ( test driver params );

boolean isOk = results agree with expected params ;

return isOk ;
}

You can see the actual coding varies a bit with language and access to result parameters.

It is half way because
- the poor coupling has not been addressed
- the private method stays private
- the test method is not as open to abuse as making the private method more visible
- it does mix code in for test with production code

I find it a useful quick and dirty hack sometimes.

Rasmus Rasmussen

Hello Michael!

A friend working as speech therapist once told me that children learning two languages from start gets a "thicker language-trunk" allowing new language-branches to sprout more easy. This means these whiz-kids has easier to adopt new languages later. Perhaps because they avoid hard coupling to one language in the brain-signaling-substances? (Boy... realizing I'm far out on thin ice here :-)

If I have to access bizlogic from presentation layer AND from testcode then the bizlayer gets a thicker trunk. Definitely big synnergy effect.

I prefer introducing decoupling instead of tricks like subclassing because with subclassing I loose the synnergy effect. But then, that's me. Or is it because I read this article two years ago? I'm not sure! :-)

Regards,
Rasmus

Michael Feathers

Elliotte: I think we've been talking past each other. It might be better if we had code in front of us. I never want make private methods public to for testing. I do, however, enjoy moving them to new classes where they can be accessible to tests yet inaccessible through the original class's interface.

Becky Breeden

This is so contrary to my ood upbringing where everything is made private except for the logical operations that a consumer needs. I was also trained to break logic up into 'page' size methods, resulting in too many methods to expose through a public interface. Many of these functions are utility type functions and a person may argue that they should be put into a static utility class but often times there is business logic specific to the class that should reside inside the class but not be exposed.
With TDD at the forefront of every developer's mind, we need a non-invasive way of testing code easily. Using AOP for these purposes has certainly entered my mind on a number of occasions. Another notion for testing that I fantasize about is a highly configurable runtime that can provide state and behavior info on selected objects.

The comments to this entry are closed.