Separate Interfaces From Implementation

From SelfDocumentingCode:

An interface separate from its implementation filters the pertinent information a caller cares about.

In languages that permit you to declare interface signatures independently from their implementation, typically for constraint/type checking, you've got a handy place to document the interface with comments.

Whilst it can be argued (correctly) that the type checking information is really DerivedInformation and is annoying to maintain, it's generally worth it just for the added documentation benefit. I'm not saying to write MassiveFunctionHeaders, but FileHeaders by themselves mixed with small CrcCard like method comments go a long way to explaining how to use a system.

The main idea here is that you don't want to inundate your reader at this level with information about the implementation. All she wants to know is how to use your class. Typically you're only publishing the public interface as well (cf. EmphasizeImportantInformation), once again improving the signal to noise ratio.

So, with a separate interface you can a) identify the public interface cleanly to the caller, b) document what the caller needs to know to use your code.

Typically you'll find the caller will jump into the implementation anyway, but at least this way she knows where to go and has a good module-wide understanding first instead of having to page up/page down through lots of code to get an idea of what's going on.

Just an example of GroupRelatedInformation and EmphasizeImportantInformation.


In a language like JavaLanguage, for which this method is applicable, what advantage does this give us? Shouldn't JavaDoc serve as the public interface layer? Doesn't creating an interface for every class just increase the count of class by a factor of ~2 without any visible benefits?

In other words, a violation of OnceAndOnlyOnce.

There are also disadvantages to this in terms of code traceability. When checking a control flow, these interfaces become dead end walls, making it hard to trace the flow of the code.

The only major advantage I see is the ability to use MockObjects, which is big plus but not mentioned here.

-- SriramGopalan

The purpose of an interface in Java is to allow one to derive multiple child classes. If only one class is needed, then there is no value to type the same information twice (remember, this is one of the gripes against C/C++, the requirement to define each function twice). I agree that use of a MockObject is a valid reason to define multiple child classes, but I hasten to add that it is usually more beneficial to test with the real class whenever feasible. Don't create interfaces just to create interfaces, let the design evolve and create an interface when the design demands one.

-- WayneMack


The ability to use MockObject's underlies one of the greatest benefits of separating an interface from its implementation: the ability to "swap out" an implementation with another without affecting dependent clients of its interface(s). This is the core concept being used with mock objects; the client expects an interface that behaves in a certain manner (see also: LiskovSubstitutionPrinciple), and nothing more. As long as the mock object fulfills the contract of the interface that its mocking, the clients of the interface could care less how it does it.

Take the idea of a standard Collection interface, for example. The basic and commonly-accepted purpose of a Collection is for clients to have the ability to add, remove, iterate over, and look up a set of objects. A class (call it SimpleClass) may expose, as part of its interface, a Collection. To a client of SimpleClass, the Collection is just that: a basic Collection instance.

However, SimpleClass could actually be instantiating a more feature-full implementation of Collection for its own purposes. This implementation could do any number of things that SimpleClass requires for the proper functioning of its own internal state. Some additional functionality of the Collection implementation used by SimpleClass could include raising events when an item is added/removed, as well as providing additional members on its interface for other set-based operations.

-- RyanKinderman


See Also: ImplementationIndependenceLimits, SeparateDomainFromPresentation

EditText of this page (last edited August 28, 2006) or FindPage with title or text search