views:

252

answers:

6

Should you always create an interface if there's a possibility that there might be something else that could use it, or wait until there's an actual need for it then refactor to use an interface?

Programming to an interface generally seems like sound advice, but then there's YAGNI...

I guess maybe it depends on the situation. Right now I have an object representing a folder that can contain recipes or other folders. Instead of using Folder directly, should I worry about implementing something like IContainer? In case in the future I want to have a recipe that refers to other sub recipes (say an apple pie recipe that is also a container for a pie crust recipe)

+5  A: 

It always depends on the situation. If you KNOW there is going to be another class using the interface, then yes, create the interface class to save time later. However, if you are not sure (and most of the time you aren't) then wait till you need it.

Now that doesn't mean to ignore the possibility of the interface - think about the object's public methods and such with an eye toward making an interface later, but don't clutter your codebase with anything that you don't actually NEED.

Michael Kohne
YAGNI, you aren't going (to) need it -> you ain't gonna need it
Robert Gould
Precisely. Every time I've ever put in interfaces or whatever 'just in case' they turned out to needed exactly never. But your mileage may vary.
Michael Kohne
+2  A: 

I would say it depends more on how many places you're going to use the class, and less on how many classes might possibly implement the interface. If you're only using Folder in one or two places then I would say wait until there's an actual need for the interface before you implement it and refactor. However, if Folder is going to be used in 100 different places, then you can save some time by programming to an interface up front.

Bill the Lizard
+3  A: 

There will be always a test that use it, right (you do unit tests, don't you?). Which means it's always N + 1 classes that use it, where N is number of classes that use your class in application.

Another purpose of interface besides dependency injection is separation of concern so that your class may actually implement multiple interfaces.

Keep all of that in mind but you can always have interface(s) introduced later via refactoring if not implemented in the beginning.

grigory
What if the class is simple enough that a mock object isn't needed for unit testing (i.e. it's simple enough to just use a real object)?
Davy8
I never said anything about mock objects, didn't I :-) ? All I say that number of classes that use it is always + 1 (test). And I agree that interfaces can be introduced later by simple refactoring.
grigory
Ah, I misread, "uses" not "implements"
Davy8
+1: Dependency Injection is definitely a driver to use an interface.
Richard
+1  A: 

Generally, you shouldn't bother with creating an interface if only one class is going to implement it, even if you anticipate a possible class for it since there may be implementation issues that won't come up until the class is actually tested in a scenario, in which case a prematurely created interface may have too many memebrs or may be missing a member.

For example, the .NET Framework Bas Class Library team has admitted to prematurely designing ICollection when it included a SyncRoot property. For the later generic ICollection<T> they decided to remove it (http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx).

If you are going to create a mock object implementing the same interface then that waould count as a second implementation that justifies creating the inteface. Not all unit tests warrant a mock-style interface, though.

Mark Cidade
+2  A: 

Think of an interface as a contract to define semantics, or a concept. That's a general approach and not really language specific. In context of OO, if you are working in a single inheritance model, there is an excellent case to be made for preferring interfaces over classes for defining your object model, since that single super class pathway is fairly precious and you want to save it for something more 'substantial' than defining properties that are exposed on an object, or methods.

To have IContainer semantics (contract) is a fairly poor reason to make an interface out of your folder; better to have your folder (if it is doing any non-trivial logic) 'implement' the (likely already existing) IContainer or ICollection interface in your language's core frameworks.

As always, the better choice is fairly dependent on the specific problem. In case of your recipes that are also folders (?!) you are probably thinking of a parent-child, or composition, relationship -- a semantic that can (and should) be expressed using interfaces if you will have other elements in your system 'operate' on things that are composed using that sort of semantics.

There is a bit of overhead (programming wise) with interfaces, and, if you find yourself when you are done with nothing more than a set of Woof and IWoof classes and interfaces, then you'll know you probably didn't need to express your problem in terms of interfaces -- simple classes would have been sufficient.

As a rule, for any I, you should have at least a couple of concrete classes (with more meaningful names other than IImpl, or ).

Hope that helps.

This thing ate my angled brackets: for any Ixxx ... names other than IxxxImpl, or XXX.
+1  A: 

A lot of the people have already outlined very sound advice. One thing I'd like to add is that if you are looking to avoid direct hard dependencies on concrete classes then interfaces will help by providing loose coupling. If you are creating a plug-in based architecture then interfaces are definitely the way to go. Also, if you are planning to write unit tests either side by side or later down the line, you will probably notice that code which calls into your folder class(es) will have to carry around a concrete implementation for the calling code to be testable. If your concrete implementation of the folder class(es) is in turn talking to a DB or a service then you will need to have that carried over into your tests as well which will get unwieldy very quickly. Just my 2 cents.

Abhijeet Patel