Thursday, October 18, 2007

Constant Interface or Constant Class?

I have been using classes to hold constants instead of interfaces (which we call the 'Constant Interface'), all these while. My colleague, Kynan, was reading my code today and questioned the reasons behind such practice.

There has always been debates on this subject, e.g.

TheServerSide.com - Use Interface for declaring Constants

I think it's good to share. I have read the following books which justify why should you avoid 'Constant Interface':

Philip Heller and Simon Roberts, "Complete Java 2 Certification Study
Guide":
"In the first place, to say that a class implements an interface
really means that the class exposes the public methods listed in the
interface. Interfaces are for defining types and should be used
exclusively for that purpose. Constant interfaces only contain data,
so they definitely don’t define types.

The second disadvantage is a bit more complicated. Suppose someone you
work with writes some code that uses an instance of Scales. This
person can legally reference that instance with a variable of type
Conversion, even though doing so would be quite inappropriate. Later,
if you wanted to eliminate the Conversion interface, you couldn’t do
so, because your misguided colleague would be relying on the existence
of the interface."

Joshua Bloch, "Effective Java - Programming Language Guide":
"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 nonfinal class implements a constant
interface, all of its subclasses will have their namespaces polluted
by the constants in the interface."

To sum it up, which are basically what I told Kynan:

  1. Interface is for defining types, and not solely for holding constants.
  2. Avoid creating coupling. e.g. introducing or removing a method from the interface will either take you time to fix all implementing classes or make things look ugly. Likely or not, I don't care.

Regards,
Yuen-Chi Lian

3 comments:

Ivan Memruk said...

I think originally they used constant interfaces to type less (to be able to use them without specifying the declaring type when using the constant). Although I don't accept that as a reason anyway, now you can use static imports for that.

Y said...

Thanks for pointing that out Ivan.

yc

Peter Lawrey said...

My view is: interfaces are simpler than classes and if you can use an interface for a given purpose, do so.

One interface I have lists all the System Properties which the application supports (documented in one place)

I would agree that you should keep the number of constant you expose to a minimum.