tags:

views:

448

answers:

10

I understand that programming to interfaces helps with loose coupling. However, is there a guideline that explains when its most effective?

For example, I have a simple web application that collects data on employees, their training plans, expenses and computes their expense for the year etc. This is a fairly simple application and I can of course use an interface but wonder if there would be any use. I will be using it for the sake of using it.

It can always be argued that as the application grows in complexity and I pass around objects it would make more sense to pass the type (interface) than an implementation. So, should I wait for the application to become complex or use it right away? I'm wondering the best practice might turn out to be "this guy is over doing things".

+7  A: 

The reason to program to an interface is to insulate higher-level classes from changes in lower-level classes. If you don't anticipate a lower-level class to change at all, then it's reasonable not to program to an interface in that case. This article (PDF) elaborates on the idea, coining the term the Dependency-Inversion Principle.

namin
Thanks. It looks similar to DI of Spring.
Shaw
+3  A: 

If there is a good chance the app will become more complex it's easier to set up the scaffolding earlier rather than later. However, if the app is not complex and it's unlikely it won't become complex the ROI may not be there. You can always refactor later.

rich
Exactly. I can set up the scaffolding part to avoid unnecessary work later. But, will it be called a bad practice - owing to over use or poor application of a good practice?
Shaw
I think it is a judgment call based on what you're implementing. One example of where I would say to always program to interfaces is when creating a DAO layer since interfaces will lend to using different data sources and creating mock data for unit testing.
rich
+1  A: 

You have to see an interface as a contract. This contract defines the set of rules and operations that need to be fulfilled by those who signed this contract, no matter how it gets done.

Trap
+3  A: 

A simple example that opened my eyes for Interfaces is this

class SimpleClass
{
  public int A { get; set; }
  public int B { get; set; }
  public int C { get; set; }
}

List<SimpleClass> Calc(IEnumerable<SimpleClass> list)
{
  foreach(SimpleClass item in list)
  {
     item.C = item.A * item.C:
  }
  return list.ToList();
}

Notice the IEnumerable input parameter. By using this I can pass in any collection that implements IEnumerable as the in parameter. List<SimpleClass>, SimpleClass[], Collection<SimpleClass>.

The IEnumerable interface guarantees me that I can use the foreach loop and this way I have made my function a bit more generic and there will be less chance that I have to change this code since the chance that IEnumerable changes is less that f.ex. List changes.

TT
I'm aware of the benefits with built-in types and always try to use them. But, I'm not sure about custom types -- specifically my question was with it. Thanks for your answer and code :)
Shaw
The principle for why using interfaces is as valid for you as for the developers of the .net libraries, so if you understand why they were using them you would understand why and where you should use them. Of course a framework will benefit a lot more from interfaces.
TT
+3  A: 

Programming to an interface in a simple application where you don't plan on swapping implementations may seem like overkill.

The second you get into Unit Testing you will be very happy to have programed towards interfaces because it gives you the ability to more easily mock out the real object with test doubles.

Tigraine
Very true. I have often heard the statement: "Never use an interface on something with only one implementation". Well, when you unit test, you create a second implementation of the defendant classes. With a good set of unit tests, you ALWAYS have more than one implementation.
Brian Genisio
+6  A: 

If you ever get yourself interested in Test Driven Development, the need for "programming to an interface" really becomes apparent. If you want a class to be tested in isolation of its dependencies, you need to pass around interfaces instead of objects.

Brian Genisio
This is the primary reason I've avoided test-driven development. On the face of it, TDD is a great idea, but I think the cost is too high, since it requires over-architecture of most application classes.
benjismith
This is where I disagree. My test coverage is so high and my classes are so well decoupled that I am forced to think about good design up front in a very real way. It creates a more modular, extensible architecture which has enough tests behind it to remain robust. I rarely write bugs anymore.
Brian Genisio
+1  A: 

I usually think this way - there are only two things that separate an interface from an implementation:

  1. An object can inherit from many interfaces, but only one base class;
  2. Interfaces do not allow default implementations, while a base class does.

Now think about the objects that will inherit from your "structure". What will be more important to them? Will they benefit most from default implementations of the methods, or will it be better if they can have other base classes?

In most cases it's pretty clear which one is the more important factor. If you happen to be on the thin line inbetween... tough luck. Microsoft recommends base classes over interfaces.

Vilx-
+1  A: 

For anything that is part of an API, whether for external customers or other teams who reuse your code, use interfaces for as much as you possibly can. It's worth it, because it hides as much as possible about how your implementations work and gives you greater freedom to enhance them in the future. Only expose a small concrete (perhaps static) class from which instances can be obtained.

For internal parts of your design, you have the option of starting off with concrete class references everywhere, and only introducing interfaces where it makes sense for the design.

But the other important thing to consider is unit testing. You can fully "mock" an interface in the CLR with no technical difficulty, but mocking other things is either impossible or would require some severe trickery. So one discipline to consider is test driven development: write the tests for your code as you go along, and you'll discover that you need certain things to be expressed by interfaces so you can provide mock versions of them.

Daniel Earwicker
+1  A: 

If you want to be able to test your application and not have to use (and subsequently not have to build up) a full employee object, you have can create the IEmployee interface and then create light-weight test friendly mock employee objects to test with. That can be a big gain if creating an employee is difficult or even impossible to do by hand or without a database.

Another good reason is that it helps you define what exactly you are dependent upon in your employee class. You may have thought that you were only using a few public methods, but then find out later that you were using 10 methods and that they're more tightly coupled than you thought.

Finally, if you need to change your code to use SuperEmployee instead of Employee, if you had been using interfaces all along then all you would need to do is to have SuperEmployee implement IEmployee and you'd be set.

Mike Hall
+1  A: 

Take a browse through the book Head-First Design Patterns... you'll see good arguments for using interfaces that have nothing to do with TDD or polymorphism.

Interfaces allow you to change an object's behavior at runtime... Think of places where you'd need a handler for a particular behavior, but might not know what behavior is needed until runtime. In the case of computing expenses for employees... Managers might have a higher allowance for 'entertainment' expenses than a regular employee.

If your Employee object has a reference to an IExpenseCalculator interface, you can assign it a manager's calculator or an employee's calculator at runtime. Calling Employee.GetExpenses() will give you a differently calculated result for a manager than for a regular employee. Internally, the code would look like this:

public class Employee {
  private IExpenseCalculator expenses;

  public ExpenseSheet GetExpenses() {
    return expenses.CalcExpenses();
  }
}

This example assumes that 'expenses' is exposed as a property, and that IExpenseCalculator has a method for CalcExpenses().

Interfaces are also closely tied to the concept of object factories... think database layer. When you've configured your data layer as a factory, you can create objects to connect to Sql Server, Oracle, or MySql dynamically, at runtime, based on configuration settings. But the client needs a concrete handle to the database layer object... enter Interfaces.

Interfaces are a powerful tool, one that is often misused. Using them properly will take a shift in your way of thinking, but can help your application structure tremendously.

snogfish