Replace Constant Interface With Static Import

You are subtyping a class or interface in order to get access to the static members defined on it (a common JavaIdiom called ConstantInterface).

Replace the subtyping with static import. Possible only since java 1.5 aka 'Tiger'.

Replace this:

 public class Order
implements Constants {

double price() { return basePrice() + shipping() + TAX; } }
With this:

 import static Constants.TAX;

public class Order {

double price() { return basePrice() + shipping() + TAX; } }
Motivation

Sometimes, people place static members into an interface and inherit from it looking for avoiding prefixing static members with class names. This produce the so-called "ConstantInterface" AntiPattern.

Interfaces are intended for defining types, not providing access to static members. When a class implements an interface, it becomes part of the class's public API, creating an undesirable connection between classes and confusing clients. Even if you remove the access to static members, you still have to implement the constant interface as clients now depend on it.

Using static imports, you can remove the class name prefix from static members without inheriting from the type containing them, and avoiding the aforementioned problems. This is a very clean alternative.

Mechanics

Example

Suppose we have the following class fragment:

 public class Order
extends Values
implements Constants {

double price() { return basePrice() + shipping() + TAX; }

double shipping() { return Math.min(basePrice(), SOME_VALUE); } }
We both agree that the Order class is not a "Values" neither a "Constants", so we are in presence of a clear "ConstantInterface" AntiPattern. This example needs an urgent refactoring, so I start step by step by removing the Values class dependency:

 public class Order
implements Constants {

double price() { return basePrice() + shipping() + TAX; }

double shipping() { return Math.min(basePrice(), SOME_VALUE); } }
Now, when I compile, the compiler signals that it doesn't know who is SOME_VALUE, so I'll include the corresponding static import:

 import static Values.SOME_VALUE;

public class Order implements Constants {

double price() { return basePrice() + shipping() + TAX; }

double shipping() { return Math.min(basePrice(), SOME_VALUE); } }
I compile and test and things work well, so I continue by repeating the previous steps with the second dependency. After the changes, the code will look like this:

 import static Values.SOME_VALUE;
 import static Constants.TAX;

public class Order {

double price() { return basePrice() + shipping() + TAX; }

double shipping() { return Math.min(basePrice(), SOME_VALUE); } }
At this time, I removed completely the use of the "ConstantInterface" AntiPattern. I compile, test, and save the changes.

-- SantiagoValdarrama?


See also:


CategoryRefactoring


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