The case against Interfaces in TDD

Mark Ploeh has an interesting post about interfaces in TDD – that interfaces aren’t necessarily abstractions. That’s certainly true. Interfaces don’t guarantee we’re actually following SOLID design principles. In fact, the whole idea of the typical repository pattern in a lot of “DDD” codebases just screams of ISP violations.

However, I don’t think any of that changes the value of using interfaces in TDD. Interfaces let me do a few things that are annoying, difficult or impossible with concrete/abstract classes

Do top-down design

Program to implementations that don’t exist

Test against dummy/mock/fake/stub implementations

C# isn’t a dynamic language. I can’t easily swap out behavior at runtime, (or at least, I don’t want to pay for a tool that lets me). Interfaces are the easiest way for me to accomplish my goals in TDD, even if I have the issue of 95% of the interfaces I create only having 1 implementation.

All the points Mark made in his post:

LSP violations

ISP violations

Shallow interfaces

None of these go away when I choose classes. Instead, TDD just becomes harder. Now, I do have a lot more end-to-end, behavioral tests these days as I find these have more value. But interfaces still provide the clearest definition to end users on the needs of the class’s dependencies. Interfaces in the constructor tell us that this class needs an ISomething to accomplish its task, but concrete Something says it needs THIS SPECIFIC Something implementation to do its work.

So no, interfaces aren’t compiler-enforceable contracts, but our usage with proper naming and tests does lead us down this path.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.

Nice post Jimmy. I agree 100% with you and have noticed the recent trend to criticize the use of interfaces in C# as they are used now, often to enable testing (i.e. 1 implementation). However, I have not read one article that proposes a tangible alternative solution that still allows for ease of TDD. C# aint Ruby…..

Hey Jimmy, I’ve been lurking here for a while but not contributed much. I really enjoy your blog. Anyway…

I think, like Roco, that a lot of the debate about this subject centers on the difference between dynamic and static languages. In static languages, Interfaces provide a language supported, well known, low friction means by which to substitute functionality. In a dynamic language (I’m thinking of javascript), this can easily be done by just replacing a function with a new one. There is no reason to define an interface because the contract won’t be enforced anyway. It’s all about deciding which is the better trade off: compile time static analysis or run time flexibility. There may be some way to bring these two paradigms closer together, but I have yet to figure out what it is.

Can you explain your assertion that “TDD just becomes harder” when choosing abstract classes over interfaces? The degree to which it may [or may not] become harder is important. Does laziness or saving time trump good design?

I disagree that interfaces provide the clearest definition of class dependencies to end users. Interfaces only provide member signature requirements. They do not provide validation logic nor do they guarantee how the members work together. Folks believing your assertion is true may be used to designing classes that simply consist of a set of properties but very little interesting behavior (methods). If my classes are simply data buckets that look like database table rows, then interfaces are, indeed, the simplest way to represent this. However, if my classes contain interesting behavior, as I believe classes should, then an abstract class is a better way to not only guarantee a certain contract to calling code but also enforce how the different members of the class interact. Here’s an example of where interfaces are insufficient:

With just INumber, I cannot guarantee to users that the implementation they receive *always* returns the whole and fractional part of the number they pass to SetNumber. I can only guarantee that public or explicit member signatures will exist in any implementation they receive. I could choose to implement INumber like this:

Another benefit of using an abstract class is that it can be easier to enforce immutability. I don’t have to provide a public SetNumber method just to attempt to guarantee to users that there is some way to set the number, or that their implementations should allow setting a number. I have a protected constructor that enforces that for me. Notice I wrote “attempt.” The interface has no way to *force* implementing classes to work this way. I am relying on the names of the interface members and any accompanying documentation to merely *encourage* implementors to follow these rules. Abstract classes *guarantee* the rules are followed.

You’re making a different argument here. You used a strawman of a bad interface to promote abstract classes. But the real argument is that you shouldn’t have poorly designed interfaces. I could use your same argument against abstract classes. This is the “Don’t be stupid” principle — we can be stupid with interfaces just as easily as we can be stupid with abstract classes.

Let’s step back and get to the real argument which is what you said at the end: You want to force behavior on implementers. There are a few places where this might be useful, but usually when people feel the need to do this, as in the case you presented, it’s due to inappropriate abstractions and poor separation of responsibilities.

The example you proposed was bad design in general and that’s why you feel that you *need* an abstract class to get out of it.

I wouldn’t use an interface *or* an abstract class for “Number”, I’d probably use a value type.

I suggest you consider some of Jimmy’s previous blog posts where he has examples of interface usage and TDD and tests and try to explain how an abstract class would be better usage there. If you’re honest about your research, I think you will find that your arguments for abstract classes presented in this blog post, don’t hold water in those other scenarios.

w/r/t to the Ruby and JS arguments, the point there is that, with dynamic languages, you’re essentially binding to interfaces. It’s just that the language makes it much easier for you to do this and handles the minutiae behind the scenes.

The point in any of these languages, static or dynamic, what you *really* want in order to reduce coupling is to say, “I want an object that has a method Bar() on it. I don’t care what object it is as long as it has a Bar() method on it”

Static languages like Boo and now VB/C# with the “dyanmic” allow some degree of late binding like this. In C# without dynamic capabilities, you have to early-bind using the interface to guarantee that whatever object is passed in has a Bar() method. C# requires more effort and ceremony, but the effect is the same: Any object that has a Bar() method.

The key for TDD is to be able to plug in stub/mock objects that have a Bar() method and be able to assert various things on that stub object.

With abstract classes, you’re loading in more baggage and implementation onto that goal by requiring the stub/mock to inherit some implementation baggage instead of just the presence of the Bar() method. This can complicate testing and interfere with the purity of the test because the implementation of the underlying abstract class may change and subtly affect the veracity of the tests which use that abstract class.

@Chad: I agree that this is “Don’t be stupid” — but really, almost everything discussed on here can be boiled down to “Don’t be stupid.”

I think the (admittedly heavy) real question is: How many tests do you want to need to write to reasonably prove your software works?

As a (probably easily criticized) example, say I have a class that wraps a numeric value, but guarantees it is never more than, say 50. Perhaps the constructor throws an exception if the value is more than 50, and the setter makes sure the value is never changed to a value more than 50. Lets call this class FiftyOrLess. An interface for this class might simply have a Value property of type int.

If I declare a class Foo that takes an IFiftyOrLess instead of the concrete described above, the responsible thing to do is to make sure the class can handle any values the interface declares as legal. Because, clearly I could use a mock and that mock would not have the constructor validation in it. Thus, I could break my Foo class if it depends on that promised cap on the numeric value (perhaps it has a fixed-length array of 50 or something). I can only prove that my Foo class works by writing tests that make sure the class appropriately handles cases allowed by the IFiftyOrLess interface.

If I instead take the concrete FiftyOrLess, it is possible to either inspect the class itself or read the comments/documentation for the class to understand the promises it makes. I should be able to skip writing any code to handle cases related to receiving a value greater than 50 in my Foo class. I would also not need to write tests around those scenarios for my consuming class, because the scenario is impossible. I would write tests for the FiftyOrLess class — tests proving it cannot be constructed with or modified to contain a numeric value greater than 50.

Is using an interface for my example class AND not writing code to handle ANY number (and therefore tests to cover that code) at each place of consumption a responsible thing to do?

I guess that depends on how much certainty is enough certainty for you. The interface in this simple case enjoys the luxury of being able to clearly describe the usage expectations — IFiftyOrLess probably should not contain 65. But many real life interfaces may have unreasonably long names should they try to be named with such clarity. There’s nothing Foo can do to make sure noone will implement that IFiftyOrLess and return 65.

I think my personal principle (line in the sand) lies somewhere near “interface for services, concretes for entities.” I’ll take the uncertainty in the cases where the return justifies it — for example a repo that calls out to a database. Using the interface gives me no guarantee that I’ll actually get entities from the retrieval methods, but using the concrete means I must write integration tests every time. Whereas, with domain operations I will use the concrete everytime, and skip having an interface for each of my POCO entity implementations.

What are your thoughts on how the C# 4 dynamic keyword should influence what we’re talking about in this blog?

I think there’s an underlying thread here about whether interfaces are fundamentally for creating a stub boundary or for implementing polymorphism. Your “I just want an object with a Bar() method” is more a case of polymorphism and naturally interfaces are the appropriate thing to do. Contrast that to the example I posted and what Jimmy seems to be alluding to when he says “…even if I have the issue of 95% of the interfaces I create only having 1 implementation”.

“Concrete Something says it needs THIS SPECIFIC Something implementation to do its work.” – no it doesn’t it. It says it needs this specific something OR something that inherits from it.

Aside from the pain of having to mark your properties and methods as virtuals, and having to not access too many statics in your constructor, there’s very very little difference between TDDing with interfaces and classes when you use Moq.

Bill P.

“Aside from the pain of having to mark your properties and methods as virtuals, and having to not access too many statics in your constructor, there’s very very little difference between TDDing with interfaces and classes when you use Moq.”

So you are going to alter the design of all your classes because it works well with a mocking framework, instead of using an interface to represent the functionality? How is that a cleaner solution than ISomeService or ISomeDataRepo?

Both INumber and IFiftyOrLess are bad examples because they imply implementation rules and so aren’t good candidates for interfaces in the first place. A better example may be an IDocumentProducer that has a GetDocuments() method.

RE: Dynamic keyword: I admit I haven’t had a lot of opportunity to play with this in C# yet. I’d probably be tempted to treat it like I would a dynamic language and I’d probably be disappointed by that, but I can’t speak from experience, only speculation at this point.

But the point I was trying to make is that the way I use interfaces is to get the compiler to acknowledge that the passed-in object will have a Bar() method with the correct signature.

I believe Jimmy is of the same or similar mindset here. It is common/normal to have many/most interfaces with only a single implementation. This is because the interface is being used to satisfy the compiler’s requirement of certifying that the passed-in object has the correct method signature for Bar().

I’m not sure if you are agreeing with me, missing my point, or avoiding the discussion.

I was angling towards an entity. I don’t personally back my entities with interfaces except where polymorphism is desired. I get the impression that many folks do, in the name of TDD (or whatever flavor). This is the point I was making. I would argue that entities without implementation rules are just typed data tables.

Substitute your own “good” example if necessary, so long as its not apples to oranges like your IDocumentProducer example, which is a service, not an entity.

@Bill P. I strongly suspect that all the interfaces with one implementation wouldn’t exist if a different testing methodology was used.

The interfaces certainly don’t add flexibility to a system that you wouldn’t get with a class (given that you can always extract an interface when you actually need one).

While we’re talking about the pain of interfaces, its a good time to tangentially pimp Nicolas Dorier’s little-known-but-AWESOME Genuilder project, a pre-processor for msbuild (it’s like PostSharp for source code) that can (amongst other amazing things) magically generate an interface for your classes by marking them up with an attribute.

http://genuilder.codeplex.com/documentation – see the InterfaceExtrator magic. Genuilder blew a few minds at the London ALT.NET conference recently, where we did a code session and wrote an extension to mark all properties as virtual according to a convention.

“I’m not sure if you are agreeing with me, missing my point,…” it appears I was missing your point.

Interfaces on entities is an anti-pattern and part of what I was referring to earlier with people mis-using interfaces.

It seems in most of these discussions I get with people advocating abstract classes, they don’t first understand how to use interfaces properly. The problem is not interfaces vs. abstract classes usually, but rather bad interface usage vs. abstract classes. So abstract classes seems the more reasonable, logical alternative. But in a choice between bad and wrong, wrong seems not as bad.

“The interfaces certainly don’t add flexibility to a system that you wouldn’t get with a class (given that you can always extract an interface when you actually need one).”

First, they do add flexibility because I can pass wildly different impls into a method that takes an interface in its signature vs. a class which forces me to either pass in that class or pass in an inherited class (if the base class even allows inheritance). Interfaces allow for composition scenarios in ways that classes don’t or only allow awkwardly.

Second, “you can always extract an interface” — that is, until you ship in which case you now have versioning and compatibility problems.

If you are shipping assemblies for public consumption then you REALLY have to think about using interfaces vs assemblies (particularly given that adding a method or property to an interface requires that the consumer implement it, while you can add a property to a base class without forcing your consumer to update their code).

If you aren’t exposing the code to a third party (most of the lines of code I suspect most people write) then versioning etc. isn’t a concern – when I need the flexibility to pass in different unrelated implementations I extract an interface – not before (YAGNI).

Writing a class instantly requires many decisions that interfaces defer:

Does the concept call for imposing inheritance?
Do I make a reference or value type?
Do I make the class abstract? Do I seal it?
Do I make its members abstract? Virtual?
Do I specify hierarchy-wide implementation details?
How will derived classes use and override these rules?
What state will each instance store? What state is static?
What problem was I solving again?

When we identify the need for a new type, we really uncover a dependency on some set of operations which is best left to another component. Choosing to model those newly-discovered capabilities with a class or struct places the emphasis square on the implementation. It’s tempting to delve in and switch contexts.

Decoupled design is about isolation, and nothing isolates a dependency with fewer decisions and assumptions than an interface. They are a low-friction way to identify work for later while keeping the focus on the current problem.

In that respect, I call reverse YAGNI on @Harry M

(I should qualify this by saying that I don’t use entity interfaces. Abstraction in the model should only occur if it exists in the domain.)

Robert

The title of your article doesn’t match your articles. I want my five minutes back.

Ads

About Me

I'm the chief architect at Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.