I have been reading a lot of posts on this site regarding the usage of constants.
Question:
When should I use Enums for constants, vs using classes or interfaces.
I see 2 key situations I am looking to address.
1. Global Constants used in a applications by multiple projects.
Example:
Common logging strings
Container references like a database mapping reference used in
WebSphere EAR's
2. Object Specific Constants
Example:
Employee pay rates for an Employee Object
From everything I have read this is what I think I have a grasp on and what I am looking for an opinion on.
For situation 1:
Design Approach: Use a final class and a static import.
Seen here: What is the use of interface constants?
For Situation 2:
Design Approach: Apply the use of Enums to represent those constants as a object.
Additional points to remember:
If the constant string belongs to the class and you only need the string value keep in the class that uses it
Don't use an Interface for situation 1. As mentioned in the link above as Constant Interface Anti-pattern.
.
Thanks in advance for thoughts and opinions.
Global constants as you put it should actually be in a properties file as it allows each application to configure them individually without a code modification. For object specific constants my general rule of thumb on Enum versus static final I typically lean towards how many elements there are to have and how related those elements are. If there is a big relation between them such as Suits in a deck of Cards then I would go for the enum. If it is default age for a user, then this becomes a final as there is no purpose to making it an enum as it would not need to be referenced in many areas. These are just some thoughts on each of the ways I have approached it.
Global constants used by different projects: Enum
Better to use Enum over public static final members in a class. More clean and easy to understand I guess.
Object specific constants: public static final members in Class. Because, they are needed only within the scope of the object, then no need to created a new Enum for that.
Nice read
Update (fixed broken link):
Making the Most of Java 5.0: Enum Tricks
Making the Most of Java 5.0: Enum Example
It sounds like almost everything you've listed for both numbers 1 and 2 belong in configuration files or database tables.
Do you want to re-compile code when your employee's get a raise or a page name changes?
Unless there is a compelling reason everything else that is constant should be modeled as an enum. This way you realize the benefits of fast object equality comparisons and you avoid problems associated String constants.
The scope of those enums however is application specific. If the enumeration is only used by a class that it should be a private enum. If it is shared by multiple classes then it should be in its own class definition file.
Related
It may be very obvious questions, but is it good to use Enum class if you know that the list of values will keep increasing?
Let's say you define an Event Enum first it contains only [Poo, Too] then as we know we always have some new requirement it becomes [Poo, Too, App, Laa] and that keep changing again and again,
So what is the best approach in this case?
tl;dr
If the entire set of possible values is known at compile-time, use enum.
If values can be added or dropped while your system is in use (at runtime), then you cannot use an enum. Use a Set, List, or Map instead.
Known at compile-time
An enum is appropriate when the domain (set of all possible values) is known at compile-time.
If this year your company is offering two products ( Poo & Too ), then make an enum for those two elements.
public enum Product { POO , TOO }
Next year, your company decides to grow their product offerings by adding App & Laa. As part of a planned deployment, add two more objects to your enum.
public enum Product { POO , TOO , APP , LAA }
By the way, notice the naming conventions. The enum has a regular class name (initial cap). The objects being automatically instantiated are constants, and so are named in all-uppercase.
Also, be aware that the enum facility in Java is quite flexible and powerful, much more so than the usual naming-a-number enum scheme seen in most languages. You can have member variables and methods and constructors on a Java enum. For example, you can add a getDisplayName method to provide text more appropriate to a user-interface than the all-caps object name, as seen in DayOfWeek::getDisplayName. You can add quite a bit of functionality, such as ChronoUnit.between.
What you cannot do at runtime with an enum in Java is add or remove objects. Thus the requirement that you know your domain at compile-time. However, when working with a group of enum objects, you can use the highly-optimized EnumSet and EnumMap classes.
Known at runtime
If you cannot determine the domain at compile-time, if users can add or remove elements at runtime, then use a collection such as a List, Set, or Map rather than an enum.
Singleton
Though not originally intended as a purpose of Enum in Java, an enum happens to be the safest (and simplest) way to implement the Singleton design pattern.
This approach to a singleton is explained in the famous book Effective Java by Dr. Joshua Bloch, et al. Using an enum solves multiple obscure technical problems with other approaches to a singleton.
Your question is pretty generic and I'm pretty sure there is no single right answer. But judging based on spring* tags, I suppose you might be asking about enums in DTOs that being sent over your system in serialized form. If that's the case, I would recommend to choose String in DTO, while inside single app it's ok to use enum. Then you would just care about deserialization/conversion in a factory manner, having ability to handle unknown/missing constant gracefully by logging/providing fallback or meaningful error.
It depends on a case-by-case situation and your question doesn't have much context. However, I do recommend using ENUMs for many cases, including if you expect the list of ENUMs to increase.
Some reasons to use them are:
It creates a definite guide of ENUM elements that can be used throughout your code. It eliminates uncertainty over what something is named or what it is. For example ENUM that contains list of animals, or enum of "something".
Its easy to refactor later if you need to change anything.
I'm sure there are many more reasons, I find it like a table of contents sometimes. For many cases, you can completely avoid it and be fine but I think its better to use it in general if you're on the fence.
I have a project that consists of 5 different packages in Java. All of them contain classes that have magic numbers and hardcoded strings for which I'm looking to create constants. I would like to know what is best practice. Should I create one Constants class for all of the constants in the program that all classes can import? Or would it be more efficient to split up the constants into multiple, smaller files?
In terms of best practices, see the Principle of Least Privilege.
You should extract inline hard coded constants, but you should not put all constants into one monolithic class. Instead, split the constants into contextually appropriate classes ("multiple smaller files") and keep those classes only at the package level they need to be referenced properly.
If the value applies only to one particular class (aka private static final), there is no need to lift this value out of the class. It would only create more work to keep it elsewhere if it is only referenced in that one place.
If the value acts like a global variable or needs to be accessed in many different classes (aka public static final), extracting related values into a separate class makes sense but is probably a code smell you should investigate.
Since you are using packages, consider using package-private (static final) to isolate your configuration values to a single package that needs it.
Consider using configuration/properties files to inject values instead of explicitly hard coding them in a class at all. Depending on your needs, you may use simple Java Properties or there are many libraries/frameworks which can help you handle properties, such as Spring.
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
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.
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.
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
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.
I am designing a java API(not an API exactly) in my office which will contain 4000+ constants. So all the teams can use them directly. Initially i thought to create their classes according to their type and create their static objects into a separate class. So anybody any use them directly.
But after reading need of static variable, i afraid it could be a problem of creating so many static variables. Is there any alternate?
*After me whoever will join this project can also add a constraint in my Constant class without caring of performance. There is a possibility that many of the constants will be used rarely.
*Every member of Constant class will represent a class which will have its own behavior. It might be the part of some inheritance tree further. So using enum might not be a good idea.
You want to create a location where some 4000+ constants will live. there's the possibility that users of this class may add constants (possibly at runtime)?. T
Concern about the memory issues of statics is misplaced. If you need 4000 values, they're going to have to live somewhere, right?
If people will be adding values at runtime, this sounds like a singleton Map or Properties (which is really just a kind of map anyway) of some kinds. People often use dependency injection frameworks like Spring or Guice to manage this sort of thing.
If you just mean adding compile constants, you can make them all static. You'd probably want to make them static final as well, they'll be compiled inline.
It's very likely that 4000 constants is a very bad idea. Where I've seen systems with large numbers of constants (>100, even) defined in one place, what usually happens is that people forget the definitions of them and end up using their own variants , which sort of defeats the purpose (for example, I've worked on a system with 100's of SQL queries defined in a "Queries" class. Of course people immediately ignore it as it's more of a bother to look up if the exact query you need is in there than to roll your own. The class eventually grew to something like 1500 queries, many exact duplicates and many unused, most used once. Utterly pointless). I can imagine exceptions where you wouldn't "lose" things with naming conventions, but unless you've got a use case like that this seems like a really bad idea.
Breaking out your constants into enums gives you type-safe references. It also makes things conceptually easier to deal with. Compare:
-
public class Constants {
String WORK_ADDRESS;
String WORK_PHONE;
String HOME_ADDRESS;
String HOME_PHONE;
}
with
public enum ADRESS{ WORK, HOME }
public enum PHONE { WORK, PHONE }
Which would you rather work with?
Performance is highly unlikely to be the problem with this design. RAM is cheap. (Cue the usual quote: Premature optimization is the root of all evil.)
On the other hand, I'm not quite sure how any client developer can remember and use 4000+ constants. Can you give us an idea what sort of object this is?
You may, depending on details you haven't given us, find it useful to collect constants into enums. Stateless enums can be easier to understand than public static final variables if there are some natural groupings you can take advantage of.
What happens when you allocate in static is that it surely won't be freed in the runtime of your app.
so what ?
if you don't create them static then they'll be duplicated through every instance of your classes.
what you don't want to do is to set static huge amounts of data such as images or GUI
an image takes up a lot more than a few fields;
4000 constants of surely int (4 octet) = 16000 octets not even the size of an icon ^^
I would point out hte Javadoc to prove my point
http://download.oracle.com/javase/1.4.2/docs/api/constant-values.html#java.awt.event.KeyEvent.CHAR_UNDEFINED
this is the KeyEvent decleration in Java, check the out declarations ^^
Unless you are creating large arrays or very long strings, 4000 data values isn't going to be a lot of memory. I think that post you cited was talking about much larger amounts of data.
Another approach is to read the values from a preferences file.
Perhaps the constants be modularized into a collection of classes, so the more rarely used ones will be loaded only on demand.
Possible ways to refactor the code which had Java interface solely used to define lots of constants.. You can now imagine how this class is used to access these consts.
This is known as a constant interface anti-pattern. Although the previous link provides a way to fix this (using a class and static imports), I think there is a better way of refactoring this. Follow the suggestion here to fix this. Overall it is better to move the constants to the appropriate classes/abstractions rather than using one utility constant class. For e.g Calendar class defines only the constants that are relevant to its operations. Also as CoolBeans suggested try converting those String constants to enums where applicable.
So you have a big bag of constants (you don't say how big, but I've seen things like this with thousands of entries). Importing all of these values is a mess, as you get all the unrelated values imported into everything.
Rather than automating the changes, what I'd do is separate the constants into logically coherent groups, and then moving each group into the class hierarchy where they make sense. e.g. if you've got constants for COLOR_RED, COLOR_GREEN, DATE_FIELD, WEEK_FIELD, you'd probably want to appropriately split them into the color and data hierarchies. For the first pass ignore edge cases where you can't decide immediately - anything you can do to trim the constants down to coherent groups will help.
Seems like a good usecase for enums. So take out the interface and replace it with an enum. Since it is a collection of constants enum fits the bill nicely. Moreover, enums are one of the most efficient ways to implement a Singleton in Java.
Instead of duplicating answers, take a look at these good relevant questions.
Java Enum Singleton
Efficient way to implement singleton pattern in Java
Alternatively as Pangea mentioned you can do static imports. I think both approaches are fine but enums in my opinion will be a better placeholder for organizing your unrelated constants in relevant meaningful groups.
You could attack the source files with a shell script that does the following:
for all .java files:
if (content matches " class ? imports Singleton {"):
replace "imports Singleton" with ""
append "import static Singleton.*;\n" after package declaration
This is far from perfect (it just ignores cases where a class imports Singleton and other interfaces...) but it could be a practical strategy - and maybe it's OK to solve 80% with a quick script and correct the remaining 20% manually (IDE will report errors).