1

I have to work on some code that was CAST-audited. The report says that it is bad in Java to use public static and that accessors should be preferred. That is also what I was taught at school.

The application uses public static fields in various classes to define the values that should be used in attributes etc.

Coming from the Typescript world, I am not sure if should change all the public constants in the application for private fields that are only accessible though getters. Thinking of it, I never saw such a practice (access constants through accessors) in Java.

Should I change all the "global constants" (there are many of them in the project) from public to private/ accessed through Getter?

6
  • 1
    As with most things in software development, it depends. It's hard to know without looking at some of your code. The problem that I see in your scenario is not so much the lack of accessors, it's the use of statics. Apr 12, 2019 at 14:42
  • Possible duplicate of Why use getters only as opposed to marking things final?
    – gnat
    Apr 12, 2019 at 14:54
  • @RobertHarvey I would gladly provide code if it could help, but I am not sure of what to show to imrpove my question Apr 12, 2019 at 15:15
  • @gnat i dont think so. That question asks about member fields, this one about static fields.
    – marstato
    Apr 15, 2019 at 8:50
  • @Pikuni IMO this is purely opinion based. I have never seen accessor used for static data / constants, although i wouldn't think badly of it if i encountered it today. Make up your own mind and decide in your team and codebase on whether you want to follow that advice from the audit.
    – marstato
    Apr 15, 2019 at 8:52

1 Answer 1

2

Might I suggest first and foremost, not doing bulk rewrites of the entire source tree. :)

That aside, there are pros and cons to using constants and accessors. Using constants often allows data to be available to Java at compile time instead of just run time (of course it depends on what the data type is, and how you set that data). This will likely be slightly faster, as it will inline that data, but you should always prove this out with some data-driven performance testing if you're going to make a sweeping change. That said, inlining constants also leads to static dependencies between different libraries. Consider if you inlined a value of 5 (for example), gathered from a RUN_MODE_QUICKLY constant. But in the an update of this library, they rearranged the values, and now 6 means RUN_MODE_QUICKLY, and 5 means RUN_MODE_VERY_SLOWLY. Code would "break" -- perhaps so subtly nobody would notice. There are also concerns about interned Strings using up all the object references, but I might be a little out of date here.

So you can decouple this by using accessors. Instead of inlining the values, call a function (perhaps even a static one), and ask the library to give you the data. Secondly, if you have a bunch of accessors for everthing, it's a little more future-safe in case you need to go perform some operation on every access (e.g., print some log message, or even set a breakpoint to observe all accesses).

Ultimately, it depends on your use case. Are the constants used between JAR files? If not, constants can be faster, and seem like a lot less typing, and a lot more readability. Do you need the flexibility of massaging values on every access? Perhaps accessors.

6
  • Thank you very much for your answer. I am not sure, though, that I get your example right. You mention that if the values change over time, code would break if, for instance, 5 became RUN_SLOWLY instead of RUN_QUICKLY. But I don't undestand the link with accessors... isn't it the very purpose of constants, that changing a value does not break the code because, no matter the value is 6,5 or whatever, you access the run mode from RUN_QUICKLY? Aside from the performance criteria you mentioned and that I find very interesting, I must admit that I am a little bit confused. :) Apr 15, 2019 at 8:21
  • Consider that RUN_QUICKLY and friends belongs to another library, and in your library, when you use them, it may just put a 5 in there. As a consumer of this API, should not have to care what the actual value is, but the compiler may inline it. If the API updates 5 to mean RUN_SLOWLY, you still have the 5 in your bytecode, so you're in trouble. Hoping that makes sense so far. With an accessor, your code compiles the function call into the bytecode, so it will always call the function that generates/accesses the right value -- the "quick" one and not the slow one. Does it make sense? Apr 15, 2019 at 13:30
  • We're talking about indirection, and isolating the client of your API from changes, basically. It's not as relevant in a stand alone application... Apr 15, 2019 at 13:31
  • 1
    Ok, I just got your point :D I should have mentionned that my particular case is about a stand-alone application. However, that point is very interesting. Apr 15, 2019 at 13:34
  • In that case, then I would suggest the only relevant trade-offs are performance (constants) vs. flexibility (the ability to modify values returned from accessors later on down the line), and how much of a pain it will be to move from one type of idiom to another (including performance testing to show it's actually worth it). Apr 15, 2019 at 13:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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