Refactoring Day 9 : Extract Interface

Today we look at an often overlooked refactoring. Extract Interface. When you notice more than one class using a similar subset of methods on a class, it is useful to break the dependency and introduce an interface that the consumers to use. It’s easy to implement and has benefits from loose coupling.

   1: public class ClassRegistration
   2: {
   3:     public void Create()
   4:     {
   5:         // create registration code
   6:     }
   8:     public void Transfer()
   9:     {
  10:         // class transfer code
  11:     }
  13:     public decimal Total { get; private set; }
  14: }
  16: public class RegistrationProcessor
  17: {
  18:     public decimal ProcessRegistration(ClassRegistration registration)
  19:     {
  20:         registration.Create();
  21:         return registration.Total;
  22:     }
  23: }

In the after example, you can see we extracted the methods that both consumers use and placed them in an interface. Now the consumers don’t care/know about the class that is implementing these methods. We have decoupled our consumer from the actual implementation and depend only on the contract that we have created.

   1: public interface IClassRegistration
   2: {
   3:     void Create();
   4:     decimal Total { get; }
   5: }
   7: public class ClassRegistration : IClassRegistration
   8: {
   9:     public void Create()
  10:     {
  11:         // create registration code
  12:     }
  14:     public void Transfer()
  15:     {
  16:         // class transfer code
  17:     }
  19:     public decimal Total { get; private set; }
  20: }
  22: public class RegistrationProcessor
  23: {
  24:     public decimal ProcessRegistration(IClassRegistration registration)
  25:     {
  26:         registration.Create();
  27:         return registration.Total;
  28:     }
  29: }

This refactoring was first published by Martin Fowler and can be found in his list of refactorings here.

This is part of the 31 Days of Refactoring series. For a full list of Refactorings please see the original introductory post.

About Sean Chambers

I am a Senior software developer from Palm Coast, Florida. An advocate of Domain Driven Design, Behavior Driven Development, creator of FluentMigrator and community activist. I am married to my beautiful wife Erin and am the proud father of two wonderful children. I currently reside at ACI, a local insurance industry/mortgage software company that excels in creating solutions using Agile methodologies.
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  •  I appreciate you want to bring understanding to the developers, but you misunderstood the poinf of this refactoring.

    Both the first and the second version of the RegistrationProcessor are equally decoupled from the type of the object called registration in your example. In other words the RegistrationProcessor does know nothing about the actual implementation of the Create method in any of the cases. Moreover it is not aware of the fact that ClassRegistration is declared as a class (and not an explicit interface).

    Note that every Class exposes its interface implicitly, and the outer classes can refer to the actual implementation only through this implicit interface.

    The real value of the example you provided is that you are able to limit the interface exposed by ClassRegistration to a subset interface that provides operation used for example by a Registration Processor. And this exaposes the type naming issue that was introduced to your example.

    The original ClassRegistration should be named sth like ClassManagement and the extracted interface: ClassRegistration (drop the I as this bring no value to the type name).

    also see the original Fowler’s example:

    Marek Dec