Symptoms

 < Day Day Up > 



Hardcoded values are in general easy to spot in the source code itself. Nevertheless, to further the motivation to remove them, let us look at some of the results that occur from hardcoding these values.

Strings and Numbers

The two most common value types that are hardcoded are strings and numbers. Very few other base types are hardcoded, and many of the others that are represent a collection of strings and numbers. With only a few exceptions that we will mention shortly, any string or number that is placed directly in the code is likely to cause the problems indicative of the Hardcode illness.

What are the exceptions to the rule of no strings or numbers in the code? First, let us consider strings. There is really only one string value that should ever be placed directly in the code, and that is the empty string (""). Any other string, from one letter to a full book, should be stored in an external resource file.

The case for numbers is slightly more complicated. Determining exactly when a number can safely be hardcoded is a matter of context. In general, however, only the numbers 0, 1, and 2 should be found directly in the code. Most valid cases for hardcoding these values involve either a comparison, such as determining if a number is zero or not, or as part of a fixed equation, such as inverting a number. The reason that these hardcoded values are acceptable lies in the fact that the equation or comparison is extremely unlikely to change later in development. Therefore, any number that is likely to change, even if it is 0, 1, or 2, should not be hardcoded.

The following lines of code illustrate both acceptable and unacceptable use of numbers in code:

   if(value > 0) {            // acceptable    float inverse = 1.0f / n;      // acceptable    currentSpeed = 1.0;            // unacceptable    Vector midpoint = (a + b) / 2.0;   // acceptable    double area = 3.1416 * r * r;      // unacceptable

Notice that the use of 1.0 as a speed is not considered acceptable because it is not part of a fixed formula. The 1.0 could be replaced with any number and should therefore not be hardcoded. On the other hand, both the 2.0 and 3.1416 are part of a formula. However, since 3.1416 represents a mathematical concept, it would be better to give it a name such as PI. The 2.0 is not as easily named and is simple enough that it can be allowed to stay hardcoded.

More CAP

One of the most dangerous results of hardcoding is a major illness known as the Cut-and-Paste (CAP) Epidemic. Because the values are not stored in a variable, any usage of the same value must be cut-and-pasted. Thereafter, any change to one of these values must be followed by a change to all of them or unpredictable behavior will result. This is true of numbers and strings, as well as any other odd type that might occasionally be hardcoded.

One solution that is better, but still not optimal, is to place these values in a variable whose scope is accessible to any that need its value. This will eliminate the cut-and-paste that is required of hardcoded values, but it will not solve some of the other problems caused by hardcoding. This solution is most acceptable when the value is extremely unlikely to change, such as the value for (. The other common acceptable usage comes at the end of development, when it is clear that placing the value within the code will allow the compiler to optimize the application in ways that would otherwise not be possible. Be careful to only use this solution when the profiling shows that access to a particular variable is a major performance cost.

Localization

Very little software development these days escapes the need to be international, and nothing can make this more difficult than hard-coded strings. While there are other considerations to making an application suitable for a particular locale, the most prominent is always text. All visible strings must be translated into the various languages of each locale to which the application will be distributed. Even strings used for configuration, which are visible only to advanced users, might require translation.

Strings that must be translated to other languages offer several special challenges to the application’s programmers. First, translation is not often done by the programmers, and therefore not only should changes not require recompiling, but the strings should be collected into one convenient location. This makes it obvious which strings must be translated and saves time and money on the translators and on the quality assurance that must check the results.

The other challenge to internationalization of strings is the differences in grammar across languages. Therefore, it is not sufficient to avoid hardcoding the strings. It is also important to be careful about the methods used to construct strings that are generated at run time.

Take, for example, one method of constructing strings that is commonly used in the Java language, which is concatenation:

   String sentence = "Do any languages treat the " +       "important " + "arrangement " +       "of words differently?"

Or for the more performance conscious:

   StringBuffer string = new StringBuffer();    string.append("Do any languages treat the ");    string.append("important ");    string.append("arrangement ");    string.append("of words differently?");    String sentence = string.toString(); 

Do not be concerned, this is not a case of Premature Optimization if you use the second method since it does not sacrifice readability or robustness to any large degree. However, this method of creating strings creates problems when constructing strings that must be localized later. For instance, if you have a lookup function with the following signature:

   public class Localize {    static String lookup(String label); }

Then you might be tempted to use the following code to construct a sentence that varies at run time:

   StringBuffer string = new StringBuffer();    string.append(Localize.lookup("SENTENCE_BEGIN"));    string.append(Localize.lookup("MODIFIER"));    string.append(Localize.lookup("WORD"));    string.append(Localize.lookup("SENTENCE_END"));    String sentence = string.toString();

The problem arises when you attempt to translate the English version to French. To understand this, here is an example of the English language lookup table:

   SENTENCE_BEGIN = "Do any languages treat the "    MODIFIER       = "important "    WORD           = "arrangement "    SENTENCE_END   = "of words differently?"

This creates the following sentence:

   Do any languages treat the important arrangement of words differently?

If you translate the lookup table to French, you get:

   SENTENCE_BEGIN = "Est-ce que des langues traitent "    MODIFIER       = "important "    WORD           = "l'arrangement "    SENTENCE_END   = "des mots différemment?" 

Unfortunately, the resulting string is:

   Est-ce que des langues traitent important l'arrangement des mots différemment?

Instead, it should be:

   Est-ce que des langues traitent l'arrangement important des mots différemment?

Therefore, seeing string concatenation is often a sign of hardcoding. Even though the actual strings have not been hardcoded, the format of the string has been hardcoded. This example does not even mention the further complications that can arise from context-sensitive translation. For many applications, the use of a format string with replacement will suffice, but even that can be considered hardcoded if the string creation has words whose translation are determined by other contextual word replacements elsewhere in the string. Therefore, you must not only keep an eye out for hardcoded strings, but also the method of constructing strings.



 < Day Day Up > 



Preventative Programming Techniques. Avoid and Correct Common Mistakes
Preventative Programming Techniques: Avoid and Correct Common Mistakes (Charles River Media Programming)
ISBN: 1584502576
EAN: 2147483647
Year: 2002
Pages: 121
Authors: Brian Hawkins

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net