The Constant Interface Pattern Is Discouraged

It has been an age old practice to place commonly used constants in an interface, and classes implementing it can directly access those constants, without prefixing the Interface name.

Advantages of this practice

AdvantageRemarks
No need to worry about instantiating a classConstant classes are meant not to be instantiated and hence has a private constructor
Any thing??
Access the constants directly with out prefixing a namespaceJava static import can be used with classes

Disadvantages of this practice

Constant Interface does not define a type

It is being considered a good practice to segregate the contract (Interface defining the type and behavior) from implementation, and brings in lots of benefit. Lets consider some examples.

public class Employee implements Person {  }Employee is a Person and defines specific behavior specific to Person
public class Tiger implements Animal {}
Tiger is a Animal and defines specific behavior specific to Animal

However when we write the following, it really does not make any sense. Hence constant interface by its very nature does not define any type.

public class Tiger implements SessionContants {}What does it convey?Tiger is a SessionConstants?  🙂 🙂

Run-time Issues, because of field shadowing


public interface SessionConstants {
String SESSION_NAME = "XYZ";
}
 
 
public class HttpSession implements SessionConstants {
 
private static final String SESSION_NAME = "ABC";
 
public static void main(String[] args) {
System.out.println(SESSION_NAME);
}
}

What you think the sysout would print?
Is it desirable?


It just works fine with out any warning/error, unlike with Constants class [there would be a warning].
Unless a developer checks any implemented interfaces when adding a constant to a class, or does so but makes a typo in the new constant’s name, the value of a constant can be silently changed.

Namespace pollution

The named constants appear in the namespace of all implementing classes as well as their sub-classes.

Code Compatibility issues 

If binary code compatibility is required in future releases, the constants interface must remain forever an interface (it cannot be converted into a class), even though it has not been used as an interface in the conventional sense.

Constant Class approach

The fact that the interface CAN be implemented by an individual if desired, leaves room for the issues pointed out above. So it’s best to prevent the ability to implement the interface altogether. Hence, it’s more appropriate to have a final class that can’t be instantiated (With private constructor) at all.

Bad Practice

public interface SessionConstants {
    String COOKIE_NAME = "JSESSIONID";
    String WLS_AUTHCOOKIE_PREFIX = "_WL_AUTHCOOKIE_";
    String DEFAULT_WLS_AUTHCOOKIE = "_WL_AUTHCOOKIE_JSESSIONID";
}

Preferred approach

public final class SessionConstants {
    public static final String COOKIE_NAME = "JSESSIONID";
    public static final String WLS_AUTHCOOKIE_PREFIX = "_WL_AUTHCOOKIE_";
    public static final String DEFAULT_WLS_AUTHCOOKIE = "_WL_AUTHCOOKIE_JSESSIONID";
     
    private SessionConstants() {
    }
}

Advantages of this approach

  • Since the required static memebers are imported statically, the class namespace is not polluted.
  • The compiled code has one fewer binary compatibility constraint (that “class implements Constants Interface”).
  • Because static imports apply only to the current file (and not the whole class hierarchy) it is easier to discover where each static member is declared.
  • Run-time and compile-time semantics are more closely aligned when using static imports instead of constants interfaces.
  • If Required static blocks can be declared.

Disadvantages of this approach

TODO : List out

Constant Interface Pattern and the rest of the world

Joshua bloch in his famous book, Effective Java talks about it in great detail

The constant interface pattern is a poor use of interfaces. That a class uses some constants internally is an implementation detail. Implementing a constant interface causes this implementation detail to leak into the class’s exported API. It is of no consequence to the users of a class that the class implements a constant interface. In fact, it may even confuse them. Worse, it represents a commitment: if in a future release the class is modified so that it no longer needs to use the constants, it still must implement the interface to ensure binary compatibility. If a non final class implements a constant interface, all of its sub classes will have their namespaces polluted by the constants in the interface.

It is indeed a distasteful use of interfaces, since interfaces should deal with the services provided by an object, not its data. As well, the constants used by a class are typically an implementation detail, but placing them in an interface promotes them to the public API of the class. And hence,

Interfaces should only be used to define contracts and not constants

Leave a comment