Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant Interface Anti-Pattern Clarification

Tags:

java

I just read somewhere that having an interface with common project constants is bad practice and also known as the Constant Interface Anti-Pattern. If I understood this correctly, the reason provided was that once implemented, the class would expose these constants to the public.

Well, I don't understand the need for 'implementing' in the first place. Isn't it possible to just use these static constants directly? So why do I have to go through the trouble of import static when I can do something like:

interface Constants {     public static final int FOO_1 = 1;     public static final int FOO_2 = 2; }  public class Test {     public static void main(String[] args) {         System.out.println(Constants.FOO_2);     } } 

I would appreciate any guidance to help me understand this a bit more.

like image 709
Grateful Avatar asked Apr 01 '15 04:04

Grateful


2 Answers

The arguments against the "Constant Interface Pattern" are mainly stylistic. You can use a Constant Interface in Java if it suits your need and in fact the Java libraries include a few of these (though they are considered poor examples that shouldn't be repeated).

The reasons why the Constant Interface is considered by many to be an "anti-pattern" are enumerated in Effective Java, 2nd Ed. Briefly, some of the reasons that this use of interfaces are discouraged include:

  • Namespace pollution. The named constants appear in the namespace of all implementing classes as well as their subclasses.

  • Interfaces should define types. In Java, most of the major types in a project should be represented by interfaces. A constant interface by its nature does not define a type.

  • Noninstantiable classes with import static. Declaring constants as static final fields in a class (rather than an interface) achieves all the same objectives as declaring them in an interface. Doing so does not create namespace pollution by the class. If desired, these constants can be used without the qualifying class name by using the import static declaration.

  • Interfaces should specify behavior. An interface is supposed to define a contract between the interface and implementing classes. Implementing the interface is supposed to say something about what the class can do. Constant interfaces do not follow this pattern.

like image 121
scottb Avatar answered Oct 14 '22 03:10

scottb


I realised... the fact that the interface CAN be implemented by an individual if desired, leaves room for the issues pointed out above (i.e. namespace pollution, non-conventional use, exposure through public API ). So it's best to prevent the ability to implement the interface altogether. Hence, it's more appropriate to have a final class with a private constructor so that it can't be instantiated / extended.

public final class Constants {       // to restrict instantiation       private Constants() {}        public static final double PI = 3.14159;       public static final double PLANCK_CONSTANT = 6.62606896e-34; } 

... and use that in combination with the import static.

import static Constants.PLANCK_CONSTANT; import static Constants.PI;  public class Calculations {          public double getReducedPlanckConstant()       {                    return PLANCK_CONSTANT / ( 2 * PI );          } } 
like image 40
Grateful Avatar answered Oct 14 '22 03:10

Grateful