This guest post is by Evan Light a test-obsessed developer, the author of several rarely used gems, and the curator of Ruby DCamp. When he’s not a talking head at conferences, he’s usually working at home as a freelance developer remotely mentoring a developer, working for one or more startups, playing with open source, keeping his wife and four cats company, hacking nonsensically, talking at people on the internet, and/or attempting to lose weight (or any combination of the above). What else do you do when you live 3 hours from civilization?
Why should I care?
“The hell with clean code!1, you say. “I’ve got stuff to get done!” You beat on keys for a while. Characters appear. The characters don’t make a lot of sense but, hey, the compiler compiles it or the virtual machine interprets it. Things happen. Eventually, an application emerges.
Success? Hell no!
Most of the time, someone has to maintain that pile of crap you just birthed! It may be someone else. It may be you! But it’s always wise to pretend that the person who will own your code next is an axe-wielding lunatic who knows where you live.
The worst sin that I’ve seen people make in their code: choosing poor names… for their classes, methods, literals, you name it.
“I don’t have time to sit around thinking about the perfect name for a class! Besides, I know how the code works! I can fix it.”
Oh, yeah? You may now. But how about in a month? Or three? Or a year? Wait… will you even be working for this company or on this project in a year? Who inherits this code?
Prototypes, spikes, and other rationalizations
Occasionally, developers invoke the “p” word: prototype. Prototypes are ugly little creatures that live only a short while.
At least that’s the myth.
The truth of the matter is that prototypes don’t exist. Prototypes don’t get thrown away. What happens when you show a manager working code? He says, “Great! Here’s your next feature!”
“But…”, you start to say.
“But what? It’s working! Marvelous! Right, here you are. Next feature!”
Heard of a “spike”? That’s basically a small prototype that you may not tell management about. You spend maybe 30 minutes working on one. The pain of throwing away the code is lessened. But even then it may offend your sensibilities. And that code is going to be ugly too.
We tell ourselves that the code will be temporary. Most of the time, this just isn’t so. These techniques are rationalizations for writing ugly code that will likely outlive its intended lifespan.
Think about the future!
So don’t throw that code away! Don’t prototype. Don’t spike2.
Dave Thomas sometimes describes writing an application as writing a Domain Specific Language. That is, creating an application is akin to developing a semantically meaningful API to describe an application’s behavior.
Therefore, the smartest thing you can do, when starting a new application, is to cultivate an understanding of the overall problem the application is intended to solve.
How can we do this? Personally, I favor contemporary Test Driven Development techniques:
For a given feature:
- Describe, in English, what the feature is trying to accomplish
- Exercise the API that I wish I’d write as a test
- Make the test pass
- Compare 1 & 2
For instance, consider this simplistic example:
Names should match intent
The English uses the word “subscribe”. That’s the action that I want the user to perform. So I make it the method name because that’s what I want to tell the user to do. That’s the message that I want to send the user.
Now what if I need an entity to representation that relationship between a User and a Plan?
I’ve seen (and written) some egregiously bad code in situations like this. Once upon a time, my initial reaction would be to call such a thing a “UserPlan”.
That’s just vile and disgusting. Sure, it conjoins the two entities but it does so like Siamese twins!
The better answer should be in plain sight. I used the word “subscribe” in the description! Call that entity a “Subscription”!
But maybe your description was
That would probably cause me to write sample code
It’s still valid though I did less to model the relationship between the User and the Plan because words matter and naming matters.
So what happens when we name things badly?
Is “UserPlan” so bad? Perhaps not. But UserPlan only represents a relationship between two entities. Perhaps I need a greater monstrosity to make the point plain.
So what is a SelfpropelledFourWheelGroundVehicle? It’s pretty plainly a Car/Automobile. But it’s a disgusting name. Yet these are the kinds of names that people frequently use in their code due to lack of effort!
Or there’s the other direction: Haskell developers often like to abstract functions such that they have no clear applicability to a domain. That is, their functions will have semantically meaningless variables such as “x” and “xs”. I’m told this is because Haskell has its roots in Lambda Calculus. Be that as it may, mathematical variables have only place in code: in implementing a mathematical calculation!
How would you feel maintaining code where the classes, literals, and methods read like that?!
How productive would you be working in such code? If you cannot trust the names in a code base to accurately represent the ideas at work then you need to understand vast swaths of the code base to be the least bit productive!
If you did not before, I hope that you now have a better appreciation why it is worth your time to get the names right in your code. It will make yours, your colleagues’, and any who later touch your code lives better and more productive.
And if you don’t use good names, I have an axe and I know where you live.
I hope you found this article valuable. Feel free to ask questions and give feedback in the comments section of this post. Thanks!
Subscribe to the waiting list of the free, online “Intermediate Ruby Course“.
- Robert Martin also wrote about this topic, and, in part, inspired this diatribe with the first chapter of his book, Clean Code. ↩
- Yes, this is a sweeping generalization. Yes, I occasionally spike on code. However, I only do this for technically challenging pieces which is to say very infrequently. And I throw my few spikes away. ↩