20 August 2007

We don't need no stinking interfaces

There's been another round of anti-Dependency Injection chatter in the blogsphere, so here we go again. Ayende's done a pretty good job of defending his response to the original posting. The arguments are the same as usual: we don't see why we should change our design just to make it testable. I would like to add a few comments to this round.

  • Static factories and the like are still dependencies, just implicit. Instead of making the dependencies clear in the code, so you can set up an object once and then just use it, statics force you to package up a load of hidden references with your class that aren't relevant after instantiation
  • I don't go around exposing private features all over the place. I expose the parts that need exposing because they express a relationship with a collaborator
  • As an author on the original papers, I resent quotes like
    I wonder if this is a defensive reaction because the authors of the examples don’t want to have to justify making you fundamentally alter your coding habits and re-write all of your existing code just so that you can use their pet objects.
    I'm used to being disagreed with over this technique, but this is a new one on me. Our approach to design has a long and very respectable history. If you're not aware of its roots, then maybe you should alter your coding habits.
  • I could do without some of the language, such as
    "The emperor is naked" and you see it.
    and
    Take a look at what people are asking for on the xxMocks forums and the yahoo test-driven group and you will see how every problem that the tool can't solve is actually a design smell. Pragmatic development teams don't believe this anymore.
    like we don't care about shipping reliable and effective systems.

One good thing this episode shows is that there are plenty of people who understand the issues and are prepared to engage.

7 comments:

Jacob said...

I love it when people in the clear majority try to pull off the victim thing. The acrimony on this thing swings both ways and you seem willing to keep the pendulum hopping with this post. Interestingly, the fact that a site labelled "About Mock Objects, a technique for improving the design of code within Test-Driven Development" that feels so closely tied to dependency injection as to feel personally attacked without actually being targeted is pretty revealing.

Steve Freeman said...

I don't think I have to add any more to this comment. It speaks for itself.

jdn said...

Jacob's original post, and subsequent postings, were about having designs be testable without having to use DI.

Nothing in your post defeats anything he said about that, and your comment "The arguments are the same as usual: we don't see why we should change our design just to make it testable" suggests you didn't actually read them.

Steve Freeman said...

OK, I'll be more precise. The argument appears to be: we're not going to change our design to include Dependency Injection. Other people differ.

The situation remains that I, for one, don't recognise the claims he's making about my motivation.

jdn said...

Steve:

That's a helpful clarification, thanks.

Disclaimer: I use DI, and not just for testing. And like it.

But I do understand why some might think it is mainly useful for testing from reading certain information about DI, since testing examples are often very easy and very informative ways of explaining how DI works. That was my introduction to DI, but I've since very quickly learned how it helps in other areas.

For lack of a better term, it's sort of a 'marketing' thing.

I can understand your reaction to the motivational angle. I'd have the same reaction (though to be fair, I think that at least one of the comments you objected to was from a comment on Jacob's blog, and not from Jacob himself, which isn't clear from your post).

Thanks again.

Jason Gorman said...

I'm still not convinced that creating interfaces that are only implemented once isn't a design smell somehow.

I've tried to explain myself - in the usual unscientific, handwavy manner - in this blog post:

http://parlezuml.com/blog/?postid=480

No proof, I'm happy to admit, but a strong inkling that something is amiss.

I see this as a tradeoff between increased code complexity and reduced maintainability, and testability.

Isn't there any way JMock and other mocking frameworks could take a concrete type, generate an interface at runtime and noodle with the model code to bind to the new interface?

Dependency injection I have no problem with, but unreused abstractions make me uncomfortable.

Steve Freeman said...

Hi Jason, I've read your posting a couple of times and I'm afraid I'm struggling with it. We'll have to meet up and you can give to me again with handwaving...

On the interfaces note, I have a different take. I tend to use interfaces to express relationships between objects, their roles. So it's almost like the interface is being used twice, once in the caller and once in the implementer. Rather than having multiple classes implement an interface, I tend to have classes that implement multiple interfaces.

I'm not sure about the automatic extraction idea, since the thinking about and naming of the interface is a large part of the benefit. If I did want to do it, I wonder if I could hook into Eclipse, which has a refactoring to do this.