Designing inter-object protocols using mocks

The intent of my recent paper, was to demonstrate how mock objects could be used to discover roles, and design the communication protocols between objects. The following content did not make it to the final version, I think these are important points so i will describe them here.
Distinguish between an Object’s Internals and its Peers
It is important to distinguish what the internals of an object are and who are its peers that it communicates with.  An object’s internals are usually created and used within an object. In my example the fact that the Register object collaborates with the Sale object to calculate the receipt total is hidden. Peer objects, on the other hand, aren’t hidden inside the object, they are a passed in to the object, either through the constructor as a dependency or through a setter (if the peer object is a policy or notification object).
All interactions internal to an object should be hidden from the client code that uses the object; likewise a unit test should not be concerned with the internal details of the object under test.
Exposing an objects internals details to simply test every aspect of a class in pure isolation, causes the tests to be overly coupled to the implementation details of the object. You will find tests using mock objects highlight these design issues very quickly, one hint is when you find that the production code, simply mirrors the expectations you wrote in the test code, this  obviously makes tests very brittle since they overly coupled to the implementation details of the object under test.
This could be addressed by changing the behavior of the mock framework to ignore all calls between the object under test and its collaborator unless explicitly specified.  However this does not address the underlying weakness in the design of the protocol between the object under test and it collaborators, it fact it simply hides all complex inter-object protocols.
Nat Pryce coined the phrase “A composite object should be simpler than the sum of its parts.”  An object should provide a simpler API to its clients, rather than simply exposing all its internal objects through its API. I find this is a good heuristic to follow when deciding what should be internal to an object and what its peers should be. On the other hand we should ensure we are not hiding the wrong information inside an object. Well-designed objects should be context independent and not tied to its environment; objects tightly coupled to its environment will be difficult to instantiate in a unit test. I find the rapid feedback provided by tests is invaluable when designing objects.

Why did I chose to use NMock ?

A lot of people ask me why i chose NMock, for this introductory article, I felt NMock 2 is the best choice of API,  because it works best within the context of the article. It has an expectation-based API, which makes designing object communication the focus of testing. Its expectation API acts as a domain specific embedded language that clearly, precisely, and declaratively describes object communication. I also find that NMock2 provides a highly detailed explanation of what has failed, which allows for quick error diagnosis and resolution.

I’m sure many people will have different opinions on this but I have avoided using mock frameworks that use the popular Arrange, Act, Assert (AAA) style because I find that it does not get you started off by thinking about the contracts or communication protocols between objects. With AAA-style mocks I find it’s easy to overlook design flaws in your inter-object communication.

The main drawback of NMock is the use of strings to identify expected methods makes refactoring harder.  This becomes less of an issue when a code based is designed around well-defined roles and responsibilities, containing narrow role based interfaces, which are used more locally.

About these ads

2 Comments on “Designing inter-object protocols using mocks”

  1. Sjur Kvammen says:

    Great article and a lot of fine points to digest :) But I’m curious, what happens to the process of interface/role-discovery in a dynamic language? It seems interfaces are recording part of the dialogue(protocol) between the objects, Then later you plug in an actual implementor(actor to fill the role). But in a dynamic language you don’t have the interfaces to specify/make visible/clearify the roles, so how do you handle it? Do you just skip the interfaces and rely on the tests to document/specify the roles an object needs/expects from its peers? Or?

    • isaiahperumalla says:

      I often program in smalltalk in my spare time, I find mock objects still useful for discovering role in the system. its true interfaces help make roles explicit in a system, in a dynamic language like smalltalk, there are no interfaces, but the smalltalk ide does have concept of protocols, set of messages that an object responds to. This helps to some extent to see what role an object plays.
      But i find that the tests make communication protocols more visible and provide a better documentation on this.
      Interface dont tell the whole story, there is a suttle difference between protocols and interfaces. it best summed up by this quote
      “an interface describes whether two components will fit together, a protocol describes whether they will work together. ” –from steve freeman and nat pryce book

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Get every new post delivered to your Inbox.