Separation is useful in simplifying a complex system because the goal or effect is often simpler to explain than the means needed to reach the goal or achieve the effect. For example, it is easier to state the goal of solving a maze puzzle ("Find a path from the entrance to the exit.") than it is to find the solution or to describe an algorithm for finding the solution.
Programmers are familiar with separation for it is present in all manuals and documentation. For example, a typical description of the command read(f, buffer, nbytes) is that the command transfers nbytes of data from file fto the specified buffer. The mechanism required to achieve this effect involves the disk hardware, software device drivers, the file system, the disk block management code, and run-time I/O library routines, none of which need to be mentioned in the description of the read command.
A well-established use of separation in software design is distinguishing an interface from an implementation. The interface is viewed as the visible, external aspect of the software that must be understood to use the software; the implementation is viewed as the hidden, internal aspect of the software that is important only to the implementor. It is this form of separation that is taken as the definition:
An implementation satisfies an interface if the behavior specified by the interface is provided by the implementation.
The interface-implementation separation suggested by the figure below appears at many different levels. Manual pages for libraries describe only the interface properties of individual operations without describing how any of the operations are implemented. A more complex layer of software (e.g., a windowing system or a networking environment) may be described by an application programmer's interface (API). The API defines what data structures and facilities are available for use by the application programmer without defining how the structure and facilities are implemented. A last example is a software standard which is a commonly accepted definition of a service (e.g., the TCP/IP communication protocols standard) that defines the external behavior that a compliant system must exhibit but leaves the implementor free to implement that behavior in any way.
In addition to its simplifying advantages, separation provides flexibility to implementors because different implementations may satisfy the same interface. The several implementations may differ in time or space efficiency, purchase price, maintainability, documentation quality, reliability, or other non-functional characteristics. If separation is fully observed, one implementation for a given interface can be replaced by a different implementation of that interface without altering the overall operation of the larger system of which it is a part. The ability to associate different implementations with the same interface is shown in the following figure.
Two different interchangeable implementations of the same interface are said to be "plug compatible"; unplug the current implementation and plug in its replacement. Certainly many non-software products take advantage of such interchangeability: car tires, stereo speakers, and computer monitors are only a few examples.
The animation below illustrates this notion of plug compatibility as it applies to interface and implementation.
A single implementation can simultaneously satisfy several interfaces. In such a case, the implementation contains the union of all of the methods required by each of the interfaces (and possibly additional methods that are not used by any of the current interfaces). The figure below shows a single implementation, named Graphics, that contains two methods, DrawText and DrawShape. Two interfaces are also shown: TextInterface that defines only a DrawText method, and ShapeInterface that defines only a DrawShape method. Clearly the Graphics implementation satisfies both of these interfaces.
The animation below illustrates the idea of one implementation (Graphics) being able to satisfy two different implementations.
As shown in the figure, each interface provides a different view of the implementation: each view may expose only a subset of the implementation's full capabilities. Such a restricted view is useful in isolating those capabilities that are required in a given situation or by a specific part of the system. Isolating the most limited set of capabilities needed makes it possible to replace a more capable implementation (e.g., Graphics) that may contain present, but unneeded operations (e.g., DrawShape) by a smaller implementation that contains only those methods defined in the more limited interface. For example, suppose that a part of the system needed only the methods defined in the TextInterface. This need could be satisfied by the more general Graphics implementation or a more specific one that implemented only the TextInterface and not the ShapeInterface. Because it is more specific, the smaller implementation may be more efficient in execution time or may need less memory.