Skip Navigation LinksHome > View Post

Avoiding Primitive Obsession to tip developers into the pit of success

Perhaps the wooliest blog post title I've posted in a while, so bear with me. Imagine a component that uses strings as parameters. Not too hard, right?

Have you ever created a list of string constants for use with such a component? Something like this:

public static string CommandNames
{
    public const string ProfileCommand = "ProfileCmd";
    public const string WebExecuteCommand = "WebExecuteCommand";
}

Of course you have. But how can you do your best to encourage other developers to use these constants instead of hardcoding the strings when using the API?

P.S. Don't get too hung up on the details of this example, I had to make up an API.
A common approach that solves these problems is to remove the use of the primitive (in this case a string) and use a specific class. Maybe a CommandName class something like this:

public class CommandName
{
    public static CommandName Create(string name)
    {
        return new CommandName() { Name = name };
    }

    private CommandName()
    {}

    public string Name { get; private set; }
}

And we could have a CommandNames static class that exposes the appropriate objects


public static string CommandNames
{
    public static readonly CommandName ProfileCommand = CommandName.Create("ProfileCmd");
    public static readonly CommandName WebExecuteCommand = CommandName.Create("WebExecuteCommand");
}

Now all we have to do is modify the API to no longer accept a string and only accept a CommandName, i.e.

public void ExecuteCommand(string commandName)

... becomes...

public void ExecuteCommand(CommandName commandName)

This is fine if you own the API. If not, you'll probably have to wrap the existing one. However, another developer is now much less likely to hardcode a string where the API is used and will hopefully use your static CommandNames. You can even enforce this by making the static Create method internal and embedding the CommandNames class inside the same assembly (or adding an InternalsVisibleTo attribute to the assembly).

If you do decide to lock down the capability to create new CommandName objects then beware that you've now limited use of the ExecuteCommand API. I find that the mere avoidance of exposing a plain string is enough to make a developer think before embedding a string. As always, your own mileage may vary.

Tags: .NET

 
Josh Post By Josh Twist
7:24 AM
14 Aug 2008

» Next Post: Validation Application Block and WCF
« Previous Post: Databinding to property bags and dictionaries in WPF

Comments are closed for this post.

Posted by Michael Giagnocavo @ 15 Aug 2008 12:48 PM
As I wrote on Simon's blog, you can use generics to get the same functionality (type names) without any extra code when you need a list. So, you could write Id<CommandName> instead of having to create a new type.

http://www.atrevido.net/blog/2008/08/15/Typing+String+IDs.aspx

Anyways, it's good to see people taking advantage of type systems!

© 2005 - 2014 Josh Twist - All Rights Reserved.