views:

973

answers:

7

I've always thought having a class just for the sake of holding constants is a bad design. But recently, I've tried googling for it and found only that having an interface as a constants is bad an anti-pattern - no mention of using a class of constants.

I'm of the opinion that since a class of constants is really not much different from global variables, that's why I'm against it and tend to refactor away such classes. It creates a class of data that has absolutely no context. Those constants are much better off tied to whatever actually use them, to give them context and meaning, as well as making them encapsulated within a class.

What do other people think?

+16  A: 

Global constants are fine.

Global (non-constant) variables are the work of the devil.

Justice
+4  A: 

I believe the global variables problem is that they create global state. Global constants don't do this, but they indeed is responsible for some contextless constants, which may be bad.

What I'd suggest if you need stuff like that is create enums (in case you have int constants) or static classes for constants, so you can give them some context (Math.PI, for instance)

Samuel Carrijo
A: 

Global variables have been widely recognized as a bad thing and generally should be avoided. This is why so many people have an issue with the Singleton Pattern. The trouble with global variables is that they are transitive.

SwDevMan81
Yep, but I'm asking about global *constants* actually.
aberrant80
What design patterns use global constants?
SwDevMan81
He's talking about an anti pattern.
the_drow
And what is an anti pattern? (were almost there)
SwDevMan81
An antipattern is either a design pattern that is applied inappropriately (so that it does not address the needs of the application or is ineffective) or a bad solution to a problem (the exact opposite of a design pattern).
Thomas Owens
Here it comes, full circle, so what pattern uses global constants?
SwDevMan81
I assume you're implying that you think setting up a global constants class is not a design pattern at all then.
aberrant80
You assumption is correct :)
SwDevMan81
+2  A: 

Global variables are problematic because they introduce largely unnecessary dependencies across modules. These dependencies make it harder to debug problems and reuse code.

I'd say that truly global constants are also problematic for the same reason, So instead of having a singleton called MyGlobals containing a constant like MyGlobals.HTTP_SUCCESS_OK, package like constants together in their own classes, such as HttpStatus.SUCCESS_OK.

Jim Ferrans
+4  A: 

I suppose one thing that's not being mentioned are the more pragmatic issues. If you're using a compiled language, bear in mind that you have to recompile to change the constant's value. If it's a value you may want to change frequently, you may also want to consider a config file.

Jason Baker
if the value changes often, its not much of a constant :)
gbjbaanb
I mean that the *programmer* changes the value often, rather than the value changing at runtime.
Jason Baker
constant for the life of one programme execution might do though. For a very long running process I guess Entropy will get it in the end though ;-(
djna
+7  A: 

Global constants aren't bad practice, as long as they are...

  1. ... immutable - a global, final/readonly reference to a mutable object (like a Java ArrayList<T> or a C# List<T>) is not a constant, but global state.
  2. ... needed by >1 class. If only one class needs your constants, put the constants directly in the class. (Caveat: Balance DRY vs YAGNI appropriately.)

Bloch covers the "constant interface" vs. "constant class" issue in Effective Java, and advocates the "constant class" approach. The reason why you don't want the constants in an interface is that it entices client classes to "implement" that interface (in order to access the constants without prefixing them with the interface name). You shouldn't, though - the interface isn't actually an interface to the object's capabilities, but a compile-time convenience ingrained in the class' external type. Consider this:

interface C { public static final int OMGHAX = 0x539; }
class A implements C { ... }
class B { private A a; }

Class B now unnecessarily has a dependency to C. If the implementation of A changes so that it doesn't need the constants from C, you can't remove implements C from it without breaking its external interface - someone (arguably a very stupid person, but such people abound) might reference an A object through a C reference!

By putting the constants in a class, and by making that class uninstantiable, you inform clients that the constant class really just functions as a sub-namespace. In C# you mark the class as static, in Java you'd want to make it final and give an unreachable constructor:

final class C { 
    private C() { throw new AssertionError("C is uninstantiable"); }
    public static final int OMGHAX = 0x539; 
}

If you program in Java and want the constants without prefixing them with the constant class name, you can use the import static functionality.

And yes, it's slightly redundant to be forced to create a new type just to have somewhere to put your constants, but that's a wart in languages like Java and C# that we have to deal with - we have to put our constants somewhere, and our best option happens to be a non-instantiable class.

gustafc
+1  A: 

In some cases, global constants are the perfect way to go when they are truly constant (not only constant for one build of the program, but supposedly during the whole lifespan of the software product and beyond).

For example, you wouldn't want to have several classes each declaring their own constant for pi, e or HTTP_SUCCESS.

On the other hand, global constants can create many of the problems of global variables if they are arbitrary values that could be changed e.g. because of changing requirements. I.e. if putting those constants into a config file seems like a reasonable option, it should not be a global constant.

ammoQ
The config/properties files have one more advantage - it is much faster to search the text in them (when you need to rename window, label of button for example).
Ha