Need a Magic Constant? Choose Something Obscure

We all have various constants in our code, whether they are integers for use with startActivityForResult(), strings for Logcat tags, and so forth. Most of these are internal to our code and do not affect others.

Sometimes, though, we have an API that we expose that others might call, where certain parameters are up to the caller… except for some magic constants. For example, you might have a key/value data store, where you want to reserve some keys for your internal use, but others can stuff whatever they want into that data store using their own choices of keys. Those reserved keys are magic constants.

(IMHO, try to avoid such APIs, keeping your internal data separate so there is no chance of a key collision… but sometimes this API structure is unavoidable)

So, the caller of your API can choose any value for their keys, except certain magic constants. In that case:

  • Practice defensive programming and validate that a caller-supplied key is not one of your magic constants,

  • Document what the magic constants are, and

  • Choose obscure values

When it comes to NotificationChannel, we got two out of the three.

NotificationChannel has a DEFAULT_CHANNEL_ID constant. This is a magic constant, as you cannot use it as the ID of your own channel. If you try, you get a somewhat cryptic stack trace. But, that stack trace is because of the defensive programming, so that’s good. And the magic constant is documented, at least to an extent.

However, the value of DEFAULT_CHANNEL_ID is "miscellaneous".

That’s a reasonably common English word, one that somebody might well choose without noticing that it is not an eligible value.

Particularly with strings, you have a near-infinite space to choose magic constants from. So, it is easy to choose a magic constant that is unlikely to collide with any value that others might choose:

  • Use a UUID

  • Use a passphrase generated by diceware

  • Use a series of digits from a random number generator

  • And so on

Even if memory use is a consideration, it would be better to choose a random six-digit number than to use a common word. There are lots of obscure values that we could use that are shorter than "miscellaneous".

After all, neither the compiler nor the OS really cares about the actual value. Your own code does not care about the individual characters inside of the magic constant. It just needs to know that it can look up things using that magic constant and get what it expects.

Magic constants are part of your API and they need to be designed along with the rest of the API. It’s just that whereas normally you want things to be human-readable, this is one case where you do not. Or, at the very least, choose a less-common human-readable word, such as "axolotl".

(NOTE: no actual axolotls were harmed in the creation of this blog post)

Stuck on an Android problem? Subscribers have access to live office hours chats with Mark Murphy, to help you work through your challenges!