25

It's been told me (and I have seen this statement in a few other places) that it's not recommended to store your constants in a separate class in Java, in order to use them in the other classes. But I haven't seen anywhere WHY is it so. What is the reason I should not store them in their own interface/class?


I came from C to Java and in C i would just make a .h file where i defined constants with #define

Mihai Bujanca
  • 4,089
  • 10
  • 43
  • 84

4 Answers4

31

Constants in a dedicated file are frowned upon for stylistic reasons. Having a class dedicated to constants can encourage developers to add increasing numbers of unrelated (undocumented?) constants to a file that slowly bloats out of control.

By contrast, having constants associated with the classes they are related to is a more scalable and readable design.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • "Single" is relative. Per package or UOR is reasonable. Per entire code base, probably not. And there certainly should not be one central Config file stored on Google's servers that the rest of the world' Java developers maintain via a web interface. – djechlin Feb 24 '13 at 20:53
  • Wouldn't it be much easier to be documented if all put in a single class for each package?. Even if developers tend to add too many constants, they will get rid of them when making the documentation. Still seems better to me than incorporate constants in different classes or even enum them in one single class and then still getting rid of the useless ones when making the documentation. – Mihai Bujanca Feb 24 '13 at 20:59
  • 3
    @BujancaMihai Personally, I think not. I keep constants associated with the classes they "belong* to; I find that easier to read (each class may have a few private constants, some package-private ones, etc.). If appropriate, I gather related constants into an enum. – Duncan Jones Feb 24 '13 at 21:04
  • 1
    I do agree about `private` constants, they should be associated with the class that uses it. But say I have a class named Circle and one named Cylinder. I need PI for both classes. Or for 1000 classes, exaggerating, or simply for the whole package. PI will not "belong" to any of those classes so wouldn't it be a better approach to store PI in a class along with other constants than declare it in my Circle class as `public` and then use it in other classes as well? Of course I used this example to keep things simple, but you may have many constants in the same circumstances – Mihai Bujanca Feb 24 '13 at 21:09
  • @DuncanJones this can make it really hard to change, say, the port, max # of users, url, etc. especially when code is often refactored, which is why they should be isolated in a file. – djechlin Feb 24 '13 at 21:15
  • @djechlin why would then they not be isolated to a new .class file. They are just things your code might frequently run into and it's easier to store them in a constant. It's not like arguments, not like they would be a configuration or something – Mihai Bujanca Feb 24 '13 at 21:24
  • 1
    @djechlin I can see the advantage of factoring out certain properties into files. I just disagree with an approach that favours *every* constant living in a file. – Duncan Jones Feb 24 '13 at 21:31
4

So you can be an engineer and measure constants and their locations as a technical choice. This is great and fine when you work on performance critical systems or on cool small snippets. Once your application tends to grow however, it becomes harder and harder to grasp the business requirements and end-user needs reflected in the code.

So instead of thinking about style -- separate class, properties file or nested inside a class -- I tend to follow domain driven design -- if the set of constants exclusively belong to a specific class (entity), nest the constants; if the concept touches more than one of the entities in your domain model, feel free to make it a separate entity.

And please do remember, that since Java 5, you do have enums at your disposal.

Mirko Adari
  • 5,083
  • 1
  • 15
  • 23
  • Thanks for the advice, but still, you don't really tell me why should I use/ not use a separate class to store constants – Mihai Bujanca Feb 24 '13 at 21:14
  • It looks to me harder to keep track of your `public` constants, used in more classes if constants are spread trough many classes. Of course, I agree `private` constants should remain in their classes – Mihai Bujanca Feb 24 '13 at 21:31
3

A separate constants class is not object-oriented design. In OO, a class (or interface) represents a contract, and a class which only contains constants does not define any contract.

Another object-oriented consideration is that a separate constants class encourages misuse of inheritance. Inheritance is supposed to indicate that a class fully adheres to the contract defined by another class or interface. Inheritance should not be used just to share functionality or constants; that's what public methods and fields are for. Thus, this code is incorrect:

class SomeApplicationClass
implements ScrollPaneConstants  // Incorrect, import ScrollPaneConstants instead
VGR
  • 40,506
  • 4
  • 48
  • 63
-4

Issue is that they should be living outside of your source code entirely. You should be using something like Apache Commons Config, or at least loading from a .properties file.

I will also note that I'm interpreting "single" with respect to a reasonable scope. For instance, there should not be one Config file for all Java developers used stored on Google's servers with a request form for modifying. There probably should not be done for your entire code base; however, per UOR or package is a reasonable scope, and is the one I use in practice.

djechlin
  • 59,258
  • 35
  • 162
  • 290
  • 2
    Again.. the OP is asking *why* they should not be stored in a dedicated class. – Duncan Jones Feb 24 '13 at 20:43
  • No, they shouldn't be living outside the source code, since for example an entire package has classes that use it, but there is no external dependence – Mihai Bujanca Feb 24 '13 at 20:45
  • @DuncanJones "What is the reason I should not store them in their own interface/class?" because they shouldn't be in any interface/class. – djechlin Feb 24 '13 at 20:46
  • @BujancaMihai that class shouldn't contain constants, it should load them from a `.properties` file or such. Hardcoding should not appear in source. If the config-layer class is well-encapsulated it won't matter to any client package whether they were hardcoded or loaded from a random # generator. – djechlin Feb 24 '13 at 20:47
  • 3
    There are many use cases for constants being part of the code itself. Why would someone want to redeclare the block size of AES for example? They wouldn't - it's constant. Yet we don't want magic numbers everywhere so we declare constants in the source. – Duncan Jones Feb 24 '13 at 20:49
  • 4
    @djechlin again, that is just a statement, not a real answer. You reply to DuncanJones that the constants should not be there because they should not be there. I've been working in C for a while and whenever I needed to use constants, i'd just #define them in a .h header and go with it. Also, why would there be the `final` modifier if not for constants. If I need PI with 10 decimals for example, it would be much easier to write the value like `public static final PI=3,14159..` then put it in a `. properties ` file – Mihai Bujanca Feb 24 '13 at 20:50
  • @BujancaMihai do whatever you want. The only illegitimacy in storing all constants in a single Java file is that they should be outside of the source entirely. Before I learned to use a .properties file properly I stored them in a single Config file much like you are asking what is wrong with. And the only thing wrong with that is the constants are hardcoded into source. There is nothing wrong with them being in a single file per package or UOR or whatever. – djechlin Feb 24 '13 at 20:52