Are Magic Strings Bad? 3 Reasons to Stop Using Them


A magic string may sound like something that does wonders in your code. But it is not the case. You should avoid them whenever possible.

This article discusses magic strings, why you must avoid them, and how to eliminate them in your code.

What are magic strings?

A magic string is a string that declares directly in several places in a code without assigning it to a variable. According to magic strings, a program’s behavior can change. Examples of magic strings include:

  • A cache keys
  • A specific URL patterns
  • A prefix
  • A user types.

Also, you can have magic numbers in the code. They are numeric values like a timeout value, a length of an input variable, etc. I have a separate article on identifying and eliminating magic numbers in the code.

Using magic strings is not a good programming practice. Mainly because they can change over time, causing bugs if you fail to update every code line you use.

Let’s understand it using an example. The following C# program does two things. It creates a unique message ID and deletes a user using a user ID.

The two functions need to ensure that the UserID should not contain the word “STDR”. The program declares the word “STDR” in three places to check if the user ID contains this prefix. There is no single point of declaration of this word. In this case, the magic string is “STDR”.

Can you guess what “STDR” stands for?

public class Message
{
    public static string CreateMessageID(string userID)
    {
        string messageID = "";
        if (userID.Contains("STDR"))
        {
            //trim the user ID
            userID = userID.Replace("STDR", "");
        }
        messageID = userID + new DateTime().ToString("yyyyMMddHHmmss");
        return messageID;
    }

    public static void DeleteUser(string userID)
    {
        if (userID.Contains("STDR"))
        {
            Console.WriteLine("Cannot delete this user");
            return;
        }
        //logic to search and delete the user
    }
}

The “STDR” in this example stands for the Standard type of user.

Another common example of using magic strings is when declaring unique keys. For instance, let’s say you want to cache some data. For caching, you need to have a key. Then programmers might declare it directly inside the code without defining it as a constant.

The following method shows this scenario.

public static string GetValue()
{
    CacheObject cache = new CacheObject();
    string value;
    if (cache.Contains("cacheKey"))
    {
        //get the cache value using the key
        value = cache.Get("cacheKey");

    }
    else
    {
        //call the API to get the value and add it to the cache
        value = GetValueFromAPI();
        cache.Add("cacheKey", value);
    }
    return value;
}

3 reasons why you should stop using magic strings

Let’s look at some reasons why magic strings are bad practice in your application code.

1. Magic strings are often duplicated

As you saw from the above examples, magic strings are often duplicated. It means that the more functionalities you have around them, the more places you need to declare them in the code. In worst-case scenarios, magic strings can be duplicated across multiple files or classes.

If you choose to use magic strings, you must define them everywhere you need them. This also leads to unnecessary code duplication.

2. Magic strings are not always self-documenting

Magic strings do not explain their meaning or what other values they can contain. It means magic strings are seldom self-documenting. Anyone new to the code must go through the entire implementation to understand why the code uses them.

3. It’s hard to change magic strings without introducing bugs

Take the first example you saw.

Suppose your project requirements changed, and the ID can now contain “STDR-IX.” In that case, the programmer should change it in multiple places. If they miss updating it in every line, it will cause bugs in the program.

Also, there can be typos. Modern IDEs may allow selecting all magic strings and replacing them at once. Changing them again is difficult if it’s used in many files or the code has similar strings. Thus, code maintenance will be hard with magic strings.

How to eliminate magic strings in C#?

Fortunately, there are a few elegant solutions to avoid magic strings.

Use constants

The best way to avoid magic strings is to declare them in one place. If the string can only contain one value, then declare them constants. If it is used in multiple classes, declare them in a separate common file (for example, a configuration file).

The following code shows what the first example looks like after refactoring the code by declaring the magic string as a constant.

public class Message
{
    private const string standardUserType = "STDR";

    public static string CreateMessageID(string userID)
    {
        string messageID = "";
        if (userID.Contains(standardUserType))
        {
            //trim the user ID
            userID = userID.Replace(standardUserType, "");
        }
        messageID = userID + new DateTime().ToString("yyyyMMddHHmmss");
        return messageID;
    }

    public static void DeleteUser(string userID)
    {
        if (userID.Contains(standardUserType))
        {
            Console.WriteLine("Cannot delete this user");
            return;
        }
        //logic to search and delete the user
    }
}

Now, if you want to change it, you only must change it in one place.

Refactoring code that contains magic strings is easier with some IDEs.

Visual Studio, for instance, has built-in “Introduce constant” refactoring. It especially supports refactoring support for C#.

Select the magic string you want to turn to a constant. Select “Refactor” and then “Introduce constant” which will automatically extract the magic string into a constant.

You have four options:

  • Introduce constant
  • Introduce constant for all occurrences
  • Introduce local constant
  • Introduce local constant for all occurrences

Consider using Enum

If the magic string can contain more than one value, consider using an Enum instead.

Suppose, in our first example program that you wanted to extend it to more user types. Following is how you can replace the magic string in our first example program with Enums.

enum UserIDPrefixes
{
    STDR,
    TCHR,
    TA,
    ADMIN
};

public static void DeleteUser(string userID)
{
    if (userID.Contains(UserIDPrefixes.STDR.ToString()))
    {
        Console.WriteLine("Cannot delete this user");
        return;
    }
    if (userID.Contains(UserIDPrefixes.TCHR.ToString()))
    {
        Console.WriteLine("You are deleting a teacher");
    }

    //logic to search and delete the user
}

Conclusion

If you see a specific string declared at several different places in your code which change the program’s behavior based on its value, then you have a magic string.

Magic strings are often duplicated, seldomly explain their purpose, and are difficult to change in every place, which can cause bugs if you miss updating it in even one place. Thus, you must minimize using them.

There are two ways to eliminate them. If the string has only one specific value, use a constant. If it can contain multiple values, then you can use Enums. Declaring magic strings in one place makes it easier to maintain the code and improves the code readability significantly.

Recent Posts