@marick Have you blogged anywhere about with-redefs [a Clojure function used for mocking] and how it relates to mocking private fields in OO? I’d be interested in your thoughts.
@marick My concern is whether by using a test mechanism that prod code can’t exploit, am I reducing some of the design benefits of TDD?
In order to design, the designer must find words (abstractions, if you wish) that give her leverage when thinking about the code.
In order for that leverage to carry over to writing and later changing the code, those words have to appear in it. Most importantly for a language like Clojure, verbs have to be reified as functions.
Testing makes design rigorous by forcing it to be concrete along a different dimension than coding (dynamic rather than static). Tests should therefore have executable (mockable) access to reified verbs.
A programmer using a function may need a conceptual understanding of those verbs, but does not need direct access.
Therefore the reified verbs may be marked private - but only if the tests have a way to evade that. (That is, the need to do the right thing with testing trumps the desire to prevent a future programmer from doing the wrong thing.)
In practice, I’ve found it mildly helpful to add a “testable” access level to public/private. That divides a chunk o’ code into (1) functions of interest to normal users of the code, (2) functions those users don’t need to care about, but that are important for understanding the idea behind the code, and (3) functions that are just a coding convenience.