How disciplined are you in coding? No, seriously, are you a mad code hacker or are you one of those who takes that extra bit of care while coding? Are you paranoid about comments or do you believe comments are not needed especially for trivial code snippets? Why am I raising these questions? It so happens, I was helping someone out (very recently) to port code across platforms and I happen to look at a piece of code, or rather pieces of code, that were an utter disgrace to coding standards. No comments, headers included in headers, crazy loop-backs across libraries, 10 people writing code all over the place, use of non-standard practices, utter disrespect for memory management and zero design (high level or low level). Can you believe somebody using malloc to create a C++ object! I mean seriously, you could hire monkeys to do a better job than that!
OK enough of the rant already! I can’t really disclose who the code was for, since it is production code used by a reputed organization. Yeah believe it, I still can’t, but it just goes to show how disconnected the organization is with respect to what can be considered as their most valuable asset. No wrong it’s not code, it’s the process! It is not that they are not paying for it, they are, but the management is, well, too stupid (for lack of a better word) to understand the implications of not having proper coding discipline. On the flip side, you will find some organizations where the coding discipline is so rigid that it rarely allows even simple adjustments to the existing process. When coding practices are made far too rigid it hampers free thought and ultimately retards innovation. This is the other end of the story, where companies are paranoid about coding standards and don’t realize the fact that having inflexible coding practises can be in some situations counterproductive. Standardization is important, and having standards does help in many activities including coding, debugging, code reviews and can ultimately determine the quality of a product. Having standards helps maintain discipline in the team. In the above case, since the team did not maintain any standard the code just fell apart over time.
However, overdoing it can also lead to problems. Many times people simply don’t understand what a “coding standard” is. I can sight an example here; I was once involved with the team where the coding standards didn’t permit the use of RTTI. The wisdom behind that was, “RTTI breaks polymorphism”. Yes very true and RTTI should be avoided whenever possible. However, lets not be paranoid, in some situations it does help. RTTI when used subtly can solve problems which may require re-engineering of design. Not all class relationships are monolithic and RTTI can help you in such situations. I am not saying overuse RTTI, I am just saying RTTI has it’s place. To make a commandment like “Never use RTTI” is just plain lunatic. In our case it lead to breaking up of one class definition into smaller classes which ultimately lead to over-engineering of the solution. A problem which otherwise would have had a very straightforward approach was now distributed into a bunch of classes which had no real use other than to adhere to the “Never use RTTI” rule. Come to think of it, was that even a “coding standard”? This is what I can call invasion of standards on practises. Meaning in a attempt to have standards and discipline, the team/project leader went overboard and ultimately invaded on what was a design decision. It’s definitely not a coding standard.
Coming back to the code I was working on; the other thing I noticed was an attempt to do preemptive optimizations. Preemptive optimizations are an attempt to increase the run-time performance of a program during coding and/or design. While it’s not to say that you downrightly use bad practises, it often a folly to preemptively optimize code by what you think might be right. That’s because unless you are absolutely sure about what you are doing, you will have wasted your time or in a worst case actually made the code slower. What you think might be right is often not the case. One thing I remember out of the code I saw was multiplication by 0.5 to halve an integer value instead of division by 2. The reason, someone somewhere read that multiplication is faster than division on CPUs. Now this is downright crazy, because not only did it not optimize the code, it actually made it a whole lot slower. No one bothered to verify if this was indeed true. This is the type of noobish oneupmanship procreated by budding programmers who clearly have no real-world experience. A division by 2 produces
mov edx,DWORD PTR [ebp-12]
mov eax,edx
shr eax,0x1f
add eax,edx
sar eax,1
whereas a multiplication by 0.5 produces
fild DWORD PTR [ebp-12]
fld QWORD PTR ds:0x8048720
fmulp st(1),st
fnstcw WORD PTR [ebp-22]
movzx eax,WORD PTR [ebp-22]
mov ah,0xc
mov WORD PTR [ebp-24],ax
fldcw WORD PTR [ebp-24]
fistp DWORD PTR [ebp-8]
fldcw WORD PTR [ebp-22]
The code produced by the multiplication is slower than the division by several orders of the magnitude since the FPU gets involved. Why did that happen? Simple, because the compiler is a lot smarter that you give it credit for. It saw the division by 2 and quickly guessed the best way to halve a value was to use shift ops. Looks like we have a winner here and it’s not the programmer. It may happen that an optimizing compiler might be smart enough to even optimize this piece of code, but my point is there was no need to go for preemptive optimization in this case. Modern compilers are pretty smart, a for(int i = 0; i < 4; ++i) will produce the exact same code as for(int i = 0; i < 4; i++). Don’t believe me? Verify it. Oh yes and please don’t use a compiler from the 1990’s and complain. Something like a GCC 4.x series or a VC 9.0 is something all of us should be using right now. The only way to really optimize anything is via a performance analysis tool like Vtune or Codeanalyst and not make blind assumptions of what you may think is faster. Please note 10% of the code takes 90% of the time. The other 90% code may require no optimizations at all.
The other thing that got me really annoyed was the fact the code was poorly commented, or should I say rather inconsistently commented. No comments on function definitions, inconsistent inline comments, blocks of code without comments at all, algorithms explanations placed out of scope often in some other .doc file. Just a garbled tub of lard! OK everyone knows comments are a must, but very few programmers actually understand how good comments ought to be written. Properly commented code will boost productivity significantly. That doesn’t mean you have to over comment. It’s a case of working smart rather than working hard. It’s quality vs quantity. I wanted to write more on this but I figured the blog entry would get rather long, instead I will provide a link to relevant info and of course to doxygen. Please people do everyone a favor and use doxygen style commenting, please please! The another thing I advocate is keeping all documentation close or rather easily accessible. Most documents that are created never get read or never get read at the right time because they sit in some obscure directory on some machine somewhere. The intension of creating the documentation is undoubtedly noble, however none of that is of any real help if the documentation is not accessible at the right time. With some rather trivial tweaks to doxygen, you could easily make it happen. We tried something like this and it was a great hit.
It’s not the first time I have worked on such a piece of code. But still I find it difficult to understand how reputed organizations can work this way. Let the facts be known; once upon a time I too was guilty of writing such code, however we all learn from our mistakes. Taking a lesson out of every experience is, I think, the key.