Why Are Interfaces Useful?

W

Interfaces, usually prefixed by “I” are useful in software engineering, for a number of reasons.
Primarily, they allow you to create “pluggable” code.
By this, I mean that your code is easier to manage, easier to maintain, easier to change the way certain parts of your application work, without changing the entire way it works.

Lets look at an example.

Our application is an photo sharing web application, allowing users to view and upload photos.
The main functions of the site, are handled by our ImageManager class. This facilitates the retrieval, and storing of images. Fairly integral to the application.

As we are designing our application using SoC (Separation of Concerns), all our ImageManager class will do, is get, or put images. (in reality, we should really have a separate concern for each operation – get & put)
It doesn’t care about storing user details or meta data, against the image in a database, nor does it care about checking to see if a user can view that image or anything like that.
It purely puts, or gets, an image.

Now. this operation sounds simple, to get an image, I just need to connect to my file store, and retrieve my image?
Yes. But what if, one day, you need to be able to switch where you store your images.
For example..on day 1, you are storing your images on the file system, in a directory within your web application project.
This works fine, especially during beta testing, however as demand grows, the strain on your server and your bandwidth become a problem, and you need to change where images are stored.

You also want to be able to use a storage service, such as Amazon S3 to store your images.
(I’m not going to go into how S3 or any other service works in this article, it’s just an example.)

Luckily, we have a couple of ImageManagers….
FileSystemImageManager, and S3ImageManager

Both of which, implement our interface – IImageManager (notice the prefix "I”)

Here’s the interface:

C#

public interface IImageManager
{
  void PutImage(Image image, string fileName);
  Image GetImage(string fileName);
}

VB

Public Interface IImageManager
  Sub PutImage(ByVal image As Image, ByVal fileName As String)
  Function GetImage(ByVal fileName As String) As Image
End Interface

Note the empty method signatures…

Interfaces contain no logic – they are simply a contract that each implementation agrees to follow.

So lets have a look at an implementation of IImageManager:

C#

public class FileSystemImageManager : IImageManager
{
  public void PutImage(Image image, string fileName)
  {
    //code to save the image on the file system
  }

  public Image GetImage(string fileName)
  {
    //code to get the image from the file system
  }
}

VB

Public Class FileSystemImageManager
    Implements IImageManager
    Public Sub PutImage(ByVal image As Image, ByVal fileName As String)
        'code to save the image on the file system
    End Sub
    
    Public Function GetImage(ByVal fileName As String) As Image
        'code to get the image from the file system
    End Function
End Class

The FileSystemImageManager implements IImageManager (indicated by the : in c#)

note, in visual studio, you can right on your interface implementation declaration and select Implement Interface – this will create the required method signatures within your class.

Implement Interface

Our class now conforms to IImageManager.

But – there’s no code! That doesnt technically matter.

As long as you’ve implemented each method (even by throwing a NotImplementedException), your class will compile.

So what’s the point?

Well, we now have a FileSystemImageManager class, that (after you’ve added your code) gets and puts images on the file system.

In our application, we can do something like:

C#

      //get the image:
      IImageManager imageManager = new FileSystemImage();
      var image = imageManager.GetImage("my_filename");

VB

'get the image:
Dim imageManager As IImageManager = New FileSystemImage()
Dim image = imageManager.GetImage("my_filename")

“Great” you say….

But that means you can “swap out” your functionality, really easily.

Instead of declaring imageManager as a new FileSystemImage() we could have another class, that implements IImageManager called “FlickrImage”

This could then use Flickr to get and put images (obviously additional functionality would be required to authenticate against Flickr API)

I’ll expand this tutorial at a later stage to explain how to effectively use config, factory patterns, IoC etc…