I’m sure that most of us in our programming careers have seen something like this…
public static int GetNextSize(int i)
//multiply it by four and make sure it is positive
return i > 0 ? i << 2 : ~(i << 2) + 1;
Wasn’t it nice that they at least commented the line? Ha. Well, maybe you have not seen something exactly like that, but I’m sure that you have seen something equally as asinine. And I’m also sure that when you saw this the first thing that went through your head was "why would anyone ever write something like this?" And surprisingly, the answer is that they did it because they are a programmer. Well, a programmer who is not in control of their urges. :-)
Most programmers love to be clever. In fact, we probably got into programming because we loved being clever. We loved writing small, streamlined code that ran faster than anyone thought it could and at the same time confounded all those who read it. The problem is that the programming world is quickly changing and one of my favorite quotes of all time no longer applies:
"Real programmers don’t write comments – it was hard to write, it should be hard to understand."
Now, obviously that never applied and I hope you realized that, but a fundamental shift started happening years ago that has really solidified now. The shift is that the complexity in software has moved from the smaller parts of the applications to the design of the application as a whole, and so the top priority for almost all code should be in how easy it is to read and write, because the systems that they are involved in have become so much more complex.
As applications get larger and more complex, we rarely have to worry about how fast we can read a file in, but we think long and hard about how to make the format of that file easy to parse and flexible. In fact, I remember when XML first came out and there were a good number of people that were predicting its downfall because it was so verbose, but that was actually its strongest selling point. There have been several "Binary" XML specs, but not surprisingly none of them have caught on because they take away the one thing that made XML so attractive, its readability and parseability. The thing that most of those people didn’t understand was that bandwidth would get cheaper, computers would get cheaper and faster, but people’s time will always get more expensive. The more simple and easier to work with (while still being flexible) a standard is, the more likely that it will be adopted. This has held true for HTML, XML, and sometime in the future it may even hold true for REST web services.
But as programmers these same rules apply, no longer do we get any credit for writing a routine that parses a file 5 percent faster, especially not if it makes the code harder to read, longer to write, longer to debug, or harder to test. No longer does a programmer get respect for using pointer arithmetic and bit-shifting in order to speed up math operations. These kind of optimizations (for the most part) are just pointless exercises that are often written for nothing more than the programmer’s ego. (And before you guys start ranting about graphics programming or physics modeling, yes, I do realize that there are places in the world for code like this) But that does remind me of one of my favorite quotes from "Code Complete" by Steve McConnell:
"Programming is not like being in the CIA, you don’t get credit for being sneaky."
(It took me a little bit to find that, my copy of "Code Complete" has more highlights than Paris Hilton’s hair)
So, if we don’t get credit for writing clever code anymore, then what do we get credit for? Well, we get credit for making our code simple and easy to understand. We get credit for loose coupling, for testability, for shallow hierarchies, for good exception handling, for fluid interfaces, for not giving our co-workers headaches, essentially for all around good design. We get credit for being good software engineers, not being winners of the International Obfuscated C Code Contest (although you will get a certain kind of credit for that, but you get my point).
Now hopefully anyone in their right mind would have written the method at the beginning of this post like this…
public static int GetNextSize(int i)
return Math.Abs(i * 4);
Without caring one bit about performance (of which I honestly don’t know or care what the implications are at this point) I can say with 100% confidence that this code is better. And why? Because I can immediately look at it and tell what it is doing. Even without the comment it is more readable than the code at the top that has the comment, and that is what we want, self-documenting code. Because as the Pragmatic Programmers pointed out, you don’t want to have to comment on what the code is actually doing, you only want to comment on the assumptions that were made in order to write the code. Information that cannot be derived just by reading the code itself. The only problem is that the more complex our code gets, the more and more we need comments just to explain what the code is doing.
And don’t think that I am saying that there is no place for optimization, that is not true, there is just less room for optimization in the source itself, but there is lots of room for optimizations in terms of overall system performance and in terms of developer productivity. It is more important to focus on the big picture and solve performance problems that are system wide, or refactor code so that changes can be made much faster, than it is to solve a performance problem in a single line of code…unless of course that line of code is being called 8 million times by 50 parts of the system.
So next time you go to write a super clever line of code, think to yourself "Will the benefits of this super cleverness be outweighed by the future issues in maintaining and understanding the code?" And if there is any hesitation at all, then you better not be clever, because 3 months from now you will come across that code and say "What the hell was I thinking?" Then you’ll end up rewriting it anyway.
And one final note, if you are the kind of person who just has to write super clever looking code that no one can make sense out of, then they have a language for you, it is called Perl. :-) (let the flames begin)