4

I've noticed some projects like to store constants in their own file, i.e constants used globally and in the main program loop might clutter the main file so perhaps they look to place them elsewhere and then reference/import file/class.

I understand that when writing an OOP class that you'd want to keep all constants at the header of the class file so they can be referenced statically as such:

myCar.setColour(Colour.RED);

Where RED is a colour constant in the Colour class.

What is good practice for having a large amount of constants, should they just be at the top of your main file or is it in any way wise to have maybe a ProgramConstants class that is purely static, public and available to read?

11
  • 4
    I don't see how that's a duplicate...
    – insidesin
    Commented Jul 17, 2015 at 10:21
  • "Your peer tells you after reviewing the code..."
    – gnat
    Commented Jul 17, 2015 at 10:22
  • What's your point? How does this relative to storing information in seperate classes?
    – insidesin
    Commented Jul 17, 2015 at 10:23
  • 2
    Well, that's what your question boils down to in the end. "Is that more readable and maintainable?" Commented Jul 17, 2015 at 10:23
  • 1
    that "someone" as you call them, is a moderator over here. And that "failed project" is what this very site attempted at it's beginning. And that "article" explains in details how it went and how it was discovered that such questions are poor fit over here. "Irrelevant", yeah sure
    – gnat
    Commented Jul 17, 2015 at 10:35

1 Answer 1

10

The idea behind encapsulation in object-oriented programming is moving data and the code that uses it together.

There is no "but the data are constants, treat them specially." If you have colors, keep them in a Color class. Java's Calendar class has calendar field constants in it. BigDecimal and BigInteger each contain constants of their own type.

The idea is that referencing constants involves their scope: BigDecimal.ZERO for example. I know that is a decimal zero because I typed BigDecimal.ZERO and not BigInteger.ZERO.

One of the worst anti-patterns in this regard is having a "constant interface" which is honestly lazy and unclear. Sometimes you come across an interface containing a bunch of random constants thrown together, and classes will implement the interface just to make it easy to refer to the constants. That generally ends up violating LSP and makes it difficult to determine what those constants do.

Constants should be:

  • An enum if appropriate, such as java.math.RoundingMode. The Java Calendar fields which were created before enum existed should be an enum. This necessarily scopes them properly and ensures other constants are not in the same namespace (class static final field).

  • Located on the class that defines their type, if appropriate. This covers the reusable numbers on BigDecimal for example.

  • Located somewhere else where like constants are together and not intermingled with other, unlike constants.

One could argue this is a matter of opinion. I feel that if you asked any group of experts to compare e.g. BigDecimal and some random AWT constants class, we would come to a consensus that there are some really bad practices in reality and some that make code clearer and easier to understand.

7
  • What about things that aren't directly tied to an Object but are instead more logically linked to the main program itself (or something better worded).
    – insidesin
    Commented Jul 17, 2015 at 11:14
  • @insidesin without much information to go on I cannot say for sure, but maybe it should not be a constant, then. Just make it a local variable and pass it into objects that need it. For example, the "application name" can be a variable like this instead of a constant.
    – user22815
    Commented Jul 17, 2015 at 11:15
  • To add a bit and perhaps answer @insidesin 's question, I would argue topics like this from the angle of cohesion. The driving questions are: what is the underlying motivation for we grouping things together? Does it simplify things or complicate them? Could we have come up with a better grouping? In my opinion, grouping things together only because they share in a relatively unimportant implementation detail falls under coincidental cohesion, and there are likely much better groupings to use.
    – Daniel B
    Commented Jul 17, 2015 at 11:29
  • @DanielB that is the core idea behind encapsulation which I mentioned in my answer. Sometimes constants are highly cohesive with the classes that contain them, sometimes not so much. That is the crux of what I iterated in the bullet points.
    – user22815
    Commented Jul 17, 2015 at 11:46
  • @Snowman I agree (with both your answer and your comment); I just feel that the "types of cohesion" list has some value to add to the discussion, in that it actively lists and ranks different reasons for keeping things together. Representing it as a gradient helps with the justification, or at least it has helped me.
    – Daniel B
    Commented Jul 17, 2015 at 12:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.