"COMPUTER POWER TO THE PEOPLE! DOWN WITH CYBERCRUD!" - Theodor Nelson
Tuesday, September 20, 2005
David Buck and Charles Monteiro have been discussing how to make sure "private" methods in Smalltalk stay "private". Both have great techniques and it of course got me to thinking: "What a great use for unit tests!"
In all Smalltalks, we categorize methods of a class. Why not mark the private methods in some way? For example, use "private" somewhere in the category name (private, private-processing, private-accessing, etc). This way we know what should be private and what shouldn't be. It doesn't matter the convention just pick one. Now, that we know the private methods, create an object proxy that forwards all calls to the real object. This proxy would check if the method coming in is "private" and signal an exception if a method is "private" since only outside objects will call the proxy directly (Everything else will behind the proxy wall). Now, just pass the proxy around in the unit test as if it were the real object. Let the unit tests verify that we are not calling "private" methods and we have no run-time costs. Of course, we could get fancy and use method wrappers and #become:, but I will leave that as an exercise to the reader (or maybe a future blog entry?).
The main point of this post was to give yet another idea of how to make sure private methods stay private. I would love to hear more techniques. This technique that I just described is what I call meta-unit-tests. We are verifying meta-information about our program. I've used meta-unit-tests for making sure deprecated API calls are not sent in my code and that certain methods are implemented (ie don't have super that calls #shouldBeImplemented). We have a lot of information available to us at unit test time. We can take advantage of it!