The world mocks too much

One of my biggest annoyances when it comes to testing is when anyone reaches for a mock out of habit. The “purists” that I prefer to call “zealots”, are overwhelming in numbers, particularly in the TDD community (you do realise you can test drive your code without mocks?) Often I see teams use excuses like, “I only want to test a single responsibility at a time.” It sounds reasonable, yet it’s generally the start of something more insidious, one where suddenly mocks become the hammer and people want to apply it to everything. I sense it through signals like when people say “I need to mock a class”, or “I need to mock a call to a superclass”. Alternatively it’s quite obvious when the number of “stub” or “ignored” calls outnumber the “mocked” calls by an order of magnitude.

Please don’t confuse my stance with “classical state based testing purists” who don’t believe in mocking. Though Martin Fowler describes two, apparently opposing, styles to testing, Classical and Mockist Testing, I don’t see them as mutually exclusive options, rather two ends of a sliding scale. I typical gauge risk as a factor for determining which approach to take. I believe in using the right tool for the right job (easy to say, harder to do right), and believe in using mocking to give me the best balance of feedback when things break, enough confidence to refactor with safety, and as a tool for driving out a better design.

Broken Glass

Image of broken glass taken from Bern@t’s flickr stream under the creative commons licence

Even though I’ve never worked with Steve or Nat, the maintainers of JMock, I believe my views align quite strongly with theirs. When I used to be on the JMock mailing list, it fascinated me to see how many of their responses focused on better programming techniques rather than caving into demands for new features. JMock is highly opinionated software and I agree with them that you don’t want to make some things too easy, particularly those tasks that lend themselves to poor design.

Tests that are difficult to write, maintain, or understand are often a huge symptom for code that is equally poorly designed. That’s why that even though Mockito is a welcome addition to the testing toolkit, I’m equally frightened by its ability to silence the screams of test code executing poorly designed production code. The dogma to test a single aspect of every class in pure isolation often leads to excessively brittle, noisy and hard to maintain test suites. Worse yet, because the interactions between objects have been effectively declared frozen by handfuls of micro-tests, any redesign incurs the additional effort of rewriting all the “mock” tests. Thank goodness sometimes we have acceptance tests. Since the first time something is written is often not the best possible design, writing excessively fine grained tests puts a much larger burden on developers who need to refine it in the future.

So what is a better approach?
Interaction testing is a great technique, with mocks a welcome addition to a developer’s toolkit. Unfortunately it’s difficult to master all aspects including the syntax of a mocking framework, listening to the tests, and responding to appropriately with refactoring or redesign. I reserve the use of mocks for three distinct purposes:

  1. Exploring potential interactions - I like to use mocks to help me understand what my consumers are trying to do, and what their ideal interactions are. I try to experiment with a couple of different approaches, different names, different signatures to understand what this object should be. Mocks don’t prevent me from doing this, though it’s my current preferred tool for this task.
  2. Isolating well known boundaries - If I need to depend on external systems, it’s best to isolate them from the rest of the application under a well defined contract. For some dependencies, this may take some time to develop, establish, stabilise and verify (for which I prefer to use classical state based testing). Once I am confident that this interface is unlikely to change, then I’m happy to move to interaction testing for these external systems.
  3. Testing the boundaries of a group of collaborators - It’s often a group of closely collaborating objects to provide any useful behaviour to a system. I err towards using classical testing to test the objects in that closely collaborating set, and defer to mocking at the boundary of these collaborators.

Action is louder than words

It’s easy to execute a particular practice. The difficult part is executing the practice well. This applies with any trade, any profession and anything we do. That’s why we have professional sports people, professional tradespeople, and professions in general. It takes a long time to get good at anything.

One thing I’ve learned from observing great leaders and less than great leaders is that those that make a big difference follow the words they say. Less than great leaders talk in one way, yet act completely incongruently with what they said. Some leaders don’t realise this, believing that what they say is enough to motivate people. The result is that people get confused, defaulting to the behaviour they see, not the words that are spoken.

The lesson here: It’s important understand what people hear because that can be different, and to ensure that what you do follows what you say if you really want the message to get across.

Barriers to learning

One of my most memorable conversations during training went something like this…

Student: Aren’t these just best practices? I don’t see how this is agile estimation. How is this agile?
Me: Hmmm. I guess they are best practices. I see many agile teams frequently apply all these techniques when they do some estimation. Let me ask you about your current project. Do you get people who will do the work to give you estimates?
Student: No. Either we have a group of architects to estimate the work, or I estimate the effort for the team.
Me: Do you try to make make sure more than two people estimate?
Student: No. One person should be good enough to estimate.
Me: Do you try to understand or uncover the assumptions that person is making during estimation?
Student: Sure. We ask them to write their assumptions down.
Me: Do you use relative estimation?
Student: No.
Me: So you’re telling me that even though these are best practices, you’re not necessarily doing any of them?
Student: Yes. But I don’t see how this is agile.

When people get fixated with disagreeing about something, they stop listening and stop learning. Drawing them out of this corner can be a really difficult task. In this particular case, the student wanted clear evidence that agile was something else and wasn’t prepared to hear about estimation best practices being normal best practices when working in a most agile methodologies.

A state of mind

I was reminded today of a simple principle, especially when working in new environments and with new people to, “Keep an open mind”. Easy to say, yet first hand observation of others seems to imply it’s hard to do. I’ve seen a lot of people come into a new environment, judge a situation and state an outcome.

They share nothing about what they are concerned about, what they observed, and why they reached the conclusions they did. It’s no wonder that people can’t relate to the outcome immediately. Keeping an open mind helps to resolve jumping to solutions too early. Better yet, sharing your mind and the process you went through helps others to relate to you and for you to realise if you got any of it wrong.

Secret Sauce: Embedded Coaching

One of the biggest teases developers use on their peers when they move into a non-developer or a less developer focused role is to tag them as “Post-technical”. I’ve heard this term ever since I joined the industry. My other interests around team work, organisational processes, coaching and training seem congruent with this attitude.

How do I try to balance these roles? Embedded coaching.

It’s as simple as working in the role of a developer and a coach at the same time. There’s something about working “on the front lines”, so to speak, that earns you a certain level of respect that you wouldn’t get if you were on the same team in the role of a project manager, or something you wouldn’t earn if you visited as a coach or advisor. It lets you build that trust and rapport on a daily basis that gives you insight into the things that drive people mad, or the things others may not feel comfortable stepping up and saying out loud.

Of course, there are benefits to also doing coaching from an outside point of view though I do think that embedded coaching is undervalued and often unavailable due to the delicate mix of skills required.

Software Architects Of Today

Shouldn’t be sitting in ivory towers dispensing design documents or ideas with no basis of reality.

They should be coding. They should hang around to see how their decisions pan out.

They should be hunting down smells, listening to the team about painful areas, thinking about how to turn them around. They should work with the team to co-ordinate a strategy for redesign or a series of refactoring to turn complex code into simpler designs.

They should be sharing their experience in collaborative ways with the team to create several design choices, to clarify the pros and cons and to refine them to a best choice.

They should still be looking at the bigger picture, and always looking for ways to share that big picture. Part of it might be an XP Metaphor (or the Shared Vision). It might come out looking like an architecture diagram.

I’m sure of missed some things, and I know for a fact, most software architects can’t meet even these. Fortunately I get to work with many who do.

Answers for the right Question

Seek the answers to the question, “When is this useful?” instead of the classical “Is this useful?”.

If you keep talking…

You miss the valuable things that other people have to say. Listen, reflect, and then comment. Not before.