Are .net interfaces required

September 11th, 2008

Back to topics from the Elegant Code Open spaces lunch.  And this was a doosy. 

We were talking about getting developers to embrace TDD in their development methodologies.  As it so happened, one of the developers that need to be embraced was there — which always make for a more interesting discussion.

His main argument against TDD was that it almost required interfaces to do it.  Why do we need interfaces?  Because in order to mock something, it has to have an interface or an abstract class (using Rhino Mocks and Moq.  Sorry TypeMock, they aren’t breaking open the wallet).  So to do TDD, it is almost required to have an interface in every non-domain class in the system.

Why didn’t he like interfaces?  Partially because it was more work to deal with them.  Using resharper you can’t use Ctrl-B to go to reference, you have to use Ctrl-Alt-B to Go to Implementation.  Then you have to keep everything in sync.  And if you aren’t using ReSharper it is much worse.  Lets not be petty about this, implementing interfaces and keeping them up to date can be a bit of work, EXPECIALLY when the interface will only be used by one class.  Now it is just plumbing.

This isn’t the only compromise we make for TDD.  We also remove most private methods.  We make methods private by not adding them to the interface.  This becomes even more pronounced when you look at other languages (cough**ruby**cough) that don’t require some of this plumbing.

Here was my argument for interface and tdd.

First off, if you learn to use ReSharper effectively, dealing with interfaces becomes almost no work at all.  There is a refactoring called “Pull Member Up” that adds members in a class to an interface.  And if you add something to the interface directly, alt-enter will implement a stub on all of the classes that implement the interface.  Really, it can be almost pain free.

Second, from my Head First Design Patterns book: Program to interfaces, not implementations.  This is also in the GoF (Gang of Four) Design Patterns book. Interfaces are about not being tied down to a particular implementation.  Make things swapable.   It is also about making sure your class doesn’t care how any dependency class is implemented.  You can also read these points on the Wikipedia page on Design Patterns:

  • clients remain unaware of the specific types of objects they use, as long as the object adheres to the interface
  • clients remain unaware of the classes that implement these objects; clients only know about the abstract class(es) defining the interface

Third, this is another way to combat code complexity.  When you design an interface you make yourself think a bit more about the implementation (at least I do), think about how you want the code to be used.  You don’t always get more done by write more code faster.  It often pays to take a moment to think about what you are doing.  When you do this you can often get away with writing less code and create a better implementation.

Forth: more time spent early on with TDD mean less time spent later in the debugger.  Less time you have to spend in the debugger the faster you can release your product.   Now, I’m not a 100% TDD guy.  There are some things that are just so hard to test that you start diminishing returns.  But Presenters, and services should be very testable. 

Fifth: code reuse.  I have had much better luck with code reuse do to TDD than I have have without it.  Before TDD I would try to share classes around and end up having to untangle a host of classes to get the code reusable.  Post TDD, much less work.  With effective use of IoC containers it is almost no work.

Sixth: If you want the goodness of an IoC, stick to creating interfaces.  That statement isn’t 100% true, but because of limitations in the .net framework and our tool set, this is what we have to do.

Finally, one of the last arguments against TDD that I heard that night was “but I have to ship my code on time”, as if we TDDer’s get a pass on timelines.  Dude, if you’re reading this, I’m sorry for jumping all over on that one — but you deserved it.  

  • Jason Walker

    @Chris: I think we’re coming to an agreement here.

    My current policy on unit tests is to test the tricky code, and the important code, and to write tests as issues become apparent. Worse than a bug is a regression bug…

    I am not overly familiar with BDD – I’m still trying to figure out what the difference is. I must research further.

    “Also, a bad architecture, or bad testing methodology can be a major drain on productivity. Which gets to what some of your point is really after, which is:
    “show me TDD done well, and then I’ll believe you.””

    I think you hit the nail on the head with this paragraph. A bad design, or a bad test can be worse than no design or no test at all. I think a lot of people have had bad experiences with unit tests, get frustrated, and write it off as useless. Hence, friction.

    I’ve been contemplating putting together an example application using MVC, and some of the things I’ve been learning by using LTS in my last 3 projects. Making this easy to test would be one of the primary goals of the assignment for myself. Of course, as you said, it’s hard to find time…

    Finally, it is my priority to have working software too… I tend to be a perfectionist about that too… but it really comes down to the priorities of who is paying the bills.

    Good discussion,
    ~jw

  • http://www.elegantcode.com Chris Brandsma

    @Jason: this is kind of a separate topic — teaching style.

    First off, there are not many good teachers out there. But there are a lot of loud people. Just as with religion, I would differentiate between Bible thumper and apologists. I strive to be an apologist. But I also see the need to be confrontational from time to time.

    Not all of my best teachers were the coddling type. Some of them were confrontational. They did this just to get the thought processes flowing. It doesn’t work for everyone, but it does work. I know lots over VERY good preachers who do just this.

    As you know, making people better developers is more than TDD. Much more. TDD all by itself wont magically make people better, but TDD alongside better practices often start the process.

    Which leads to one of my personal items: always be improving, always be learning. At no point should you be satisfied with where you are.

  • Jason Walker

    I think it’s pretty obvious I subscribe to the confrontational theory of teaching. One of the reasons I spoke up on Tuesday was to play devil’s advocate – it sounded like everyone else in the room agreed with each other, and nothing gets done in an echo chamber. I like to argue – I don’t see it as a bad thing.

    My comments on “religion” in this industry has more to do with … leadership style. Tony is really good at coming up with existing names for the ideas that I have, and has told me that what I’m trying to convey is known as “Falling into the pit of success.” I’ve always found that if you want someone to do something, the best thing is to make it easy for them. I don’t consider it coddling, but rather subtle coercion.

  • Pingback: Arjan`s World » LINKBLOG for September 13, 2008

  • Pingback: Reflective Perspective - Chris Alcock » The ‘Morning’ Brew #179