We've found these benefits from learning to Listen to the Test Smells.
- Keeping knowledge local
- Some of the test smells we've identified, such as needing magic to create mocks, are to do with knowledge leaking between components. If I can keep knowledge local to an object, either internal or passed in, then its implementation is independent of its context. I can safely move it wherever I like. Do this consistently and I can build an application as a web of communicating objects.
- If it's explicit I can name it
- This is why I don't like mocking concrete classes, I like to have names for the relationships between objects as well the objects themselves. As the legends say, if I have something's true name then I can control it. If I can see it, I have more chance of finding other uses and so reducing duplication.
- More names mean more domain information
- I find that when we emphasise how objects communicate, rather than what they are, I end up with types and roles defined more in terms of the domain than of the implementation. I think this might be because I have more, smaller abstractions which gets me a further away from the underlying language. Somehow I seem to get more domain vocabulary into the code.
- Pass behaviour rather than data
- I find that TDD with mocks encourages me to write objects that tell each other what to do, rather then requesting and manipulating values. Applied consistently, I end up with a coding style where I pass behaviour (in listeners and callbacks) from the higher levels of the code to the data, rather than pulling data up through the stack. It's an unusual style in the Java/C# world, but I find that we get better encapsulation and clearer abstractions because I have to clarify what the pieces will do, not just what values they hold.