What Story Does Your Code Tell?
I’ve found that as the timeline of my life becomes longer, my capacity for surprise at my situation diminishes. And so my recent combination of types of work and engagements, rather than being strange in any way to me, is simply ammo for genuineness when I offer up the cliche, “variety is the spice of life.” Of late, I’ve been reviewing a lot of code in a coaching capacity as well as creating and giving workshops on story telling and creative writing. And given how much practice I’ve had over the last several years at multi-purposing my work, I’m quite vigilant for opportunities to merge story-telling and software advice. This post is one such opportunity, if a small one.
A little under a year ago, I offered up a post in which I suggested some visualization mnemonics to help make important software design principles more memorable. It was a relatively popular post, so I assume that people found it helpful. And the reason, I believe, that people found it helpful is that stories engage your brain far more than simple conveyance of information. When you read a white-paper explaining the Law of Demeter, the part of your brain that processes natural language activates and decodes the words. But when I tell you a story about a customer in a convenience store removing his pants to pay for a soda, your brain processes this text as if it were experiencing the event. Stories really engage the brain.
One of the most difficult aspects of writing code is to find ways to build abstraction and make your code readable so that others (or you, months later) can read the code as easily as prose. The idea is that code is read far more often than written or modified, so readability is important. But it isn’t just that the code should be readable — it should be understandable and, in some way, even memorable. Usually, understandability is achieved through simplicity and crisp, clear abstractions. Memorability, if achieved at all, is usually created via Principle of Least Surprise. It’s a cheat — your code is memorable not because it captivates the reader, but because the reader knows that mapping what she’s used to will probably work. (Of course, I recognize that atrocious code will be memorable in the vivid, conversational sense, but I’m talking about it being memorable in terms of its function and exact behavior).
It’s therefore worth asking what story your code is telling. Look at this code. What story is it telling?
if(person != null && person.Pants != null && person.Pants.Pockets.Length >= 2)
{
var pocket = person.Pants.Pockets[1];
if(pocket != null && pocket.Wallet != null)
{
pocket.Wallet.Remove(5);
pocket.Wallet.Add(0.12);
}
person.Leave();
}
Okay, so there’s a person with pants with pockets. We think. Assuming that there’s a person and that person has pants and that those pants have at least 2 pockets, we get the second pocket and store it as a local variable. Then we get the wallet out of that pocket, assuming that there is a wallet and that there is a pocket (wait, I thought we checked for that already). If all of that is true, then we take $5 out of the wallet and stuff 12 cents back in the wallet. Then the person leaves, assuming there is a person with pants and pockets. I guess if there’s a person with no pants, we don’t let them leave…? And, that’s the story.
So, if I’m creating an interface, what name do I give all of this that tells the story? I’m thinking:
public void Commit_A_Weirdly_Intimate_And_Specific_Petty_Robbery(Person person)
{
if (person != null && person.Pants != null && person.Pants.Pockets.Length >= 2)
{
var pocket = person.Pants.Pockets[1];
if (pocket != null && pocket.Wallet != null)
{
pocket.Wallet.Remove(5);
pocket.Wallet.Add(0.12);
}
person.Leave();
}
}
I mean, really, that’s probably as close as you can get. Of course, you might apply a benevolent interpretation and assume that there’s a more common domain being expressed here than street crime. Particularly given the removal of a larger sum and the addition of a smaller sum, you might conclude that this is a purchase transaction. But why does this purchase transaction need to know if the person has pants and how many pockets those pants have? That part of the story is more reminiscent of seedy chat rooms than going into the 7-11 to get a candy bar.
If you look at this actual code, you’ll notice the smell associated with extensive violations of the Law of Demeter. To put it more conversationally, why is this method receiving a person and then immediately plumbing, in extensive detail, the innards of Person’s implementation to tell it exactly how to maneuver those innards? That’s bad code and it’s a creepy story. There’s even a name for this code smell: Inappropriate Intimacy. The people who coined the name of that code smell certainly understand linking narrative with code.
How might this story actually go, when written in a way that you’d know easily how to name the method?
person.PayForMerchandise(5);
person.ReceiveChange(0.12);
person.Leave();
I think you’d be hard pressed not to know what was being modeled by this code. All of the logic that used to be strewn out in confusing but specific detail in this method is gone. Instead, the person is left to handle his own business, and the specifics of wallets, pockets, and pants are not the clerk’s concern. The names are clear, there is no quasi-confusing conditional logic guarding against a sloppy object model, and no one is diving into the intimate details of anyone else’s business (pants). This code tells a story, if a rather mundane one (well, you don’t always get to choose your domain). And, while it’s not as exciting as the pants-removal-heist that it started out as, it at least resembles what it’s supposed to model. Having a memorable story told by your code is doubly damaging if it’s the wrong story.
As you write your code, look at the methods and ask yourself all of the questions you’re used to asking yourself about whether your code is clean or not. Is the method compact and focused, without too much control flow? Is this readable? Does it conform to the principle of least surprise? Did I give the variables clear, understandable names? But go beyond that now and then. Look at the methods that you’re writing and ask what story is being told by them? If you have no idea, it might be that your logic is muddled, your abstractions poorly conceived, or any other number of things. But whatever the culprit, it’s indicative of a problem. Code smells all have vivid names that tell stories for a reason. Code that avoids those smells does so by telling the right story.
I hate the idea that this will make you think this was all I got out of the post, but this was totally worth reading just for the method name `Commit_A_Weirdly_Intimate_And_Specific_Petty_Robbery`.
I was about to write the same comment: the method name was pure gold.
If you ever see that method name in a code base, it’s probably a sign that you should run away quickly, for a variety of reasons.
Glad you liked, and I read nothing more into your enjoyment of the method name. I’d be doing pretty poorly teaching creative writing and story-telling if I didn’t sprinkle the occasional memorable nugget into a post 🙂
Never heard of the Inappropriate Intimacy code smell before, thanks!
No problem. Worth perusing that sourcemaking site in general too. They have a pretty good taxonomy of code smells.