Always write your code in a way that the next developer maintaining your code could be an axe swinging madman who knows where you live.
An unknown programmer (hopefully still alive and well…)
Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions and straightforward lines of control.
Grady Booch
For almost ten years now, I’m a freelancer in the field of software development. Effectively, I’m something like a well-paid stand-by man who almost always is supposed to work with an already existing codebase that needs to be extended or treated in some other way (e.g. refactored or covered with tests). An important part of the job is to quickly get familiar with this codebase – it’s the single key factor for my professional success. And to succeed, I’m reliant on the code being carefully crafted and not holding any surprises. That’s why I’ve come to value well-written code really high over the years.
In this post I wrote down my own five cents about code readability. While it originates completely from my personal experience, you can also consider the issue from a more objective basis. There are many studies that deal with code readability in some way or the other, but the single most important fact about it is this:
The ratio of time spent reading vs. writing is well over 10:1.
This is the objective reason why polishing code is not only some sort of cosmetical (‘girlish’) activity but really pays off in hard economical terms. It’s as simple as that: There’s no way to write code without reading it, so making it easy to read actually makes it easier to write.
The two aspects of good code
The minimal requirement for source code is that it has to be functionally correct – it just has to reliably work. But to write such code only means that a programmer has fulfilled the mere basics of his job, it is nothing that should be worth talking about. This is true from the absolute beginner to the rock star developer with decades of professional experience. However, there’s one thing that makes it easy to tell the beginner from the experienced developer: How his code feels, reads, and looks like – sometimes you can even see it from the overall picture that the code draws on the display, without actually reading it.
Essentially, there are two aspects to consider when it comes to authoring code:
- Pure text (e.g. code formatting, intention-revealing identifiers). Try to tell a good story. You don’t need to become a ninja in Literate Programming, common sense will do: Just write what you’d like to read. Then, ideally, it really reads like well-written prose to the skilled reader…
- Code structure and overall architecture: Use common design and structural patterns such as the GoF-Patterns on class level or structural patterns like e.g. MVVM or SOA on a higher architectural level. And – sometimes even more important – strictly use them in a predictable and conservative way. You should avoid it like hell to be creative or clever at this point. Instead, try to be as dull and narrow-minded as you can.
If you do that, the guy who comes next will be thankful and maybe value you as a good programmer.
To comment or not to comment?
How (and what) to comment? I don’t know a single developer who didn’t ask that question to himself at some point, and I’m also well aware that there are various heavyweight guides on this issue out there. I don’t know them. Instead, I rely on what turned out to be useful over the years:
- I usually ignore xml comments, because they tend to be outdated. (I’m well aware that mostly they are accurate, but ‘mostly’ just is not enough.)
- Instead, I like unit tests very much, because they are executable documentation, and they are intention-revealing. Also, a test won’t lie. If this sort of documentation is outdated, it will fail – straight and simple.
- The other type of comment that I like are in-code comments that provide additional information and tell me e.g. why something is done in a certain way.
In my world, API comments often are outdated, and sometimes they are simply redundant. They’re just not reliable enough. (However, there is one thing that you can rely upon: They obscure the actual source code.) Therefore, when I need to look up a method, I’m looking at the code itself as my primary source of information. Always.
For example, I have seen cases, where there are compiler warnings in place for lacking xml comments. And because the developers wanted these hundreds of compiler warnings out of the way, they used a tool like GhostDoc
to produce sth. like this:
1 2 3 4 5 6 7 8 9 |
/// <summary> /// Saves the specified some string. /// </summary> /// <param name="someString">Some string.</param> /// <returns>System.Int32.</returns> public int Save(string someString) { } |
… which is, ahem, not of much help. At the utmost, automatic text generation is good for a short laugh. But mostly, ‘comments’ like the above are simply disturbing – especially if the code is cluttered with hundreds of them.
My personal habits
So, how the code reads, looks, and is structured translates to bare money for me and my customers. These are some of my habits (Most of them go unconsciously, it’s just the way I’m doing things.) that I developed over the years:
- I’m used to structure my code into very small methods. My personal benchmark is 20 lines (including blank lines), but as an absolute rule, you can take this: The method must fit on the screen. When reading code, scrolling (in either direction) should be a no-go.
- I’m using lots of blank lines to structure the code inside a method body.
- I’m using very descriptive identifiers – I sometimes end up with almost ridiculously long ones. Remember: You have well over 200 chars at your hand ;-)…
- I’m writing xml comments only where they make sense and add value. In general, I’m using them only for interface definitions. I never use the compiler setting for xml file generation; or, if it should be absolutely required, at least I’m switching off the related compiler warning.
- I’m extensively writing unit tests. Some customers don’t like that, so I’m not doing it always in customer projects.
- One of my favorites in coding is deleting code. A shorter method is a better method, none at all is best (as long as the code is still easily understandable).
- I’m regularly reading code written by others. There is many well-written and not so well-written code out there (these days even large parts of the .NET framework itself). You will learn a lot from reading (and understanding) it.
- I’m used to have Coding Guidelines in place and make sure every developer in the team adheres to them. It’s a good idea to enforce them with tools like R#, StyleCop, or FxCop, preferrably in conjunction with team-shared settings that are committed to the project’s code repository. It does not pay to have religious wars on specific details (like e.g. whether placing the
using
statements on top of the file or inside the namespace declarations), but it is very important to be consistent and predictable.
Code reading is always hard. In the beginning it can be confusing, and sometimes even frustrating. To a certain extent, I accept that as part of my job – after all, it deals with complicated issues, and there is a lot to learn and understand.
And because code reading/understanding is so challenging in itself, one should strive hard to not make it harder than it absolutely needs to be.
What are your personal thoughts, experiences, and habits about this?