"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.
In [1] 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.
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.