21 October 2006

[jMock] Listening to Opinionated Software

David Heinemeier Hannsen coined the pithy term Opinionated Software to describe the design philosophy he follows in the development of Ruby on Rails:
Rails is opinionated software. We make things that we consider good style easy to do and bad style hard. Or rather, we make good style beautiful and bad style ugly.
We have followed a similar approach in writing jMock. We describe mock objects and jMock as a design tool. jMock is designed to make some things easier to test than others so that doing test driven development with the jMock framework guides your code towards a style that we have found makes it easy to maintain in the long term and adapt to new, unexpected requirements. Code that is easy to test is composed of loosely coupled, cohesive objects and dependencies between parts of the system are made explicit and highly visible. Yes, you can use jMock's CGLIB plugin or Aspect Oriented Programming to get around jMock's limitations: to mock concrete classes and static methods or change the values of singletons and other global variables during a test, for example. However, we've found that when we find a need for one of those tools it's better to address the design problem than the testing problem. When the design problem has been addressed, the testing problem has gone away. We describe this as listening to the tests.

4 comments:

Anonymous said...

Hi,
I always find useful the CGLIB extension for jMock to be able to mock concrete classes (instead of being forced to extract an interface from my object under test...).
Why exactly do you think that there may be design issues behind this use of jMock?

Steve Freeman said...

Because then the interface is implicit, which means you can't see it and you haven't given it a name. Instead of using the test to expose a feature of the design, you have more to think about whenever you're working in that area: is the method overwritten? is it in a super class? what about the state of the rest of the class I'm extending? That sort of thing.

For me, the CGLIB should have a "Break Glass in Case of Emergency" written on the front. It's useful in tight situations, but not to be recommended.

David Saff said...

CGLIB and friends are most useful when trying to get a handle on legacy code, which is a fairly common operation for me. Making badly designed legacy code difficult to test can have the effect of pushing the code to have a better design, but unfortunately, its also possible the developer feels pushed to give up testing.

I'm a big fan of opinionated software (cf. JUnit), but I wonder if we could find ways to have it more clearly say "Sure, I can help you do that, but here's a better way." Graciously opinionated, perhaps?

Nat Pryce said...

JMock 2 allows you to mock abstract and concrete classes (without invoking their constructors) but the class that does so is called "UnsafeHackConcreteClassImposteriser". Sure you can use it but the name should guide you (graciously I hope) towards a better solution.