Let's keep it real for a second: it's really easy to write shit code. It's particularly easy at work where there are tight deadlines, bad legacy code, ambitious 'idea people' who don't know what technical debt feels like, where money is involved, where you can lose what feeds you and your family if you don't deliver. I get it entirely. However, none of that excuses a care-free attitude towards sustainable output.
There will always be plenty to worry about. One would assume that because there's so much that can go wrong, generally, developers would aim to produce manageable code. Instead, there exists an all-too-common nonchalance towards the dangers of poorly written software. I'm absolutely sick of it. (*Brace yourself for what seems like a rant of a pedant. That's not what it is. It's a rant of a good guy who wants people to be a little more considerate. That's what the world needs, after all.)
I'm sick of hearing shit like
- "It's self-documenting."
- "That (method|function) name is too long."
- "We'll know this means..."
- "Just tweak it."
Back in late October (2015), Linus Torvalds went on a rant over some code he was reviewing in the networking layer of the Linux kernel. Mind you, this man's contributions to software can be found in some of the greatest innovations the world has seen in the last two-and-a-half decades. Still, even at his level of historic excellence, bad code gets under his skin. So, he was reviewing some code and was so mind-fucked by what he saw that he publicly went off and wrote
Anybody who thinks that code like this is "safe" and "secure" because it uses fancy overflow detection functions is so far out to lunch that it's not even funny. All this kind of crap does is to make the code a unreadable mess with code that no sane person will ever really understand what it actually does.
What's this guys problem? Is it his ego? Is he just too stubborn to use new, fancy overflow detection functions? No and no. His only problem is that he cares too much. He considers the other engineers who don't want to spend a week learning to use a piece of code they can't avoid using. He considers that surprises related to the way a component of software works are not good and should be avoided.
Torvalds called the code he read an "idiotic, unreadable mess" that, to boot, didn't even solve the problem the author was trying to solve. I respect Torvalds for this and so should you. But why? Why should one respect the sentiment of Torvalds, the view that he and I share? Well, quite frankly, if you have to ask, you simply don't give a damn about what you're creating on a regular basis as a craftsman of software.
Writing good code is about being considerate of others. It's easy to consider those you're obligated to share code with, like your teammates at work. Extreme: If you die tomorrow, will your team know how to function without you? Less extreme: If you quit tomorrow, will your company have the ability to hire someone in your place and continue being efficient in keeping competitors at bay by growing its list of features? More extreme: What if your kid dies tomorrow? The last thing you'll worry about is your job, right? But, how will you feel knowing that because no one at work could learn what you built, some of your teammates were let go? Your superiors thought that your teammates' subpar throughput was a direct result of their inability to adapt. Because output can be measured and "numbers don't lie," your teammates are stuck thinking of ways to scrape up rent as they look for work. Knowing that probably won't help you get through your mourning and it may be the only additional realization it takes to cause you to commit one more selfish act to the world.
Can shit really get that real? Totally. I genuinely believe that. I believe that writing code like no one else will have to read it may cause your suicide. The suicide may not be skin off my back, but whatever caused you to do it may be. There's no reason to entertain that possibility, so let's start doing at least three things as we develop software from now on:
Keep our humanity in mind. Most of us communicate through natural language. Most of us need shit explained, even simple shit, even the smartest of us. I won't get into the specifics of what this point means with hopes that if you're really serious about giving a damn, you'll internalize the point eventually and come up with a ballpark interpretation that'll make the world better. Don't make me look bad. Just try.
Write comments. Explain what's going on. Philosophical bullshit aside: someone might need to do what you did using code you wrote. That person could be someone on your team or someone who's searching GitHub's public repo base. Who they are should be of little concern. Just explain what's going on. Period.
It usually takes less than a minute to write a good doc string if you've thought about the problem you're solving. If it doesn't, that probably means you don't know what you're developing and you're just writing code, guessing along the way. Therefore, writing a doc string shouldn't just help someone reading your code, but it should also help you identify whether you're ready to write code to begin with.
Write docstrings at the beginning of methods/functions, as well as one-liners in the body of those methods/functions. At the very least, write a docstring stating what should populate the parameter space and what the method/function is meant to return. I mentioned Linus and the Linux kernel. Its source doesn't contain much inline documentation, but there are enough hints available throughout each module to provide any new reader with a picture of what's going on. For example, in
net/bluetooth/sco.c you'll find comment strings describing categories of functions. Although the module lacks lots of line-by-line explanations, because of the comments and descriptive function names and variables, you can tell what's going on. The comments become a huge aid when you're trying to get a feel for what's going on. You'll understand
static void sco_conn_del(struct hci_conn *hcon, int err) because of its name, and a tiny comment in its body
/* Kill socket */. Do you think it was so hard for the author to write those comments? I doubt it. I bet the extra tiny step of doing so even helped him/her organize his/her thoughts. And this is C we're talking about, which contains syntactic constructs much more complicated to follow than those of, say, Python.
Finally, use descriptive variable names, function names, method names and module names. HOLY SHIT AM I TIRED of seeing one-character variable names. It's 20-fucking-16 and the industry is still riddled with lazy, inconsiderate fucks who still think it's okay to write nondescript, important components of software code. Stop assuming it's okay to write "d" to represent "dog" in a loop through a list of dogs. It takes two seconds to write out the full word and it'll be pretty helpful to everyone.
In terms of function and method names, just be as descriptive as possible. The length may seem excessive sometimes, but that's much better than having to reference something nonintuitive.
BONUS: STAY THE FUCK AWAY FROM HARD-CODED INDICES AND OTHER AMBIGUOUS NUMBERS Oh my FUCKING GOD. HOLY SHIT AND A PILE OF BOLOGNA. Are you fucking kidding me? And I'll be the first to admit that if you're under the gun and simply see no other way to do what you're doing, feel free to write those numbers. BUT, leave a comment describing each of those numbers before submitting that pull request. And, the second you get a chance, fix that chunk of code.
I bet living legends like Brian Kernighan are preparing to turn over in their graves as we speak because all of their comments on how code is meant to be written have gone ignored by the majority of folks out there.
Examples of what your code should look like if you give a fuck:
- https://github.com/python/cpython - The CPython code is really well-documented and well-written overall.
- https://github.com/django/django - The Django core. Nicely done, IMHO.
- https://github.com/OpenRA/OpenRA - OpenRA. Huge fan of C&C Red Alert. Turns out this open source version of the game is what I also consider well written. Take a gander.
- https://github.com/tensorflow/tensorflow - TensorFlow. Yeah, I don't use it. Only took a minor look at what it offers (I currently have no use for it). Still, I found the code base to be a pleasure to read through. Go ahead and randomly open one of the modules. Very clean, IMO.
I'm not asking for much; I'm not begging for perfection. Just meet me halfway. Make the landscape friendlier. You're not the only one participating in its construction.