Thursday, June 7, 2012

The Basics

“This report, by its very length, defends itself against the risk of being read.”
- Winston Churchill

I know that programmers are very busy people, often chasing deadlines, fighting off pointy-haired bosses, and so on, and have therefore decided to condense the most important aspects of coding into a lesson you can learn in, say, 5 seconds.
Ready? Here we go:

Your priorities while coding:
  1. Keep it clear
  2. Keep it short
  3. Everything else (safety, performance, and other such nuances)

Alright, everyone who can’t spare more than 5 seconds is dismissed.
The rest of you, unfortunately, will have to put up with outrageous things like, for example, a more detailed look into these few ideas.

1. Clarity, for meta-clarity’s sake, means that a person who needs to understand your code right now can look at it and understand it. It doesn’t mean your mom needs to be able to recompile your kernel, it doesn’t mean your dentist should be able to optimize your code for Win2k on a 486. It does mean that a person who knows what this code does must be able to find particular bits of code that do particular things, and must be able to easily modify it to do different/ additional things. Because, you know, that’s exactly what programmers do with code.

If you have a module named CUpload which handles download operations and a module named CDownload which handles upload operations, your code is not clear.
If your database has 3 different columns named payment_id, payment_number and payment_code, any code that refers to them will not be clear.
If you’ve decided to take a 6-line function and write it in one line because pressing Enter increases your carbon footprint, your code is not clear.
Sadly, most of my other examples for unclear code are actually a result of it being too long, so let’s move on to:

2. Contrary to to what spam senders want you to believe, shorter is better. No forum troll has ever said “too short; didn’t read”. No matter how many times you fail your theoretical driving exam, you never stop to say “it would all be so easy if they replaced all these damn signs with carefully detailed textual instructions”. Time is money, and short things take less time than long things, and that’s not even half of the problem.

As far as I can tell, running into the proverbial wall of text feels rather like actually running into an actual wall, except for the medical bill.
When you see a cute little function where every line is nice and short, you are confident in your abilities to just sit down and understand it. Look how small it is! How complex could it possibly be? It’s just good old void StartMapping(), barely 20 lines, totally easy.
Then it calls DoMapping(), where just the for loop alone takes up over 2300 lines of code, and you get blocks that are 10 indentations in where you still can’t see their top and bottom at the same time, and every variable name is 50 characters because most of the numbers you need are sitting comfortably inside globalData.tT_MGR_GeneralData.initData... and it’s the mental equivalent of having been going full speed ahead when suddenly you hit something impenetrable and had to stop very quickly, and it knocked out your breath and you’re feeling confused and want to lie down.

I’m going to have plenty of things to say about clear code in the near future, but today I intend to keep talking about short code. The quote at the top was probably a bit of a spoiler for this.
But anyway:

Short is good.
Short is friendly and benign.
Short tells you, hey, come read me, it’ll be easy.

Long is bad.
Long is intimidating and dispiriting.
Long shouts at you, stay away from me, or I’ll devour your soul.

Here are some more reasons to keep things short:

  • Humans are generally predisposed to short things. They always make names shorter. I mean, how many people in the world actually call the city El Pueblo de la Reina de Los Angeles by its full name? And since your code should communicate with humans (even if they are programmers), better do it their way.

  • It doesn’t matter if it takes you only 10 seconds to read each function; most programmers have to read more than one function in their career (dozens in an average day, I’d say). Anything that makes this slower will accumulate quickly, and odds are that when the code is twice as long, reading it would take more than twice as long. So the benefit from keeping your code succinct will accumulate quickly as well.

  • Long code is unsafe. When a block fits neatly into the screen, it means you can see the whole thing at the same time, which makes it much easier to spot mistakes, see connections, compare lines and so on. You can probably have a function as long as a screen and a half, but beyond that it’s just much harder to simply see things that you need to see.

  • Programming properly generally involves holding a huge amount of information in your head; programming one function at a time is fine when you’re optimizing a loop, but once you have a few dozens (or thousands) or functions you have to remember a lot of things. Naturally, the shorter and simpler these things are, the easier it is to remember them, and the connections between them.

  • Humans really don’t like to read. I know, I know, you’re probably a geek and are reading this thing right now (and, I hope, suffering only slightly). Maybe you even read 3 novels every week. But you don’t do any of it because you enjoy the activity of reading; it’s all for the content, which might be interesting, educational, funny, or anything else. But nobody enjoys the actual reading enough to pick up a phone book and read it cover to cover, and source code usually resembles a phone book more than, say, The Hitchhiker's Guide to the Galaxy.

  • In a long piece of code you’re always searching for things, and they’re never there. If your function spans 1000 lines of code and your IDE only shows 50 at a time, that means that at a given moment the odds of immediately seeing a specific line you’re looking for is 5%, which is terrible. Since actual functions are much easier to find (distinctive names, keyboard shortcuts) than variables or function calls or whatever you’d be looking for inside a function (variables get referred to many times, functions get used many times, especially in a long function). Therefore smartly dividing your code into smaller blocks significantly cuts down the time of searching for things.

  • Reading long code really, truly, isn’t fun. Having to deal with all of the above points inevitably leads you to spend even more time brooding about how bad this code is and what unpleasant things you’d like to do to the person who wrote it, and generally makes you miserable.

To sum up: shorter code makes you faster, stronger, safer and happier. It’s almost like being a local superhero. I hope that the fact I divided most of the topic into short blocks, rather than spill it all into one big wall of text, helped to convey some of this idea, too.

At this point, some acute thinkers must be wondering: so should I really just give every variable a one-letter name to keep everything as short as possible? Won’t that turn everything into gibberish? To which I say:

Somehow, even though I wrote a instead of the quadratic coefficient, and b instead of the linear coefficient, and c instead of the constant term, I’d dare say that this expression is perfectly easy to understand for anyone with basic knowledge in algebra. And don’t get me started about how I replaced square root with that strange angular line!
In plenty of cases, yes, one letter truly is enough. When you’re defining a short, simple function with 1-2 parameters, possibly without any confusing local variables, assuming the function’s name is very clear, there is no reason to give the parameters longer names.
Let’s put that to the test right now. Here are several function declarations with one-letter parameter names, and to make it even worse they’re in a dynamically typed language so you have no types to give you hints. Is it in any way difficult to guess the purpose of any of these parameters?
  • IntFromString (s)
  • MoveWindowAbsolute (x,y)
  • AddMatrices3x3 (m,n)
Alright, to be honest I’m not really suggesting everything needs to be just one letter, and I specifically chose extreme examples. As I said, shortness is merely the second priority; but if you’re sure that whoever reads the code will understand everything from the context alone, then there is no reason to bother with a second letter.
In conclusion, you should always strive for shorter code as long as it’s easy to understand.
Don’t call a variable strShippingAddress when shipAddr will do.
Don’t let a function sprawl over 30 lines when you could do the same in merely 10, and never let it grow to 100 lines unless it's a really extreme case.
Just keep it clear, keep it short, and future generations of programmers will thank you for making it that much easier to debug, maintain, extend, use and read.

No comments:

Post a Comment