Steve Freeman Rotating Header Image

IWonderAboutInterfaceNames

InfoQ has just published Udi Dahan’s talk from QCon 2008 on “Intentions and Interfaces”. It’s good to see the message about focussing on Roles rather than Classes being pitched to a new audience. That’s what we were trying to talk about in our “Mock Roles, Not Objects” paper.

I wonder, however, about his style for naming roles:

interface IMakeCustomerPreferred {
  void MakePreferred();
}
interface IAddOrdersToCustomer {
  void AddOrder(Order order);
}

It took me a little while to figure it out, but to me the issue is that these interface names bind the role to the underlying implementation, or at least to a larger role. One of the things that Nat Pryce and I discuss in our book is that interfaces need refactoring too. If two interfaces are similar, perhaps there’s a common concept there and they should be collapsed—which brings us more pluggable code. This implies that roles, as described by interfaces, should aim to be context-independent. In this case, I might rename one of the interfaces to:

interface IOrderCollector {
  void AddOrder(Order order)
}

since there will be contexts in which I really don’t care that it happens to be a Customer. That said, I think Dahan has other motivations with this naming scheme, since he also uses it to control retrieval from the ORM, but there might be other ways to achieve that.

A colleague was once accused of being so role-happy, that he defined an Integer as a combination of Addable, Subtractable, Multipliable, and Divideable.

8 Comments

  1. Jim Arnold says:

    ICollectOrders surely? :-)

  2. Mike says:

    Yes, although without an implementation to anchor you to reality, there’s always a temptation to over-abstract interfaces. If you can generalize from IAddOrdersToCustomer to IOrderCollector, why not from there to a generic ICollector, and from there to ITakeOneThingAndReturnVoid?

    Same with (C#) delegates. Predicate and Converter<I> are reasonable enough, but when you get to Action (“take a thing and do something”) you’ve lost all sense of what role is being performed. Which is OK in some contexts, but not in most.

    Maybe the rule of thumb should be that an interface name should convey something beyond what’s already implied by its method signatures?

  3. @Mike I take your point. An interface should be relevant to the domain its defined in. If I’m talking about shopping, then an IOrderCollector would be appropriate. If I’m building a virtual machine, then ITakeOneThingAndReturnVoid might actually make sense.

    I think your rule of thumb is interesting. IAddOrdersToCustomer looks a bit like a duplicate of its method — except that sometimes it’s really hard to find a better name.

  4. @Jim If you insist… :)

  5. Malte Finsterwalder says:

    Concerning Roles, did you read the DCI-Architecture Article from Jim Coplien?

    http://www.artima.com/articles/dci_vision.html

    Might be interesting to you…

  6. @Malte Yes, we already saw that. A lot of what we already do is inspired by Reenskaug’s work on Roles which is quite old now. Frankly, most of the serious OO programmers I know do something like DCI already without the fuss. In the book we talk about two-layer architectures: the lower layer is a graph of objects that implement the behaviour, the higher layer is a declarative description that constructs the graph. We haven’t needed traits to do that yet. We’re also not quite so obsessed with graphical UIs, there are plenty of other types of system in the world.

  7. Andy Palmer says:

    I agree that the interfaces you’ve chosen are poor.
    The Interfaces contain the name of the type that it appears that they will operate against. This is particularly true of IAddOrdersToCustomer where it does not take a customer.

    The point that Udi was making was that by leveraging the ‘I’ prefix, you can anthropomorphise your interfaces into roles. A class then defines itself in terms of things that it can do.

    Have you seen this blog post on Interface Names that was inspired by my experience of that presentation?

    JNarrate also contains some good examples of the direction that we took this.

  8. @Andy. Using the ‘I’ wart as part of a description is an interesting idea to push people into thinking about roles, but I think of it as a “Training Wheels” rule–something to get started with until I can don’t need it any more.

    I find that puns don’t age well in code. I still regret that we use the name Mockery in JMock. One of the clues is that the variable names are always different from the type names. We often write:

    Mockery context = new Mockery();

    and you write:

    IBrowseTheWeb browser

    Maybe I’m just too fixed in my ways but I believe I would have more consistent language with:

    MockContext context = new MockContext();

    Browser browser

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>