Extract Interface

"Several clients use the same subset of a class's interface, or two classes have part of their interfaces in common."
See page 341 of the book RefactoringImprovingTheDesignOfExistingCode, or brief graphical summary at http://www.refactoring.com/catalog/extractInterface.html


When you use TestFirstDesign, you'll often find yourself with one class that will soon be many. But to switch from one class to multiple in a strictly typed language, the several classes will have to share a common base class or interface.

Classic example: Knowing that you wish to write a drawing program that includes lines, rectangles, triangles, circles and groups of same, you know you'll need to use the CompositePattern DesignPattern. But you don't want to start there; start by implementing Line. Once you have the system working with Line, you'll want to add, say Rectangle. But everything's done with collections of Line and all parameters are of type Line; nothing will accept instances of class Rectangle! What shall we do?

Answer: Don't sweat it; just ExtractInterface the commonly used functionality of Line, like moveTo and drawAt to a new interface, say "IShape". Change almost all uses of class Line to interface IShape. That would include practically all collections and method parameters, but it would not include constructors (until you get into AbstractFactory).

Run your tests. Once the system works with Line objects passed around using the new IShape interface, you're ready to add the Rectangle class, which will implement the IShape interface.

(Later, you'll think of the CompositePattern again, but don't mess with it until you need it. ;-)


Technical details for VisualBasic:

  1. Create a new class for the desired interface. Name it (IShape) and change the instancing property to "2 - Public Not Creatable."
  2. Copy the appropriate Public methods from the existing class to the new interface, and delete the contents of their method bodies.
  3. Add "Implements <new_interface_name>" to the original class (Line).
  4. In the original class, prefix interface methods with the new interface name (IShape_).
  5. Change these methods from "Public" to "Private". (Yes, they're still publicly accessible, through the interface, but it's generally bad form to expose the "Interface_Method" form on the class' default interface unless you have to -- for scripting clients or other IDispatch users, for instance.)
  6. Run tests, and continue, as usual.


EditText of this page (last edited November 24, 2001) or FindPage with title or text search