First, an apology to Alan:
Perryn’s right; by and large we agree. I should have phrased things better (again). That’s what I get for posting on Friday afternoon while trying to do three other things at the same time.
I know you know BDD. I just didn’t think you had covered it at all when saying, “No, no, no” to my insistence on using mocks, hence the rather lazily worded post. I should reword it as “he still only discusses testing in a context of ensuring that nothing’s broken”. Then, if you still find it irritating, it’s fair. Your experience far outstrips mine. I love to provoke, because it gets people riled enough to share their wisdom with me. Thank you for doing so.
Even so, assigning behaviour to people based on misconceptions or lazy thinking is far worse than doing it to code, and I do know better. Slapped wrist for me. Apologies to you.
Second, back to the point:
Maybe it’s because I type stupidly fast (not always a good thing, as evidenced above), but I find it a lot easier to just throw an interface in for something I haven’t designed yet, add methods as and when I need them and create a “real” class from it later. The alternative is to be writing two or three behaviour classes at once, trying to separate all the responsibilities for each, while mocking out the tools that they rely on or – heaven forbid – adding another couple of unfinished behaviour classes as the tools expand.
I wouldn’t use one behaviour class to test / design one class and its tools, because then anyone else who comes along to use the tools has no idea what they do. It’s a pain to have to track tools back and see how other classes are using them. So, if you need to have a behaviour class for each tool, why not just mock it out to start with?
The exception to this rule has got to be when you’re writing “utility” classes – pieces of the system which are going to be widely used, such as persistence layering, or in the case of my game stuff the asynchronous mechanisms. Then you’re designing a library which should be fully tested itself, and it seems just as reasonable to use these tools as it is to, say, create a new HashMap or ArrayList. However, using libraries brings its own fun and games – see Darren’s posts re third-party code. Even then, even for something as simple as file handling, I frequently want to use something other than the real tool so that I can either test what’s going in and out or stop it from affecting other tests.
And my final note (for this post, anyway):
The use of
FooImpl for the implementation of interface
Foo is really, really annoying me. Call it
DefaultFoo if it really doesn’t do anything different to what it says on the tin, which I haven’t come across yet – most of the
FooImpls here I would rename to
ServicedFoo or similar. Calling something
FooImpl implies that there will never be a different implementation of
Foo. Mocks are an implementation of an interface too – they’re just very specialised.
Update: I’d only call them
ServicedFoo because the relationships between the tools and the things which use them aren’t well defined (or designed), and having a better name is better than having the worst name, even if it’s still not great. This is called Technical Debt. I am working in a Technically Indebted environment which has matured to the point that the cost of change curve, whilst less steep than many of the projects I’ve been on, still exists. Unfortunately unwinding all of the tangled interrelationships, renaming poorly named classes, providing unit tests for everything etc. is so expensive that it no longer has any business value. I probably shouldn’t even suggest renaming things, because it’s not worth it. At least the bad naming is consistent. I’d just like to stop it happening in the first place.
(Is ServicedFoo really that bad? It implements Foo using server-side services… well, maybe I need more experience here.)
I do know that in an an ideal world,
Foo is the relationship between the tool and the thing using it. Maybe the tool is actually called
An instance: I have a
RequestEventHandler interfaces. The thing which submits report events and handles request events is better known as the
Engine, or back end. The thing which submits requests and handles reports is better known as the
Gui. There’s a whole asynchronous event handling mechanism which sits between them which implements both interfaces. Neither the Gui nor the Engine needs to know about that, or even about each other.