What – constants in Java
While Java does not have a built-in Constant type, functionally constants are supported through the use of two modifiers: final and static, like this:
public static final int NUM_CARDS_IN_DECK=52;
First, we define the variable as public, this is not necessary for using the constant within the same class, but is needed in order to access the same constant from multiple classes. I will go into this distinction in more detail later.
Secondly we mark it as static. This provides two related features. The variable can be referenced without instantiating a copy of it’s enclosing object. The variable will only exist ONCE in memory. This is very efficient. Also, during compilation the access will be in-lined into the class and therefore much faster.
Thirdly we mark it as final. This prevents the value from being changed or overridden, ensuring that that the value is consistent throughout your entire application, and letting the compiler know it does not have to worry about the value changing.
From there it looks like a normal variable except for the name. The convention is to name constants in all capitals with underscore characters separating logical words.
Where – local or global
Constants can be defined within one of your functional classes as private (or another restrictive modifier), and used only within that class, or they can be defined in a single purpose location holding all of your shared constants as public. For the nature of this container, see the next section.
The defining line governing where a given constant should live is based on it’s usage. Is it something that is specific to the one class, or is it something that multiple classes within your application should be utilizing? You can always refactor it later as well, so don’t get too hung up on this question.
How – interface versus class
For constants that need to accessed from multiple classes, there are two options on exposing the constants. First, by creating an Interface which will hold all of the constants for your application. Then, in any class you need access to a constant, you simply implement the interface. The advantage to this is that you do not need to prefix the constant name with a class or anything else. This has been a popular approach, and many of the initial examples of constants used this method. However, thankfully, it has finally been recognized as an anti-pattern. Using an interface for this purpose is really abusing the concept of an interface. An interface is meant to hold a type definition, not to piggie-back your constants around your application.
The second approach, creating a constants class which houses your constants and referring to them via the Class.CONSTANT notation in your code (or you can import the individual static constants if you like) is the best approach. It is easy to tell where the constants are defined, and you aren’t cluttering up your class definition.
Why – context through constants
People usually think to use a constant when a value may be used across many classes within their application. For instance an application limit such as the maximum number of threads to use, or the number of cards in a deck of playing cards, etc…
These are great places to use constants (assuming they shouldn’t be runtime configurable properties). In this case one of the main reasons constants are used are to provide a single point of definition. Allowing you to have consistency across the application and a single point to make changes.
What is often overlooked is the use of constants to provide context. The above usage does this as well, but is rarely a motivating factor for developers. I advocate using local constants in classes frequently in order to convey context to your code. Consider this code:
int tally = 0;
for(int i = 0; i < 60; i++) {
Random rand = new Random();
if(rand.nextInt(100) > 60) {
tally = tally + 5;
}
}
There are many numbers but no context. This can easily happen with Strings as well, see the section on ATG for an example. If you were new and had been asked to adjust the game logic to make the game this code is part of, easier or harder it would not be easy. Now, let’s add some context to the functionality by using local constants:
private static final int SECONDS_PER_TURN = 60;
private static final int PERCENT_CHANCE_OF_SLIPPING_PER_SECOND = 60;
private static final int FEET_SLIPPED = 5;
.....
int tally = 0;
for(int i = 0; i < SECONDS_PER_TURN; i++) {
Random rand = new Random();
if(rand.nextInt(100) > PERCENT_CHANCE_OF_SLIPPING_PER_SECOND) {
tally = tally + FEET_SLIPPED;
}
}
and it becomes clear that this piece of code calculates the number of feet slipped in a turn. It also makes it easy to adjust the percent chance of slipping, without getting confused by the multiple uses of “60” in the area. If you use constants to give your code more context you will thank yourself later, as will anyone else who deals with your code.
ATG – repositories
Repositories are ATG’s data access and object-relational mapping technology. In many ways the technology is similar to Hibernate with a few key differences. One of those differences is that instead of mapping to typed objects like Hibernate does, ATG Repositories use RepositoryItem to represent every data object. The values are accessed through a value dictionary. In the repository definition file you map out all the objects, their properties (and the tables and columns backing them), and the relationships between objects. Each object is given an item descriptor name which is used to identify that type of object. The properties of an object are also named. These names are used to query objects from the database and access, or update, the properties of the object.
Take a shoe management application (not that you need one): You have a Shoes object, representing a pair of shoes, which happens to have a few properties, including flags for shoes, boots, or sandals (not the best way to model it, but perhaps it is a legacy database). You also have a Wearer object, for the person currently wearing the shoes. This object has a shoe property. You have a Manufacturer who has a shoes Collection property. You also have an Owner who also has a shoes Collection property. You can see where this is going.
RepositoryItem shoes = Repository.getItem(myShoesId, “shoes”);
if((Boolean)shoes.getPropertyValue(“shoes”).booleanValue()) {
List manShoes = (List)manufacturerer.getPropertyValue(“shoes”);
manShoes.add(shoes);
manufacturer.setPropertyValue(“shoes”, shoes);
.........
}
And so on. You can see that it can get ugly very quickly. And of course you may want to change the names of properties as time goes on, and trying to work through all of your code to update it each time is bound to cause problems.
When using ATG Repositories, I highly recommend using a constants file to hold all of the item descriptor and property names.
Leave a Reply