Monday, April 2, 2007

Java :: Constants Interface or Constants Class?

We all know about patterns and anti-patterns. One anti-pattern that has been hated by many people is the Constant Interface anti-pattern. Java doesn't support globals directly, but sometimes you will need to have a few things as global. Meaning, accessible to every class in your entire program.

In Java to get the platform independent new line character, we write the following code:

final String NEW_LINE = System.getProperty("line.separator");

But the new line character is something any class in our program may need and writing System.getProperty("line.separator") is not good for two reasons.
  1. We may misspell the key 'line.separator' in which case we'll get a 'null' back, and
  2. It's inefficient.
A better way is to get this new line character one time, store it in the memory and make it accessible to all the classes in our program. This kind of a situation led to the invention of the "Constant Interface" anti-pattern. People implemented this pattern like this:

public interface Constants {
String NEW_LINE = System.getProperty("line.separator");
}

And the client of this 'Constants' interface started implementing this interface for convenience reasons. This is a bad idea because let's say this 'Constants' interface has 100 constants and a client class implements this interface for convenience reasons, all the 100 constants from the interface end up being a part of the public API of the client class. This breaks inheritance and you can by now imagine how the Javadoc will look like for this client class.

OK, we may ask all of our clients of this 'Constants' interface that they must not implement this interface and they should only see it as a place where global constants are stored, but what's the guarantee that they will NOT implement this interface?

Thankfully we have a better way of doing this, see the following code:

public class Constants {
public static final String NEW_LINE = System.getProperty("line.separator");

private Constants() {
// Private constructor to enforce un-instantiability.
}
}

The above 'Constants' class has the following benefits over the 'Constants' interface:
  1. No client can instantiate, because the constructor is private
  2. No client can extend, again for the same reason, the constructor is private
Having a class for constants and making it's constructor private is a much better approach than using an interface.

4 comments:

Anonymous said...

Good info :)

Anonymous said...

what about Constants.NEW_LINE ??? =)

Anonymous said...

This article is so wrong on so many levels. You acknowledge the fact having such a Constants class is an anti-pattern, yet you proceed to endorse it.

You say System.getProperty is inefficient. Based on what analysis? You might also want to look up File.separator.

There is NO situation that warrants having a global constants class in OO. Such a class becomes non-OO and breaks the concept of encapsulation. You're basically having data without context. Every single one of those constants will be better off elsewhere.

Srikanth said...

No, I didn't acknowledge having a Constants class is an anti-pattern, I was mentioning about a Constants interface, whose members can be inherited by an implementing class.

I didn't say System.getProperty() is inefficient, I was telling that calling that again and again like this...

System.getProperty("line.separator");

... is inefficient in terms of typing and you can make a mistake.

If I remember correctly, I read this exact method of storing constants in Effective Java. And, I disagree with you when you say having a global constants class (which is final and constructor is private) is violation of OO. Sometimes you do have data without context.

You also mention that every single one of those constants will be better off elsewhere. In this case of new line, where can you store it if not here?

Post a Comment