views:

373

answers:

13

This is in response to certain comments made by Zed Shaw in his blog a long while ago.

The experts will then saunter off to implement their Flaming Tower of Babel without any comments, horribly complex mock enabled tests, making sure EVERY SINGLE CLASS HAS AN INTERFACE, and ending every class with “Impl” because, well, that’s the best practice.

I use Spring and Google Guice in equal measures and I've noticed that these frameworks do use the Impl postfix but sparingly. In my code, I use interfaces everywhere because I've been told that it makes it easier to mock etc. Do I have a naive understanding of the issue ? (Perhaps mock frameworks can work with abstract classes or classes, I don't know. I have never tried) For my concrete implementations, I have chosen the Spring convention of prefixing the name of the implementation with the word Default.

e.g. BottleOpener (interface) is implemented by DefaultBottleOpener (class)

What is the best practice on this issue ?

UPDATE1 I find it useful to return an interface from a method because I can always return an anonymous class.

+4  A: 

The best practice is to:

  • Pick a convention and be consistent about it; and
  • Don't go overboard with making everything implement an interface.
cletus
+12  A: 

It's more than just mocks. In the case of Spring, it's about dynamic proxies and aspect-oriented programming. That's how Spring does transactions, remoting, and aspects of all types.

I use interfaces for repositories, services, and the like, but I don't put interfaces on model objects or anything else whose implementation isn't likely to change.

Interfaces separate APIs from how they're implemented. If your implementation doesn't change, an interface doesn't make much sense.

Zed Shaw is a terrific writer and developer, but take what he says with a grain of salt. I think some of the over the top hyperbole that he indulges in is for entertainment value. He's got a point ("Don't do things just because somebody who claims to be an authority tells you it's a 'best practice'"), but the way he's saying it is part theater.

duffymo
A simpler way to think of this might be: interfaces for logic, no need for interfaces for data
matt b
@matt b - I like it. Pithy phrasing, easy to remember.
duffymo
+1 for the service vs. model objects. In a distributed environment this is a must otherwise you effectively give the green light to developers creating their own model object implementations, that no receiver will understand or deserialize.
Robin
+1  A: 

Well I 'heard' that in SmallTalk, you always start defining interfaces before the actual implementation... So I guess, it really depends on the purpose and the design objective the you want to achieve...

ultrajohn
I agree with that advice, by the way. If you design the interface from the POV of the consumer of it, you end up with better interfaces.
kyoryu
+2  A: 

This is largely a subjective matter. The best response is probably due what you can to enable as much unit testing of your code as possible but don't let interface creation get in the way of getting things done. If you code is quickly getting swamped trim it down.

That said, I've seen code where there are 400 classes and 400+ interfaces for those classes. Just digging through the pile of code with its poor naming conventions was enough to give me the willies. On the flip side I'm dealing with a third-party proprietary library with no interfaces. Mocking these objects is getting to be a pain.

wheaties
A: 

Going overboard on interfaces is a very real possibility. Ignoring the [neglible] performance penalty of making every method call using virtual dispatch it also introduces more options into the system. It can actually make it harder to debug and secure the software. If your method/function accepts any old interface implementor you've made a decision to accept that the implementor may have implemented the interface wrong or perhaps even maliciously. How your program/library/framework allows variation is an important part of the design process.

Robert Davis
A: 

Giving everything an interface (or more generally designing for flexibility that will probably go unused) is called overengineering. If you're likely never going to have more than one concrete implementation of something, an interface is just bloat. Code that avoids building in unused flexibility is easier to understand, because without the interface obscuring the fact that you only have one implementation, you know what concrete type you're dealing with and the code is easier to reason about.

This is also one of my favorite arguments against mocking: It introduces artificial requirements into your code, such as being able to have more than one implementation of things that you will only ever have one "real" implementation of.

dsimcha
+2  A: 

Having interfaces on objects, and having objects only talk to each other through interfaces, is a good thing.

Note that I do mean objects, and not collections or other things that are essentially 'data'.

However, having a class implement 'IClassName' or similar, and having that pattern throughout a codebase reflects a poor understanding of the concepts of an interface. Interfaces should generally be declared by the consuming class, as a declaration of 'hey, here's the services I need.' In that way, an interface represents the interactions between two objects, not a single view of the object to the world. It also helps keep responsibilities separate, as each class is dealing with its own ideal interfaces, and so can help keep domain logic separate from implementation logic.

(edit)

It's really about the difference between indirection, and abstraction. An interface that matches your API directly is simply indirection. An interface that matches the needs of the consumer directly is an abstraction, as it declares what the consumer wants done, and hides all information of how it is done.

Zed Shaw has a good article on this.

http://www.zedshaw.com/essays/indirection_is_not_abstraction.html

kyoryu
+2  A: 

I don’t think that you can go really wrong by hiding all your concrete classes behind interfaces.

There are cases where it’s superfluous, but it doesn’t cost you much.

One can even make a case for making Domain Objects implement interfaces. Benefits:

  • You can hide the ugly details from the client code (e.g. JPA annotations, setters to be used by the ORM framework only)
  • Just like with DAOs or Services, you can program against abstractions. Think of a User abstraction – your business logic does not depend on how and where they are stored (e.g. DB or OS), and you can easily use an Adapter pattern if you have to work with third-party code.
Francois
+1  A: 

I think it depends on your design. If you want to use dependency injection or mock object testing, then interfaces make sense. Also, if you plan on having multiple implementations, then interfaces are definitely required to state the contract for the behavior.

When in doubt, perhaps take the agile approach?

Just need a beer bottle opener

class BeerBottleOpener // life's good

Now need a wine bottle opener

class WineBottleOpener // life's still good

Refactor a little

interface BottleOpener;
class BeerBottleOpener implements BottleOpener;
class WineBottleOpener implements BottleOpener;
// now living the life!  ;-)

Btw, for mock testing, I've used EasyMock which requires interfaces. Now switched to Mockito which can mock classes and is more explicit and slightly simpler.

marklai
I might switch to Mockito soon
Jacques René Mesrine
EasyMock supports classes just fine, thanks to its ClassExtension library. http://easymock.org/EasyMock2_5_2_ClassExtension_Documentation.html
CaptainAwesomePants
I actually somewhat disagree with this approach. I prefer to use interfaces for abstraction, rather than generalization. The 'BottleOpener' interface is of minimal use in your example, as you still need the right bottle opener for the right type of bottle. They're not interchangeable in any way. Also, I prefer to think of interfaces as a declaration of the services the consumer needs, rather than the ultimate generalization of a specific instance.
kyoryu
+1  A: 

I don't see any advantage to creating an interface for every class. That just forces you to write a bunch of code twice.

I don't see a need to create an interface to distinguish an API from an implementation. The list of public functions of a class with their signatures is the API. If the class requires worker-bee functions that are not part of the API, then they shouldn't be public. I don't see that

I create an interface when, in the given context, it serves a useful purpose. Basically this means:

(a) In practice, my most common reason is to implement/simulate multiple inheritance. If I need A extends B but I also need to have a function that accepts a C and I want to pass A to that function, then I must make either B or C an interface rather than a parent class and make it A extends B implements C or vice versa.

(b) When I am creating an API for a library or utility function that will be implemented by something outside that library or utility, usually by multiple somethings. The "Comparable" interface in the Java library would be an example of this. A sort utility needs a function to compare a pair of objects. When a program calls the sort utility with objects defined in the calling program, the sort utility can't be expected to know how to compare them, so the calling program must provide a compare function. The signature for the compare function logically goes in an Interface that the caller can implement for its objects.

(c) If I want to publish an interface without revealing the implementation. This might be for proprietary reasons, but in practice it's usually because another person or team will implement the interface.

Jay
+1  A: 

Any class that provides a 'service' to another collaborator should have an interface - you would potentially want to chop and change implementations to achieve the desired behavior. As an example you could replace a twitter service with an email service easily.

Any class that represents a 'value' object should not need an interface as it serves a single purpose. In testing you would not even need to mock these objects, just used them directly as they define leaf nodes of your object graph.

gpampara
Agreed on the value objects! Having an interface on a value object is almost always overkill.I'd say your first paragraph differently, though. While I agree that every consumer should talk to their service through an interface, I think it's more important that the consumer talk through an interface *that they define*. To use your example, it would be rather difficult to replace an interface that was derived from an email implementation with one that talked to twitter. However, an interface defined by the consumer that had something like 'SendMessage' would be able to be easily swapped.
kyoryu
+4  A: 

The book Interface Oriented Design has a helpful way of thinking about interfaces - that they belong to the client, not the provider. So rather than thinking about whether a given class should be represented by an interface, think about what interfaces a given class might want to interact with, then find or write classes that conform to those interfaces. An interface may be very pared-down, compared to a longer list of public features in an implementing class - and of course a given class can implement several interfaces. Looking for a one-to-one correspondence between classes and interfaces, even thinking about interfaces as representations of full classes, isn't as useful a way of thinking about interfaces.

Carl Manaster
I've called this "Ideal Environment Development" - write your classes as if they existed in their ideal environment.
kyoryu
A: 

Doing anything to the point of obsession is wrong. These are just tools, we are the masters.

EJP