~/src/www.mokhan.ca/xlgmokha [main]
cat interface-based-programming.md
interface-based-programming.md 7797 bytes | 2007-05-22 00:00
symlink: /opt/dotnet/interface-based-programming.md

Interface Based Programming

“By using the interface, I allow myself the advantage of making it easier to change implementations later on if I need to. Another implementation may provide performance improvements, some database interaction features, or other benefits. By programming to the interface rather than to the implementation, I avoid having to change all the code should I need a different implementation… You should always try to program to an interface like this; always use the most general type you can.” Martin Fowler - UML Distilled: A Brief Guide to the Standard Object Modeling Language, Third Edition by Martin Fowler

Let’s take a look at the following code as an example:

  [Test]
  public void GetStudents_ShouldReturnAllStudents() 
  {
    List<Student> students = _store.GetStudents();
    Assert.IsNotNull(students);
    foreach (Student student in students) 
    {
      Console.WriteLine(student.FirstName + student.LastName);
    }
  }

The code above is tightly bound to a specialized type of collection, List<T>. If we crack open Lutz Reflector and take a look at the List<T> type we can see that it implements IList<T> and ICollection<T>.

If we wanted to code to an abstraction, in this case we have two options, IList<T>, ICollection<T>. (For the above test it would probably be best to use IEnumerable<T>, but let’s assume we need to add items to the collection in client code.)

If we take a look at IList<T>

As you can see IList<T> implements ICollection<T>. ICollection<T> does not implement IList<T>, it would be safe to say that ICollection<T> is the most generalized form of List<T> or IList<T>, which gives us the greatest flexibility to change the underlying implementation of GetStudents() in the future.

The final code looks more like this:

  [Test]
  public void GetStudents_ShouldReturnAllStudents()
  {
    ICollection<Student> students = _store.GetStudents();
    Assert.IsNotNull(students);
    foreach(Student student in students)
    {
      Console.WriteLine(student.FirstName + student.LastName);
    }
  }

As a side note, for this particular contrived example since ICollection<T> also implements IEnumerable<T> the above can be re-written as follows (without any changes to the implementation of GetStudents())

  [Test]
  public void GetStudents_ShouldReturnAllStudents()
  {
    IEnumerable <Student> students = _store.GetStudents();
    Assert.IsNotNull(students);
    foreach(Student student in students) 
    {
      Console.WriteLine(student.FirstName + student.LastName);
    }
  }