One of the real delights of programming is picking great variable, method, and class names. But an even greater treat is when you can name pairs, or even whole narratives, that fit just right. And the very best of those is when you’re forced to trade off multiple forces pulling in different directions. This is the story of one such case.
It started with a simple refactoring. We allow people to post arbitrary URLs in Basecamp 3’s chat, which we’ll attempt to fetch and display inline, if its an image, movie, or a Twitter URL. There’s a security concern where we don’t want to allow internal IPs in those URLs, like 127.0.0.1, and then have our Downloader class attempt to trigger an internal request that may sidestep other security precautions.
The specific policy isn’t as important as the fact that this precondition was originally just part of the Downloader class, but now I also needed it in our forthcoming webhooks API. Because just like with previewable chat URLs, webhooks allow users to set URLs that our system then calls. Same underlying security issue to deal with.
No problemo: Just extract the protection into its own module and call it from both spots. First attempt at naming this new module gave me PrivateNetworkProtector, which seemed like a fine choice until I considered the method names that’d work with it:
- PrivateNetworkProtector.protect_against_internal_ip_address(ip)
- PrivateNetworkProtector.verify_ip_address_isnt_private(ip)
Hmm. I didn’t like any of those choices. Both are a little too wordy and both include a negative. And come to think of it, I wasn’t even that thrilled with the word Protector. It implies something like surge protection, where it just negates the effects of an outlier input. That’s not really what’s going on here. We’re on the lookout for malicious attempts, so a better word would be more forceful. More focused on a threat, not just a risk.
Let’s see what the programmer’s best friend, the thesaurus, had to offer:
Lots of possibilities there, but the one that really spoke to me was Guard as in PrivateNetworkGuard. Nice. Now I can imagine some big burly fellow checking credentials with an attitude. Just the right image. So back to the right method name. Let’s try the two choices similar to what we had earlier:
- PrivateNetworkGuard.guard_against_internal_ip_address(url)
- PrivateNetworkGuard.verify_ip_address_isnt_private(url)
Hmm, neither of those are right either. I mean, you could use guard again, but the double confetti of this repetition just annoyed my sensibilities. What if we thought of the Guard as something like a prefilter, like before_action in Action Controller? That’s promising:
- PrivateNetworkGuard.ensure_public_ip_address(url)
- PrivateNetworkGuard.ensure_no_private_ip_address(url)
Still not quite right. The ensure verb just doesn’t quite fit with the forceful idea of a Guard. It’s too meek. This isn’t a casual checking of credentials. This is IF THIS HAPPENS, I’M RAISING AN EXCEPTION AND BUSTING THE REQUEST!
That lead me to think of the programming language Eiffel and the concept of design by contract. So I browsed the Wikipedia entry to see if I could mine it for a good word. Eiffel uses require to state preconditions, which is what we’re doing here, but that also didn’t see right: PrivateNetworkGuard.require_public_ip. That’s more like something you’d write in a specification to tell well-meaning actors what they’re supposed to do. This wasn’t about well-meaning type, but rather the nefarious kind.
So I tried the thesaurus again, going off ensure for alternatives:
No great candidates here. I mean, they’d all work, but they don’t feel quite right. And that’s really what this whole expedition is about. Not just finding something that could work, but something where you go: Yes! That’s perfect! How about something in the realm of Guard then?
Nope. That doesn’t do it either. But one word stood out as an idea: Police. The Guard is policing the incoming ip addresses to make sure that an internal one doesn’t slip through. That’s interesting. Let’s keep pulling on that thread:
ENFORCE! That’s it. Let’s try it out:
- PrivateNetworkGuard#enforce_public_ip(url)
- PrivateNetworkGuard#enforce_no_private_ip(url)
In some ways I like the negative version better, since it strikes to the heart of the responsibility: This is about catching those malicious URLs with private IPs more than its about vetting that something is public. Two sides of the same coin, perhaps, but still an important distinction.
In the end, though, I went with PrivateNetworkGuard#enforce_public_ip(url) because I liked keeping a positive method name more than the slightly more apt negative version. Weighing those two subtle trade offs and picking the concern that mattered more.
Now this might seem like a lot of effort to expend searching for a slightly better name, but it goes straight to the heart of programming with a smile. I ventured out to find a great name, not just a passable one. And besides, this whole exercise might have taken five minutes at the most. So not exactly blowing the budget, but definitely lifting my spirit. Isn’t programming great?
Basecamp 3 was laboured over with tons of this kind of excessive/obsessive care. You’ll never be able to tell, but you can trust that we put this sort of consideration into the product in all sorts of other ways that are visible. It’s fun to bother with quality that can’t be seen.