« Sufferin' Sukertash | Main | Thank-God for Wireless »

Mocking my Visitors

Listen to this articleListen to this article

I mentioned in a comment earlier this week that I like Builders as they allow me to separate out the ickyness involved with construction from my nice pristine objects. Besides anything else, it allows me to layer on functionality: first implement the domain objects, assembled by hand for testing purposes; then create another layer—the builder—that will automate the construction process.

Of course being the good little TDD weenie that I aspire to be, at some point I want to test that the builders are generating the correct structure.

IMHO, the utterly evil-broken-and-wrong approach is to expose all the properties on all the nodes in the graph—I use the terms node and graph generically here to refer to objects related in some fashion—for reasons I've harped on about more than enough.

Another approach—that maintains encapsulation—is to implement equals() for all the nodes in the graph. The idea for testing then is to create the expected structure by hand (just as I had already been doing) then use the builder to create another and assert that the two are identical. I have actually used this approach before and while it worked just fine, it never really felt Good™. I'm not sure why; just an intuitive ookyness.

More recently though I tried a different approach: using a visitor. Again the approach was similar: constructed the expected structure by hand; then use the builder to make another; and finally assert that the two are identical. This time however, the idea was to traverse the expected structure and match, node-for-node, with the actual. The neat thing about this approach though was that because my visitor class was an interface, it was trivial to use EasyMock to do all the grunt-work for me. (EasyMock also allows mocking classes however I still prefer interfaces.)

The idea is to create a mock visitor using EasyMock and pass that to the accept() method of the structure I had created by hand to set-up the expectation. Once that was done, I could then simply pass the same mock to the accept() method of the structure constructed by the builder:

public void testBuilderMakesIdenticalStructureToOneBuiltByHand() {
    // Create the two structures
    Node createdByHand = createByHand();
    Node createdByBuilder = createByBuilder();

    // Visit the one created by hand to set-up the expectations
    NodeVisitor visitor = EasyMock.createStrictMock(NodeVisitor.class);
    createdByHand.accept(visitor);
    EasyMock.replay(visitor);

    // Visit the one created by the builder to verify
    createdByBuilder.accept(visitor);
    EasyMock.verify(visitor);
}

private Node createByHand() {...}

private Node createByBuilder {...}

Note: I'm using the latest version of EasyMock that supporst JDK 1.5 generics however I'm not (nor will I ever be) using static imports as suggested in the documentation!

This time, it felt Good™. I could use the same visitor for testing, reporting and persistence, all without the need to break encapsulation.

Now while I'm really not keen on igniting a religious flame-war over mock objects in general nor mock object libraries in particular, the fact that EasyMock works against the real interfaces—as opposed to using string descriptions ala JMock— was a huge advantage in this case.

Comments

Hey Simon. You mention two patterns that are probably the most distinguished in terms of patterns I use least.

Your use of the Visitor pattern is very cool, although for mind on initial glance the code doesn't nicely communicate what is being tested. Also, I'm certain your use of the Visitor pattern is driven by requirements and not tests!

While I completely see the value in the Visitor pattern, the Builder pattern on the other hand is one I've avoided. To date, if it is used in a project, it usually dies a quick death at the hand of refactoring. While it does frequent my thoughts when I consider my domain language, it inevitably loses out to an Abstract Factory.

When I consider the applicability of a Builder - separating the construction of an object to allow the construction of different implementations - these responsibilities usually fall into different patterns. The 'construction' part usually falls within a Factory, the 'construction of different implementations' part in a Strategy. But perhaps that is what the pattern intends to be, a combination of a Factory and a Strategy.

Certainly an Abstract Factory, creating families of related objects, is my most used creational pattern. As the pattern suggests, if the Factory is an interface you can of course mock that, and if the Factory produces abstract objects (interfaces) then there's the added value of being able to mock the things the Factory produces. Of course, then you experience the novices delight of writing unit tests that expect a mock to construct a mock whose expectations, in turn, also need to be verified *gasp* (then again, there's no reason a Builder cannot do the same). I guess the reason I put Abstract Factory to use so often is because it's common place to have families of related domain objects, usually related via inheritance.

The 'family' part is also very important as every implementation of a Builder I've seen is very shallow, it's shortness usually not justifying it's existence. On the other hand an Abstract Factory constructs many objects and usually has a healthier length.

One part of the intent for a Builder I haven't mentioned so far is that it's usually concerned about the creation of 'complex objects'. This is also typically at odds with most objects - people don't set out to produce 'complex objects' given the goodness of simplicity and short and sharp object responsibilities. Certainly an object that manages a graph of objects (in Eric Evans' terms, an Aggregate) warrants a 'complex construction' process - and maybe you needed it for the domain you're dealing with now. Most domain models do and/or should involve Aggregate objects, but they are often created one piece at a time via UI features. The Aggregate construction usually comes into play when the objects are being 'reconstituted' from data source(s) - but hold on....a good ORM tool does this job for you. Constructing an Aggregate for other purposes is rare, and I guess that's a good reason why I've rarely seen the pattern used.

BTW - when an ORM tool is not an option for 'reconstitution' purposes, using Evans' approach of co-locating the initial construction and reconstitution of domain objects and Aggregates in an Abstract Factory has worked perfectly well conceptually and at the coal-face for me.

Oh, and your point about JMock I completely agree with. I'll take code that morphs with refactorings and offers faster feedback by failing at compile time instead of test time any day.

Matt,

Nice to hear from you. I guess you have a bit more time on your hands at the moment? Hope you guys find some more work soon so you can continue to enjoy Europe.

To your first point regarding Visitor and Builder being little used patterns. The problem with visitor is it _tends_ to be a bit brittle. That said, it's no more brittle than any other "push" interface. Stuff I work on, for some reason, tends to involve a lot of parsing and/or calculation meaning traversal of complex arrangements of objects (as opposed to complex objects) comes up quite often; Visitor/Strategy therefore are two patterns I tend to use for this purpose.

As for Builder, the distinction I make (and I don't claim to be an expert so I've probably missed the point myself) between Builder and Factory is that a Fatory creates many of the (largely) same thing whereas a Builder is configured to build different things.

It's actually quite funny because I loathe detest and despise factories for some reason. I think mainly due to their, IMHO, blatant over-use in most applications that I come across. Factories are one of the first patterns most people come to grips with early on and become a golden hammer; I speak as one who has trodden this path and realised the error of my ways ;-).

The general problem I have with factories is that whilst they allow decoupling the _actual_ construction of objects they really are a glorified "new". I try, as a matter of course, to have dependencies constructed externally and injected (sorry, it was going to crop up sometime) either via a constructed or, if you must *sigh* using a setter.

So while not useless, I tend to whince when I hear "let's use a factory" as the first solution to a problem :)

Again, the domains that I tend to deal with involve a lot of this kind of construction but I can think of other instances where a Builder _could_ be used but usually isn't for various reasons.

For example, it's usually the case that when filling out an online form to fill in say address details, that the application will construct a hollow Address object with getters and setters and as the user completes the fields--street, city, postcode, etc.--the appropriate set methods will be called. Now again, I just thought of this off the top of my head so admittedly it's not the best example, however, the thing I don't like about the approach just mentioned is that it requires me to construct an Address object in a largely invalid state: surely an address must have at least a street, city and postcode? If instead of thinking about an address as an entity and instead as an immutable Value Object (I like immutable objects!) I can interpose a builder between the UI and the domain. Now imagine I did this for as many aspects of the domain as I could possibly rationalise--phone numbers, bank account details, etc.

In some ways I don't see a graphical user interface as being _that_ much different from a database or parsing a properties file, etc: It's all about transforming one representation into another.

The other thing I like about builders is they _can_ act as a simplified, de-mormalised if you lie, facade for the construction of complex object graphs. When using a tell-don't-ask calling convention, with the Builder acting as the receiver, this further de-couples the logic for construction from the external representation.

Now again, admittedly we have fancy ORM tools, etc. for a lot of this kind of work, especially when using databases and XML but the point remains that these libraries use a similar mechanism internally; it's just that you don't see it most of the time.

The thing to me about complex versus simple aggregates is that, in my humble experience (IMHE), simple arrangements usually consist of objects that are really just a big grab bag of "every piece of data we could think of" all lumped into one class. For some reason, developers don't seem to like what they perceive as one-to-one relationships. I have a class at the moment that has 5 private methods in it, one of which could technically be (though I haven't made it so) static. This irks the hell out of me: so much private behaviour just wreaks of a missing abstraction.

Anyhoo, in conclusion, I agree that many people don't use Visitor and Builder and possibly for very good reason. However, both of these patterns fit nicely into my desire to build applications which send behavioural messages between objects rather than simply ask for data.

Your mileage may vary ;-)

Cheers,

Simon

Tangent following...

Is it just me, or is the equals() method really hard to use [properly]? I find myself creating an Equator interface (much like Comparator), and using implementations of that all over the place. That way you can use different equators for different interfaces for an object, and never have to worry about the abstract class' equals method being over-ridden.

The only time I would use equals() is if there's only one implementer of an interface, but I'm not sure about that anymore. Been bitten too many times.

Also, I only ever toString() if it's of use for debugging, or perhaps has a REAL serialized form (ie. messaging). Everything else uses a formatter.

Post a comment