…and we’re back!

Here’s two contradictory propositions about test first development (TFD):

  1. TFD helps you to design your software better.
  2. TFD should not change the way you design your software.

At the moment I’m still designing a library for intermediate level developers. Static members, for all the bad they are, often make my programming life simpler without jeopardizing the future of my code altogether, so I guess among intermediate developers some will feel my pain better than I do, and develop a negative understanding of the following, short sighted truths if I do not provide static methods as part of the kit:

  • Factory methods are a good alternative to constructors when constructors are not available (minor)
  • Where one, and one only, instance of a service is, for the foreseeable future, desirable, static methods avoid burdening oneself, or other developers, with the need to bounce a singleton around a software system (major).

As a quick reminder or introduction, here’s why TFD (among several other, theoretical and formal, protagonists) doesn’t like static members:

  1. A unit test is validating a class. This is done to ensure that the object will behave as expected, so that, if this object appears to misbehave in some way, you can rely on the unit test failing or passing to tell you either yes, the object is misbehaving, or no, the object is mis-informed – interacting with something else, and that thing must be broken.
  2. A static member is a member that you cannot, in many languages, replace by a stub. That means that you can’t isolate the behavior of A, using static member S, from the behavior of the system {A,S}.
  3. Since we can’t easily tell whether A or S or {A,S} is failing when A appears to fail, the unit test for A is imperfect. More importantly, {A,S} is harder to maintain.
  4. Ergo, static members are undesirable.

As an API designer, what should I do? Well maybe I’ll change my mind later, but for now, here is how I feel about it:

  1. If I were designing an API for experienced developers, I would most likely avoid statics. I couldn’t use them anyway because the use of static members would taint my API. Not all experienced developers have a deep grasp of why statics might be bad. This is not how humans learn. Most experienced developers feel that static members are bad. This is what developers learn.
  2. Since I am designing an API for intermediate developers, I may be ill inspired not to provide them with convenient static functions. In fact I should wonder whether my static functions are a poor substitute for globals.
  3. I need software written using my libraries to be unit-testable.
  4. Ergo, I shall have to write a stub version of my libraries – an empty shell containing all classes and function signatures in my libraries. This way developers can unit test software written using my library, and enjoy readily available stubs providing support for testing (e.g., logging API calls)

I find the ‘case of untestable static members’ delectable. I may be more against static members that many developers are, but today I’ve been the devil’s advocate, so I’m just about to turn my jacket but…

…not in this post.