Lars Stitz
Posts: 2
Nickname: stitzl
Registered: Dec, 2005
|
|
Re: The Backside of an Interface
|
Posted: Feb 22, 2006 2:21 AM
|
|
What I am missing in the discussion so far is the notion that an interface, both a concrete physical one (on a car or a box) and an abstract one (of a software unit), has a semantic that the implementor must adhere to, or risk breaking functionality. The semantic is what actually makes the interface meaningful, and not the set of method declarations common to all implementing classes. In my opinion, this is what actually goes wrong most of the times in software development, as the semantic of many interfaces is neither specified nor adhered to strictly enough.
For a real world example on underlying semantics, the interfaces of my car's rev meter and of my water boiler's pressure gauge are designed completely similar: round, with numbers from 0-6 distributed evenly spaced on the disc, and a needle that shows the current value. However, the semantics of both instruments are quite different. Another example are the interfaces of two different chargers, which may have exactly identical sets of plugs to the power outlet and the device to be charged, but generate different currents on the later one.
For a programming example of what can go wrong, consider Java's Collection and Iterator interfaces. Now, if I write an Iterator implementation called FilteredIterator, which automatically skips some of the elements of the Collection based on some voodoo algorithm (moonphase, anyone?), and return it from Collection#iterator(), some user might be suprised in the following setting:
/**
* @returns true if all items of this order are in stock,
* or false if we must order an item ourselves.
*/
public boolean allItemsAvailable(Order order) {
Collection items = order.getItems();
for (Iterator i = items.iterator(); i.hasNext(); ) {
OrderItem item = (OrderItem) i.next();
if (! itemAvailable(item)) {
return false;
}
}
return true;
}
Now, consider that while it is the general case that Order#getItems() returns a Collection with all order items, some mad hatter created an order with an item collection that returns a FilteredIterator from Collection#iterator() for some reason (or even worse, changed existing code so that this happens). The method sketched above might or might not return the correct value, and it will be completely unclear why, as everyone used the correct interfaces.
The problem is that the Iterator interface and the declaration of Collection#iterator() are, while being very versatile, loosely defined: Should an iterator return all elements of a collection? Does not say so in the documentation, but this is a common expectation. This might be called the downside of an interface.
Cheers, Lars
|
|