Shaw
Shaw

Reputation: 1494

Programming to an interface. How to decide where its needed?

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".

Upvotes: 11

Views: 831

Answers (10)

Daniel Earwicker
Daniel Earwicker

Reputation: 116674

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.

Upvotes: 1

snogfish
snogfish

Reputation: 71

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.

Upvotes: 1

Mike Hall
Mike Hall

Reputation: 1151

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.

Upvotes: 1

Vilx-
Vilx-

Reputation: 106920

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.

Upvotes: 1

Brian Genisio
Brian Genisio

Reputation: 48137

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.

Upvotes: 7

Tigraine
Tigraine

Reputation: 23648

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.

Upvotes: 3

terjetyl
terjetyl

Reputation: 9565

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.

Upvotes: 4

Trap
Trap

Reputation: 12372

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.

Upvotes: 1

rich
rich

Reputation: 987

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.

Upvotes: 3

namin
namin

Reputation: 38179

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.

Upvotes: 7

Related Questions