rc3.org

Strong opinions, weakly held

Use constants instead of string literals

One practice that I internalized a long time ago but that I still see a lot of experienced developers ignore is habitual . Most applications have common strings that are used in a number of places. These should pretty much always be stored in constants (however your language of choice implements them) rather than appearing as string literals anywhere other than when they are initially assigned. For example, a blog publishing tool might have a status field for posts with possible values of “published”, “draft”, and “scheduled”.

If you’re writing Java, you might write code like this:

blogPost.setStatus("published");

and

if (blogPost.getStatus().equals("published")) {

     // do stuff }

The reason this is bad practice (even though it works like a charm) is that it costs you an opportunity to let the compiler do work for you. Let’s say you write your code like this:

public static final String STATUS_PUBLISHED = "published";

blogPost.setStatus(STATUS_PUBLISHED);

if (blogPost.getStatus().equals(STATUS_PUBLISHED)) {
    // do stuff
}

If there’s a typo in that code, the compiler will catch it for me. Typos in string literals are the cause of a huge number of difficult to diagnose bugs, and are easy to avoid. There are other advantages to this approach as well, especially if you use an IDE like Eclipse. If put a string in a constant, I can use the “References” feature in Eclipse to show me every spot in my code where the constant appears. In a couple of seconds, I can discover every place in my application where the status of a blog post is set to “published”. There are all sorts of other advantages as well, like being able to rename the constant using the rename variable refactoring in the IDE as opposed to search and replace.

This practice is on my mind this week because I finally bothered to learn about Ruby constants, which are incredibly easy to declare and enable me to apply the same practice that I always use when programming in Java.

To create the same constant in Ruby, you’d just type:

STATUS_PUBLISHED = "published"

You can, of course, reference it by name, and if it’s declared in a class called BlogPost, you can reference it like this:

if status == BlogPost::STATUS_PUBLISHED
    # do stuff
end

Ruby will happily show you an error message if you reference that constant without declaring it first, so even though Ruby is looser in terms of variable declarations than Java, the compiler will still help you out in situations like this.

PHP also has constants but in my opinion the declaration syntax makes them a pain to deal with. (I still use them when I’m programming in PHP, though.)

4 Comments

  1. Hi Rafe,

    I totally agree that constants should be used, but I suggest reversing the order of the objects in your test…

    Instead of blogPost.getStatus().equals(STATUS_PUBLISHED), use this safer variant:

    STATUS_PUBLISHED.equals(blogPost.getStatus())

    This way you can’t get a NullPointerException if getStatus() returns null and you try to call equals on it… your constant is never null, so it’s safe.

  2. Ditto for any comparison. Always put the constant value before the variable:

    if( null == foo) { .,. if( 7

  3. Give me three reasons why we should use constants instead of literals.

  4. Reasons to use constants in leu of literals:

    1. If a constant’s literal value changes, it only needs to be changed once at the constant’s declaration. Embedded string literals require find/replace for changes.
    2. When constants are used, all of the literals can be placed in a single location, instead of having the literals peppered (and duplicated) throughout the code.
    3. If the constants are declared in the same location, that location becomes a useful reference.
    4. Constant identifiers provide more readability than literals, in effect becoming self-documenting. The conditional if (STATUS_READY == status) stands out more and means more than if ("ready" == status).
    5. Again, the misspelled constant identifier STATUS_READ would be caught by the compiler. The misspelled literal "read" would happily compile and becomes a runtime bug.

Leave a Reply

Your email address will not be published.

*

© 2024 rc3.org

Theme by Anders NorenUp ↑