// JSON-LD for Wordpress Home, Articles and Author Pages. Written by Pete Wailes and Richard Baxter. // See: http://builtvisible.com/implementing-json-ld-wordpress/

Program to the Interface

I was teaching a class last week that introduced the attendees to a BPM tool. Since this particular BPM environment leverages the use of OO paradigms, basing the organization of its rules and workflow on classes, it is central to the tool’s operation to have an understanding of Object Oriented Design (OOD). When I teach this course I always spend a day covering OO terminology and concepts. This gives the class a common basis to proceed as we learn how to navigate, design, build and test within the BPM tool.

At one point during the week we were discussing an example of some code within the BPM tool that included a variable whose declaration (type) was an interface and whose definition, obviously, was a class. Although not key to the example, I pointed out the use of the interface declaration as a reminder regarding good practices, noting that developers should always “program to the interface”.

I continued on but a student’s raised hand caught my eye. The individual asked me to repeat and elaborate on what I had mentioned. Although we had spent a day discussing OOD, it occurred to me that I may not have used that expression before. Even though we had discussed interfaces, heterogeneous collections, Liskov’s Substitution Principle, and so forth, apparently I had not effectively stressed the relationship to using interfaces as data types in order to decouple our code from implementation.

As we discussed the value of using interfaces as our data types the students caught on and were able to describe the advantages of this “rule”. Certainly Spring developers are familiar with the concept since Inversion of Control (IoC) is specifically used to decouple our code from other implementations.

Developers should favor the use of interfaces for data types rather than the implementation type even if it is not clear that another implementation will ever be leveraged or created. The practice of coding to interfaces will aid in consistently decoupling modules. The approach simplifies refactoring and allows for much more flexibility in future releases.

For programmers who are not familiar with this approach, it is discussed in the book, “Design Patterns: Elements of Reusable Object Oriented Software” by Gamma, Helm, Johnson and Vlissides. The formal statement in that book is to “program to an interface, not an implementation”.

As a trivial Java example, consider:

import java.util.Vector;

public class InflexibleConsumer {
  public InflexibleConsumer() {
  }

  public static void main(String[] args) {
    InflexibleService inflexibleService = new InflexibleService();
    Vector<Double> myData = new Vector<Double>();
    double sumOfLogs;
    String valuesInCSV;

    inflexibleService.setupData(myData);
    valuesInCSV = inflexibleService.formatCSV(myData);
    sumOfLogs = inflexibleService.sumLogs(myData);

    System.out.println("Sum of Logarithms for " + valuesInCSV + " = " + sumOfLogs);
  }
}

class InflexibleService {
  public InflexibleService() {
  }

  public void setupData(Vector<Double> data) {
    data.add(new Double(10));
    data.add(new Double(20));
    data.add(new Double(30));
    data.add(new Double(40));
  }

  public double sumLogs(Vector<Double> data) {
    double logSum;

    logSum = 0.0;
    for (int index = 0;index < data.size();++index) {
      logSum += Math.log(data.get(index));
    }

    return logSum;
  }

  public String formatCSV(Vector<Double> data) {
    StringBuffer tempValue;

    tempValue = new StringBuffer();
    for (Double oneValue : data) {
      if (tempValue.length() != 0) {
        tempValue.append(", ");
      }
      tempValue.append(oneValue);
    }

    return tempValue.toString();
  }
}

Note that the InflexibleService class is really just there to work with an ordered collection (represented by a Vector). Any ordered representation of a list should work, but since the class is coded using a specific implementation (class Vector) any other class wishing to leverage the capabilities of the InflexibleService class must also use a Vector (or subclass of Vector) to store its data. In fact, the only way to refactor the InflexibleService class to use something other than a Vector would require editing all of its methods.

As an alternative, consider the following:

import java.util.Vector;
import java.util.List;

public class FlexibleConsumer {
  public FlexibleConsumer() {
  }

  public static void main(String[] args) {
    FlexibleService flexibleService = new FlexibleService();
    List<Double> myData = new Vector<Double>();
    double sumOfLogs;
    String valuesInCSV;

    flexibleService.setupData(myData);
    valuesInCSV = flexibleService.formatCSV(myData);
    sumOfLogs = flexibleService.sumLogs(myData);

    System.out.println("Sum of Logarithms for " + valuesInCSV + " = " + sumOfLogs);
  }
}

class FlexibleService {
  public FlexibleService() {
  }

  public void setupData(List<Double> data) {
    data.add(new Double(10));
    data.add(new Double(20));
    data.add(new Double(30));
    data.add(new Double(40));
  }

  public double sumLogs(List<Double> data) {
    double logSum;

    logSum = 0.0;
    for (int index = 0;index < data.size();++index) {
      logSum += Math.log(data.get(index));
    }

    return logSum;
  }

  public String formatCSV(List<Double> data) {
    StringBuffer tempValue;

    tempValue = new StringBuffer();
    for (Double oneValue : data) {
      if (tempValue.length() != 0) {
        tempValue.append(", ");
      }
      tempValue.append(oneValue);
    }

    return tempValue.toString();
  }
}

The FlexibleConsumer is now free to use any class that implements the java.util.List interface. In fact, only one line of code needs to be changed in order to use a different implementation: the line that creates the Vector instance. Changing that to an ArrayList, LinkedList, or a project-specific class implementing the List interface (assuming the proper imports are created) will be supported by the FlexibleService class.

This ability to switch implementation classes with minimal, or even zero code changes in the case of IoC, are one tool in the developer’s toolbox that simplifies code maintenance and extensibility. If you are creating software and you haven’t found yourself leveraging the concept of coding to the interface, now would be a great time to incorporate it into your standard practices.

Leave a Reply

You must be logged in to post a comment.