I am convinced that the same applies to source code. In almost all cases, source code will be read much more often than it is written. Who writes the source code? You. A function is developed over some limited time, and once it is done it changes rarely, unless being refactored or modified to accommodate some changed requirements.
But who has to read your source code?
- Well, for starters, your colleagues who have to integrate with or use your code.
- New hires who join your team and try to find their way around.
- The maintenance (or continued engineering) programmers.
- Those who come after you, or inherit your code as part of their responsibility
- You.
We can see that over the life-time of some piece of code, it is very likely to be read much more often then written or modified. Consequently, source code needs to be read optimized just like we might read optimize a data structure or database if called for.
What does it take to read optimize source code? Here are the key points:
- Meaningful variable and function names.
- The compiler doesn't care whether the function name is 3 characters or 30 characters long. However, a colleague reading the code will be very grateful if the function is called
get_daily_rainfall_average()
, rather thandra()
. Who cares that it takes two seconds more to type it? Many modern IDEs are going to do that for you anyway. - Thoughtful source code documentation.
- Explaining in one sentence what some code does and in possibly many more sentences why it does it and why it's needed. The why is often much more important then the how: Explain the rational behind your design or implementation decisions. Everyone can see that a variable is increased in a for-loop, that doesn't have to be documented. But why the for-loop is needed in the first place is much more interesting and illuminating to someone who is new to the code.
- Comments like this should be there for each module, class, function and the more complex code blocks within a function. Keep the comments close to the code they refer to. If they are all in the function or module header, they are often forgotten when the internals of code are changed, 15 pages further down.
- A legible and consistent coding style.
- We can endlessly argue about which style of parenthesis is the right one, but what's more important is that you remain consistent throughout your project.
- If you are new to a team, use the coding style they use, even if it's not your favourite one.
- Unless absolutely needed for performance reasons, don't try to optimize your doubly-nested loop into a fancy single line statement, exploiting even the most esoteric features of the language. Instead, break it up into a more easily understandable set of spelled out loops.
- In general, don't optimize your code until you know you have to! Not only does it waste time if it turns out that the code really isn't performance critical, it is often also much more difficult to read and maintain.
- If you can do what you have to do with simple and often used language features then use those.
- Use white-space to make code less 'dense' and increase legibility. Many developers have pretty large screens these days, white space doesn't cost money.
- Align code. For example, if you have several variable assignments, align the '=' operators directly underneath each other. It's astonishing how much more legible that block of code becomes. If you have to line-break a long function call, indent the arguments of the second line to align with the start of the arguments in the first line. That's just a little example, but there are many cases like this in most programs, where a bit of thoughtful alignment can make a difference.
- "I don't want to write comments, because then I will have to scroll more to see the code."
- "Writing comments in the code takes time."
- Formatting the code nicely takes time, especially when I need to change a few things, in which case I then have to re-format the code.
- "Code changes, and before you know it the comments are obsolete."
In fact, I claim that if you don't take those rules to heart in your own source code then you are either unprofessional, lazy, not a team-player, or all of the above. If you as a software developer take pride in your professionalism and quality of your work then you have to consider that it is not only the achieved functionality for which you are being paid: The code you produce in almost all cases becomes property of your employer. Therefore, the code itself also becomes a product you deliver, and actually your most important product.
How useful and usable your code is for the team who has to work with it is what really determines its value in the long run.
You should follow me on twitter here.
I like your article, well written and informative.
ReplyDeleteAmen, brother
ReplyDeleteI actually had an interesting experience regarding this: I just open-sourced a piece of software (http://github.com/groby/iCalFix) that I considered quite reasonably written in terms of readability.
ReplyDeleteUntil I pulled the trigger on pushing it out in the open. Suddenly, I *had* to spend another 4 hours on it because it was in a shape that I'd consider completely unacceptable. Not that the code changed - just knowing it'd be exposed to an audience made all the difference.
It was a fascinating experience, and makes me appreciate open-sourcing even more. Just the *prospect* of being judged by readers of the code (nobody actually has spent any time looking at it so far ;) significantly changed my quality standards.
And I swear on a pack of bibles - if I didn't consider it a mostly dead project, I'd probably spend more time cleaning this up ;)
I tend to agree with all your points, except the one about commenting. I think the importance of source control management systems is currently underplayed by programmers. The "why" part is often a function of time (we started with design X, then realized that didn't work because of A, then shifted to Y, etc).
ReplyDeleteIf you try to document the progression of code in the code itself, you end up with long rambling comments that are hardly maintained. I posit a better way of working is hiding the historical reasons in the SCM and having just brief comments that explain the current design tradeoffs in the code. I think people don't do this because the current SCM history browsing tools suck. But some day we'll get there.
For a longer example of what I mean, see this blog post.
@ob: Thank you for the comment. I agree that the 'why' part can change. However, please see what I wrote about the 'obsolete comments': Code reviews can be use to address this. I have never suggested to document the progression of code (I assume here you mean the evolution over time) by means of code comments. Instead, once the code has addressed an issue differently, the comments regarding that particular piece of code should be updated. As you said, the 'current' design tradeoffs are usually all we are interested in.
ReplyDeleteGuys guys guys, slow down. Here is a much better article:
ReplyDeletehttp://freeworld.thc.org/root/phun/unmaintain.html
@Anonymous: Yes, that classic article is much better! :-)
ReplyDelete"The compiler doesn't care whether the function name is 3 characters or 30 characters long."
ReplyDeleteUnless you have to interoperate with old C compilers/linkers, in which case you may have to worry about making the first six characters of your names unique. Pretty rare these days, but not totally gone.
This is a pretty good article, and I agree with almost everything you have stated. However, I tend to disagree with your points on comments. I think that the code should document itself and the best way to do this is with testing. When you develop with a testing mindset, your will have smaller business concepts and functionality concepts broken into seperate testable methods. The test methods act both as documentation to describe what the code should do and *also* tests to make sure that it actually acts as it is intended. That being said, test methods should also be descriptive of what their functionality actually is.
ReplyDeleteYOU DON'T OWN THE CODE. The company does.
ReplyDeleteThat's what I tell my staff. Sometimes people forget that.
I couldn't agree with this more. In the majority of cases, the time that a subsequent developer loses trying to understand "super special optimised code" will never be made up at runtime by the optimisations that took so long to understand.
ReplyDeleteI always explain that even independent devs work in a team, always including their future selves.
ReplyDeleteI couldn't agree more with the entire article.
ReplyDeleteAt my first corporate gig, it was amazing to me how bad the coding standards were (actually there was none in this 10+ year old company) and how resistant particular staffers were to doing something as simple vertical spacing let alone = or , alignment.
I have another suggestion for this article - eliminate tabs in your code if you're able. There is nothing more troublesome than opening up a piece of code in Emacs, or Notepad (when you don't have a real editor), VC++, Code::Blocks, or Eclipse, and have a mess because one editor uses tabs of 4 spaces, and another uses tabs of 7 or 8, or whatever. Tabs aren't consistent, so remove them entirely from your code - every editor allows you to do this. Tabs are the biggest problem I run into.
ReplyDeleteSecondly, comments should explain entirely a function's function, it's a good check to see if the code is right. If the comments don't agree with the code, you're not done. Comments should explain a function well enough that the comments alone can be used to entirely re-implement the function to make it work. I know this isn't always practical, but if you do this, you can distinguish between intent and operation of a function. Even I don't always follow this rule, but I try to.
Aligned assignment code tends to decrease readability in my experience. When you have short placeholder identifiers like 'i' mixed with long descriptive identifiers, aligned assignment introduces too much visual gap between lvalue and rvalue.
ReplyDeleteOn the other hand, for complex conditional expressions (such as those spread over more than 2 lines), alignment corresponding to logical expression tree nesting is essential.
Good job! You really kicked the asses of those straw men.
ReplyDeleteComments should only be used to elucidate code that is not self-explanatory. Any comments take away visual space from code, possibly preventing the ability to view an entire block on a single screen.
ReplyDeleteThat being said, it's almost always useful to have a class-level javadoc comment that goes into detail on what the class does, and more, depending on whether the primary users are white-box or black-box users.
If the class is being used primarily by white-box users, then unfortunately this does require more verbosity, as these users will use the Javadoc as their primary reference, not the code itself. Some of the impact of this can be minimized, however. Typically, people put the javadoc comment start, "/**" on a line by itself. If you need a short javadoc comment for a bunch of single line property definitions, it would be effective to start the comment with "/** Start of comment ...". That makes for one more line that can be seen on the screen at once.
Juergen,
ReplyDeleteGood article. One of the best compliments I heard one programmer give another is "Your code is very simple to understand." Your ideas overlap with Donald Knuth's Literate Programming concept. You may find http://www.literateprogramming.com/ interesting.
I like much of what you are writing, readable code is much more cost effective than the big-ball-of-mud like units that I some time come across. I wish that some software managers would finally understand that cleaning up, refactoring and making the code purdy actually pays off.
ReplyDeleteAlignment of code may start out good. But I at up to my neck in what
used to be aligned comments/assignments/declarations but what is now a mess. Old comments may be a problem, but if you are lucky they will get updated once in a while. Who bothers with some broken alignment? None of the developers I am working with, that's for sure. And then you get the long variable name, that some indents, other don't, in any case it looks bad.
I am completly for a consistent style in coding. But on a per-unit basis is enough for me, I am proficent enough in my languages to read and write most coding styles, not only my favourite. The problem with consitstent styles is when you actually have to use energy on following the style, the people start slacking off. And aligning code is one of those.
That text is full of "good use" tips ! It should be teached at school !
ReplyDeleteSimple, factual, clear enough ... Really it's great !
I create a cumputer game. My code is a bit dark. Thanksfully, I still make some comments. On 200 000 lines, more than 20% is comments. I'll keep my way for this project, but I'll might use some more comments, just to practice your tips ^^.
Kéké
PS : sorry for my language. I'm French, and so is my game.
PS : I read your blog from here : http://forum.jeux-web.com/index.php?topic=78 , just in case you want to speak with us ^^ (it's a french cumputer developping games' forum.)
This is really great advice. I look at code allot and the ones that are the easiest for me to read and decifer are the ones that have lots of notes. Yes it does take a little time but it the code ever needs to be refactored in any way, by you or anyone else, notes will help you remember what you were thinking and why that line of code is there and not somewhere else. Thanks for the post.
ReplyDeleteI have seen many companies who write the code in very complicated way. They think that it is a customer retention policy as no one will able to read and re-engineer/construct the website. I strongly dislike this kind of shady activities. To me code should be always easy to read and understand by any person. your post can surely help to optimize the coding.
ReplyDeleteThanks for sharing,
Susan
Please see http://google-styleguide.googlecode.com/svn/trunk/javaguide.html#s4.6.3-horizontal-alignment
ReplyDeleteIf you maintain a large code base with lots of developers, you are not going to be a fan of vertical alignment.