Article Image
read

Magic Strings - they're bad right? What are these repulsive warts on good design? And why do they want to melt my code? The fear of strings drives otherwise talented and wise developers to do some extraordinarily ridiculous things...

What's a Magic String?

Seems simple to figure out - most code reviews (at one point or another) will mention the use of "magic string avoidance". The remedy is simple (if you work with C#) - just use an enum. Or work up a class that statically defines what it is that your string represents.

But that doesn't convey what a Magic String is. So let's take a look at some notable "authorities". We can start off CodingHorror-style and

hit WikiPedia:

A magic string is an input that a programmer believes will never come externally and which activates otherwise hidden functionality. A user of this program would likely provide input that gives an expected response in most situations. However, if the user does in fact innocently provide the pre-defined input, invoking the internal functionality, the program response is often quite unexpected to the user (thus appearing 'magical')

Hmm - that doesn't quite fit with the imagined threat that a lot of my .NET compatriots think. In fact if you ask a crowd of .NET developers (if you were, say, at the MVP Summit this last week): "just why are Magic Strings so bad" - you might hear something like this:

There's no compile-time checking on a string. Duh...

The C# Compiler is a Magic-remover.

This doesn't make any sense. Let's keep looking -

Jimmy Bogard has this to say about Magic Strings...

*They don’t react well to refactoring

*It’s rampant, pervasive duplication

*They’re easily broken with mispelling

*If I change the name of the parameter in the Edit method, all code expecting the parameter name to be something specific will break. This wouldn’t be so bad if I had to change just one location, but I need to fix all places that use that parameter (likely with a Replace All command)

Jimmy was talking about Anonymous Types used as method arguments - where you pass a value off using something like:

Url.Action(x => x.Edit(null), new { productId = prodId })

Jimmy's supposition here is that "productId" is a Magic String. Even though it's not a string (it's an inline property declaration) - it's unknown to the compiler and therefore is magical, and subject to failure and the requisite horrors therewith.

Yah that doesn't make any sense at all.

I'm not feeling it. Let's dig deeper:

Just what the hell is a Magic String?

Andrew Siemer has another answer:

(snip) this topic is important to the average ASP.NET MVC developer ... those magic strings reference controller names, action names, area names, and possibly other types in your code. As long as nothing changes in your code these reference should not break. However, every coder knows that the very nature of coding is going to eventually require you to refactor your code including the magic strings that reference your code.

I'm not certain (as Andrew doesn't say specifically) but I believe that "magic strings" he's referring to have to do with Routing, HtmlHelpers, and various other ways you reference Controller/Action pairs in ASP.NET MVC.

The summary form here is that, if you change the name of your Controller - your code might break - and Visual Studio won't help you when you compile your code because, hey, those strings? Yeah they're not types that are statically checked at compile time.

Let's just cut to the chase here. If you ask a .NET developer what a Magic String is

they'll tell you that it's a part of code that can't be checked by the compiler.

Does this make any kind of sense? I don't think so either.

Compiling The Meaning of Your Code

There seems to be a bit of an impasse here. On one hand you have classical references (from Wikipedia - are they ever wrong?) to "Magic Strings" that suggests it has something to do with User Data and User inputs. On the other - you have a set of developers who don't trust anything that can't be compiled.

WTF? Has this term lost all meaning? Probably. But the truth is out there somewhere isn't it?

How about this definition from Chris Falter:

A magic string is a code that represents, rather than describes, the state of some entity. Allow me to illustrate with an example: many insurance companies obtain (with a consumer's fully informed consent) some personal data about the insured so that they can more accurately quantify the risk of underwriting a policy (and thus set the appropriate premiums). A vendor might return the marital status of the insured as a code from the following list:*M: Married

*D: Divorced

*X: Separated

*S: Single

*W: Widowed

*U: UnknownThe code "M" would be the magic string that represents the "Married" status, and so forth.

Hold me. This definition*makes sense

*suggests that "magic" is an appropriate term - because it has meaning outside the context of the application/code block

*has nothing to do with a compilerChris goes on to absolutely NAIL the problem with Magic Strings: coding around them and their supposed meanings:

Woe to the lazy programmer who uses those magic strings in source code like this:

switch (maritalStatus) // maritalStatus is a one-byte string
{ case "X" : DoA(); break; case "S" : DoB(); break; // etc. }

Could you understand this code at a glance? Probably not. Does "X" signify "Unknown" or "Divorced" (as in "My kid is with my ex this weekend") or "Separated"? Does "S" signify "Single" or "Separated"? If you have to read the vendor documentation in order to understand source code, you're in a bad place.

This, ladies and gentlemen, is the best description of Magic Strings you'll find. Not because I say so -

it's because it makes good, common sense and has nothing to do with a compiler.

Superstition, Fear, and Magic

Think about the number of times you've been through a code review and some smarmy, know-it-all punk geek (like me, for instance) says

Well Actually the code you wrote looks fine - except for all those magic strings...

Of course. Enums and Class abstractions will help the compiler rid my code of all that silly magic and voodoo. OK I'm being a bit snotty - let's get back on track. Using strings all over can be a bad thing - yes indeed.

Let's jump back to one of Jimmy's points (at the very beginning of the post):

*It’s rampant, pervasive duplication

When working with strings that signify a "state", "status", or some other meaning to your code - well it's tempting to write that check everywhere. You might do something like "if(status == 'current')" all over and YES - that will lead to rampant, pervasive string hangover.

Will the use of an Enum fix our rampant duplication problem? Does the presence of "if(status == Status.Current)" make me want to write it less? Hardly - if anything I get some itellisense here so I'm probably going to write it a bit more.

But Jimmy's point was also that we could use refactoring tools if we decide to change "Status.Current" to "Status.Bitchen" - but that's a tooling thing. It has nothing to do with magic, and moreover is the same as a glorified Edit/Replace. I have a hard time believing that an Enum and Visual Studio's refactoring tools are a reason to avoid strings at all costs.

And it's at this point you'll be saying

Dude - what are you suggesting? Use strings for everything now?

Of course not. I'm saying to drop the fear of them because it makes you do silly things. Stay with me and stop interrupting...

Strings Everywhere?

Let's take Jimmy's example above - the status example. If you decide to be DRY about things (and avoid "rampant, pervasive duplication") than you wouldn't put that conditional check ("if(status == Status.Current)") in more than one place in your code.

Instead you might consign it to a method or property like you should: "if(user.IsCurrent)" and inside the "IsCurrent" getter is a check against an enum or (GASP) a string.

Here's my ultimate point: you might not be led to think this way if you didn't have the threat of string comparisons throughout your code - you might be lulled into the comfort of "well I used an enum - I'm cool. No Magic Strings" - and leave it at that.

This is a false comfort - you're letting the compiler tell you that your code is correct and that you're a good person. This is also a little bit insane. Just because your code can be compiled doesn't mean it's good - let alone optimal. Using the compiler (and the it's ability to compile your code) as a metric for code quality is utterly ridiculous.

Again - I'm

not saying to use strings to convey meaning

and I'm

not suggesting you give up on Enums.

I'm simply suggesting that

the whole idea of Magic Strings has been obfuscated and FUBAR'd

to the point where your avoidance of them drives to you write worse code than you otherwise would.

You are the music maker. You are the dreamer of dreams - Magic is our business. It's what we do - and you should know the difference between "Magic", "Superstition", and Complete Silliness.

Blog Logo

Rob Conery

I am the Co-founder of Tekpub.com, Creator of This Developer's Life, an Author, Speaker, and sometimes a little bit opinionated.


Published