The Forkless Philosopher

Programming To An Interface

General principle

Programming To An Interface describes the practice of never using concrete classes as types for attributes and arguments, but to use abstract classes instead. That way, you can later change the concrete implementation without having to change the code in all the places where it is used. And it also greatly facilitates unit testing.


Let me give you an Example. Think of the method:

double extractSharePriceFrom(string url, CWebConnection& con) {
  if ( con.isConnected() ) {
    string p = con.getPage( url );

How do you unit test it, if you do not have a web connection? The answer to this is: develop a mock object that acts like CWebConnection but always returns true when isConnected() is called and a fixed example page on getPage() calls. Quickly written, no problem. Only you can't pass it to extractSharePriceFrom because extractSharePriceFrom expects a CWebConnection and not a CMockWebConnection. And here Programming To An Interface comes to your rescue.

The first thing to do is to define an interface, i.e. list the public methods all implementations of a web connection must offer because they are used in the code at someplace or other. In other words: create an abstract class IWebConnection.
Next, make your existing web connection implementation inherit from that abstract class: CWebConnection : IWebConnection { ... }. Now you can change the method's signature: string extractSharePriceFrom(string url, IWebConnection& con) { ... }. Finally, you create your mock class as also inheriting from the abstract web connection interface: CMockWebConnection : IWebConnection { ... }. And from now on, whether you feed extractSharePriceFrom(...) an instance of CWebConnection or an instance of CMockWebConnection doesn't matter (at least in the sense that it doesn't break your build). And you can write your unit tests.

Extreme Abstraction

In "Prefactoring" (O'Reilly, 2005) Ken Pugh takes the concept even further: calling it extreme abstraction, he advocates avoiding even build-in types like integer or string completely for any domain-specific data and to use classes instead. So, instead of int price you use CPrice price or, since we are programming to an interface, IPrice price. Even if CPrice internally uses an int to store the price. But if at a later time your representation of price needs to change, you only have to do it in the concrete implementation of whaterver class you have that fulfills IPrice's contract, and not all over your code.

Exceptions To The Rule

For value classes, i.e. classes that have no other purpose than to be a container for various related values, it is acceptable to do without an explicit interface class. Like structs, they are an interface in themselves.