views:

534

answers:

14

I keep hearing the statement on most programming related sites:

Program to an interface and not to an Implementation

However I don't understand the implications?
Examples would help.

EDIT: I have received a lot of good answers even so could you'll supplement it with some snippets of code for a better understanding of the subject. Thanks!

+2  A: 

An interface is like a contract between you and the person who made the interface that your code will carry out what they request. Furthermore, you want to code things in such a way that your solution can solve the problem many times over. Think code re-use. When you are coding to an implementation, you are thinking purely of the instance of a problem that you are trying to solve. So when under this influence, your solutions will be less generic and more focused. That will make writing a general solution that abides by an interface much more challenging.

Kyle Walsh
This answer is neither a statement for or against this methodology, FYI.
Kyle Walsh
+3  A: 

It's a way to separate responsibilities / dependancies between modules. By defining a particular Interface (an API), you ensure that the modules on either side of the interface won't "bother" one another.

For example, say module 1 will take care of displaying bank account info for a particular user, and module2 will fetch bank account info from "whatever" back-end is used.

By defining a few types and functions, along with the associated parameters, for example a structure defining a bank transaction, and a few methods (functions) like GetLastTransactions(AccountNumber, NbTransactionsWanted, ArrayToReturnTheseRec) and GetBalance(AccountNumer), the Module1 will be able to get the needed info, and not worry about how this info is stored or calculated or whatever. Conversely, the Module2 will just respond to the methods call by providing the info as per the defined interface, but won't worry about where this info is to be displayed, printed or whatever...

When a module is changed, the implementation of the interface may vary, but as long as the interface remains the same, the modules using the API may at worst need to be recompiled/rebuilt, but they do not need to have their logic modified in anyway.

That's the idea of an API.

mjv
A: 

Essentially, interfaces are the slightly more concrete representation of general concepts of interoperation - they provide the specification for what all the various options you might care to "plug in" for a particular function should do similarly so that code which uses them won't be dependent on one particular option.

For instance, many DB libraries act as interfaces in that they can operate with many different actual DBs (MSSQL, MySQL, PostgreSQL, SQLite, etc.) without the code that uses the DB library having to change at all.

Overall, it allows you to create code that's more flexible - giving your clients more options on how they use it, and also potentially allowing you to more easily reuse code in multiple places instead of having to write new specialized code.

Amber
+3  A: 

At its core, this statement is really about dependencies. If I code my class Foo to an implementation (Bar instead of IBar) then Foo is now dependent on Bar. But if I code my class Foo to an interface (IBar instead of Bar) then the implementation can vary and Foo is no longer dependent on a specific implementation. This approach gives a flexible, loosely-coupled code base that is more easily reused, refactored and unit tested.

Jason
@Downvoter: What?
Jason
A: 

By programming to an interface, you are more likely to apply the low coupling / high cohesion principle. By programming to an interface, you can easily switch the implementation of that interface (the specific class).

Frederik Gheysels
+18  A: 

You are probably looking for something like this:

public static void main(String... args) {
  // do this - declare the variable to be of type Set, which is an interface
  Set buddies = new HashSet();

  // don't do this - you declare the variable to have a fixed type
  HashSet buddies2 = new HashSet();
}

Why is it considered good to do it the first way? Let's say later on you decide you need to use a different data structure, say a LinkedHashSet, in order to take advantage of the LinkedHashSet's functionality. The code has to be changed like so:

public static void main(String... args) {
  // do this - declare the variable to be of type Set, which is an interface
  Set buddies = new LinkedHashSet();  // <- change the constructor call

  // don't do this - you declare the variable to have a fixed type
  // this you have to change both the variable type and the constructor call
  // HashSet buddies2 = new HashSet();  // old version
  LinkedHashSet buddies2 = new LinkedHashSet();
 }

This doesn't seem so bad, right? But what if you wrote getters the same way?

public HashSet getBuddies() {
  return buddies;
}

This would have to be changed, too!

public LinkedHashSet getBuddies() {
  return buddies;
}

Hopefully you see, even with a small program like this you have far-reaching implications on what you declare the type of the variable to be. With objects going back and forth so much it definitely helps make the program easier to code and maintain if you just rely on a variable being declared as an interface, not as a specific implementation of that interface (in this case, declare it to be a Set, not a LinkedHashSet or whatever). It can be just this:

public Set getBuddies() {
  return buddies;
}

There's another benefit too, in that (well at least for me) the difference helps me design a program better. But hopefully my examples give you some idea... hope it helps.

weiji
Wow! That's very well explained!
Kevin Boyd
Thanks! Glad I could help :)
weiji
Just keep in mind that this principle goes for types that you create as well as built-in abstractions like Set. For example, if you have a "Foo" in your project. Don't just make a "class Foo," instead make "interface Foo" and then have some implementation like "class MyFoo implements Foo" You might even find that your project will have several classes that implement the "Foo" interface. By consistently writing the name of the interface instead of the implementation (except for constructor invocations) you can quickly change Foo implementations to fit your needs.
Greg Mattes
Be very careful about OVERusing this principle for you code. If every class has a corresponding interface that gets defined and there's always a 1-to-1 correspondence between thes classes and interfaces, then it just serves to obfuscate the code and make it harder to maintain. Knowing WHEN to introduce interfaces because you might in the future want to introduce a different implementation is key.
Chris Dodd
I really don't like this standard example about declaring local variables. It's a very weak case for interfaces. Method parameters are a much stronger case - declare a HashSet parameter, and you force clients to use a HashSet. Declare a Set parameter, and they're free to use Collections.singleton(), Collections.emptySet(), or their own custom Set implementation.
Michael Borgwardt
Michael - You're right, method parameters would make a better example. However, I purposely wanted to give something very simple for the questioner. I start with constructors and move to return types; it would just be another small step to illustrate parameters. I sort of thought he would be able to make that connection himself and so left it out due to brevity.
weiji
In Swing it is common for interfaces to have an Adapter providing a dummy implementation. It is then easy to extend the adapter to override a single method instead of providing a full set of dummy methods everytime. Very nice for anonymous functions.
Thorbjørn Ravn Andersen
+1 for simple, concrete programming example
Thorbjørn Ravn Andersen
+1  A: 

Take a red 2x4 Lego block and attach it to a blue 2x4 Lego block so one sits atop the other. Now remove the blue block and replace it with a yellow 2x4 Lego block. Notice that the red block did not have to change even though the "implementation" of the attached block varied.

Now go get some other kind of block that does not share the Lego "interface". Try to attach it to the red 2x4 Lego. To make this happen, you will need to change either the Lego or the other block, perhaps by cutting away some plastic or adding new plastic or glue. Notice that by varying the "implementation" you are forced to change it or the client.

Being able to let implementations vary without changing the client or the server - that is what it means to program to interfaces.

SingleShot
+1 for use of Lego in an analogy
Smalltown2000
A: 

It means that your variables, properties, parameters and return types should have an interface type instead of a concrete implementation.

Which means you use IEnumerable<T> Foo(IList mylist) instead of ArrayList Foo(ArrayList myList) for example.

Use the implementation only when constructing the object:

IList list = new ArrayList();

If you have done this you can later change the object type maybe you want to use LinkedList instead of ArrayList later on, this is no problem since everywhere else you refer to it as just "IList"

codymanix
+4  A: 

My initial read of that statement is very different than any answer I've read yet. I agree with all the people that say using interface types for your method params, etc are very important, but that's not what this statement means to me.

My take is that it's telling you to write code that only depends on what the interface (in this case, I'm using "interface" to mean exposed methods of either a class or interface type) you're using says it does in the documentation. This is the opposite of writing code that depends on the implementation details of the functions you're calling. You should treat all function calls as black boxes (you can make exceptions to this if both functions are methods of the same class, but ideally it is maintained at all times).

Example: suppose there is a Screen class that has Draw(image) and Clear() methods on it. The documentation says something like "the draw method draws the specified image on the screen" and "the clear method clears the screen". If you wanted to display images sequentially, the correct way to do so would be to repeatedly call Clear() followed by Draw(). That would be coding to the interface. If you're coding to the implementation, you might do something like only calling the Draw() method because you know from looking at the implementation of Draw() that it internally calls Clear() before doing any drawing. This is bad because you're now dependent on implementation details that you can't know from looking at the exposed interface.

I look forward to seeing if anyone else shares this interpretation of the phrase in the OP's question, or if I'm entirely off base...

rmeador
That's my understanding too - programming to an interface means to program to the documentation, the specification, or the protocol. So if you're programming to an interface, a discussion about "does X work" isn't "I tried it and it works/doesn't work", it's more along the lines of "I read the documentation, and it permits X/forbids X/doesn't mention X/is ambiguous about X".
d__
+1  A: 

In addition to the other answers, I add more:

You program to an interface because it's easier to handle. The interface encapsulates the behavior of the underlying class. This way, the class is a blackbox. Your whole real life is programming to an interface. When you use a tv, a car, a stereo, you are acting on its interface, not on its implementation details, and you assume that if implementation changes (e.g. diesel engine or gas) the interface remains the same. Programming to an interface allows you to preserve your behavior when non-disruptive details are changed, optimized, or fixed. This simplifies also the task of documenting, learning, and using.

Also, programming to an interface allows you to delineate what is the behavior of your code before even writing it. You expect a class to do something. You can test this something even before you write the actual code that does it. When your interface is clean and done, and you like interacting with it, you can write the actual code that does things.

Stefano Borini
As an example I had seen a class which had several private methods, and a couple of public methods which were internally calling these private methods. In this case we are exposing only a subset of the API. Is this good programming practice?
Kevin Boyd
+3  A: 

An interface defines the methods an object is commited to respond.

When you code to the interface, you can change the underlying object and your code will still work ( because your code is agnostic of WHO do perform the job or HOW the job is performed ) You gain flexibility this way.

When you code to a particular implementation, if you need to change the underlying object your code will most likely break, because the new object may not respond to the same methods.

So to put a clear example:

If you need to hold a number of objects you might have decided to use a Vector.

If you need to access the first object of the Vector you could write:

 Vector items = new Vector(); 
 // fill it 
 Object first = items.firstElement();

So far so good.

Later you decided that because for "some" reason you need to change the implementation ( let's say the Vector creates a bottleneck due to excessive synchronization)

You realize you need to use an ArrayList instad.

Well, you code will break ...

ArrayList items = new ArrayList();
// fill it  
Object first = items.firstElement(); // compile time error.

You can't. This line and all those line who use the firstElement() method would break.

If you need specific behavior and you definitely need this method, it might be ok ( although you won't be able to change the implementation ) But if what you need is to simply retrieve the first element ( that is , there is nothing special with the Vector other that it has the firstElement() method ) then using the interface rather than the implementation would give you the flexibility to change.

 List items = new Vector();
 // fill it 
 Object first = items.get( 0 ); //

In this form you are not coding to the get method of Vector, but to the get method of List.

It does not matter how do the underlying object performs the method, as long as it respond to the contract of "get the 0th element of the collection"

This way you may later change it to any other implementation:

 List items = new ArrayList(); // Or LinkedList or any other who implements List
 // fill it 
 Object first = items.get( 0 ); // Doesn't break

This sample might look naive, but is the base on which OO technology is based ( even on those language which are not statically typed like Python, Ruby, Smalltalk, Objective-C etc )

A more complex example is the way JDBC works. You can change the driver, but most of your call will work the same way. For instance you could use the standard driver for oracle databases or you could use one more sophisticated like the ones Weblogic or Webpshere provide . Of course it isn't magical you still have to test your product before, but at least you don't have stuff like:

 statement.executeOracle9iSomething();

vs

statement.executeOracle11gSomething();

Something similar happens with Java Swing.

Additional reading:

Design Principles from Design Patterns

Effective Java Item: Refer to objects by their interfaces

( Buying this book the one of the best things you could do in life - and read if of course - )

OscarRyz
Fantastic! The books seem amazing too! Regarding the code, we have changed a line of code in the program from List items = new Vector();to List items = new ArrayList(); so eventually we had to change some code in the client area so might as well change the remaining lines of code related to Vector that are going to break. I still dont understand the significance.
Kevin Boyd
It sounds like you have code which is expecting to use a Vector, which is exactly what is meant by "programming to an implementation". Your other code now expects to use Vector. If, instead, you had your code expect the data structure to be a List (in other words, you declared items to be a List, so don't treat it like a specific subclass of List, and you thus "program to an interface"), then your other code wouldn't need modification later when you change the actual type by changing "new Vector()" to "new ArrayList()".
weiji
+7  A: 

One day, a junior programmer was instructed by his boss to write an application to analyze business data and condense it all in pretty reports with metrics, graphs and all that stuff. The boss gave him an XML file with the remark "here's some example business data".

The programmer started coding. A few weeks later he felt that the metrics and graphs and stuff were pretty enough to satisfy the boss, and he presented his work. "That's great" said the boss, "but can it also show business data from this SQL database we have?".

The programmer went back to coding. There was code for reading business data from XML sprinkled throughout his application. He rewrote all those snippets, wrapping them with an "if" condition:

if (dataType == "XML")
{
   ... read a piece of XML data ...
}
else
{
   .. query something from the SQL database ...
}

When presented with the new iteration of the software, the boss replied: "That's great, but can it also report on business data from this web service?" Remembering all those tedious if statements he would have to rewrite AGAIN, the programmer became enraged. "First xml, then SQL, now web services! What is the REAL source of business data?"

The boss replied: "Anything that can provide it"

At that moment, the programmer was enlightened.

Wim Coenen
Wonderful!.. Surely written by an Enlightened person!
Kevin Boyd
Er!..But could you enlighten me!...What did the programmer do?
Kevin Boyd
He realized he could make most code agnostic about the type of data source by programming against a single abstraction of the data source; an interface! Adding support for new data source types then becomes a matter of creating a new implementation of the interface. The rest of the code doesn't have to be touched. This is the **data mapper** pattern.
Wim Coenen
+2  A: 

Look, I didn't realize this was for Java, and my code is based on C#, but I believe it provides the point.

Every car have doors.

But not every door act the same, like in UK the taxi doors are backwards. One universal fact is that they "Open" and "Close".

interface IDoor
{
 void Open();
 void Close();
}

class BackwardDoor : IDoor
{
 public void Open()
 {
    // code to make the door open the "wrong way".
 }

 public void Close()
 {
    // code to make the door close properly.
 }
}

class RegularDoor : IDoor
{
 public void Open()
 {
  // code to make the door open the "proper way"
 }

 public void Close()
 {
  // code to make the door close properly.
 }
}

class RedUkTaxiDoor : BackwardDoor
{
 public Color Color
 {
  get
  {
   return Color.Red;
  }
 }
}

If you are a car door repairer, you dont care how the door looks, or if it opens one way or the other way. Your only requirement is that the door acts like a door, such as IDoor.

class DoorRepairer
{
 public void Repair(IDoor door)
 {
  door.Open();
  // Do stuff inside the car.
  door.Close();
 }
}

The Repairer can handle RedUkTaxiDoor, RegularDoor and BackwardDoor. And any other type of doors, such as truck doors, limousine doors.

DoorRepairer repairer = new DoorRepairer();

repairer.Repair( new RegularDoor() );
repairer.Repair( new BackwardDoor() );
repairer.Repair( new RedUkTaxiDoor() );

Apply this for lists, you have LinkedList, Stack, Queue, the normal List, and if you want your own, MyList. They all implement the IList interface, which requires them to implement Add and Remove. So if your class add or remove items in any given list...

class ListAdder
{
 public void PopulateWithSomething(IList list)
 {
   list.Add("one");
   list.Add("two");
 }
}

Stack stack = new Stack();
Queue queue = new Queue();

ListAdder la = new ListAdder()
la.PopulateWithSomething(stack);
la.PopulateWithSomething(queue);
CS
No problem! regarding the language Java or C# as long as we get the understanding. Thanks!
Kevin Boyd
In Java the convention is to use Door and not IDoor for the interface.
Thorbjørn Ravn Andersen
+1  A: 

Allen Holub wrote a great article for JavaWorld in 2003 on this topic called Why extends is evil. His take on the "program to the interface" statement, as you can gather from his title, is that you should happily implement interfaces, but very rarely use the extends keyword to subclass. He points to, among other things, what is known as the fragile base-class problem. From Wikipedia:

a fundamental architectural problem of object-oriented programming systems where base classes (superclasses) are considered "fragile" because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class.

akf