Saturday, February 26, 2005

Code Quality and the "Total Software Product Quality Triangle"

Today I came across "The Code Quality Myth" by Frank Sommers. Several quotes in the article really hit home. I could have written some of this essay. For instance, "I have almost never met a developer working on real-life, production software in a business environment who was completely satisfied with the code he was working on."

The code I am "proudest" of is typically short, "one-offs". This is typically stand-alone software or routines that serves one tiny purpose and is not tightly integrated into a larger product. Usually this software is not written under deadline, and is almost always a version 1.0 or a complete rewrite with few aspects of backwards compatibility. I am usually very proud of software when I have time to "do it right," and the quality is generally the best possible that I can produce.

Frank pretty much echoes my above sentiment with "I almost discern an inverse relationship between how satisfactory a piece of code is to the developers working on that code, and the amount of money that code makes for those developers' employers." Commenter Robert to that essay asked for metrics on that statement - I think he misses the salient points I am about to cover here.

Frank later talks about how the source code is not what we ship, and that only the binary matters - since this is typically all that the customer sees. This is where our opinions start diverging, and Frank misses one point that is staring him in the face: Why is this the case?

After 1.0 is released, or when that pristine little one-off class is integrated into a larger program, things start to go sour. Now we have to start working on new stuff and maintain backwards compatibility with the old stuff. It may be quite clear that the current API or XML Schema is not perfect for the new feature. Rather than refactoring or rewriting, we (as developers under a deadline) merely attempt to shoehorn the new feature into the old codebase. This is not perfect, pretty, or something to be proud of - but we think that we will be able to "do it right" for the next iteration, whose time ultimately rarely ever comes.

Besides the "shoehorning" there are other issues. Perhaps you want to move from the Old Hungarian into the New Hungarian. Perhaps there is a new "coding style" that you are supposed to use from now on. Different programmers working on the same class introduces some additional considerations. Maybe all of your string manipulation functions from today forward are to use the new "strsafe.h" functions. Whatever the reason, this results in fragmentation of your codebase. Some of it is the "new" way, some of it is the "old" way, and you get that massive maintenance programmer headache when attempting to context switch between two or more different coding philosophies in the same routine! Are you proud of this mess - heck no! Is this improving overall code quality and maintainability? Likely not!

The last thing that spices the code up a bit are platform differences and/or new technologies. Maybe you are porting a single class at a time to UNICODE and have ugly #ifdef's all over the place. Perhaps you want to take advantage of http.sys in XPSP2 and Server 2003 while still working under OS's that don't support it. Plus, that hack-around for people with IE4 installed is still lurking in the bowels of the core program. While this may assist in code "robustness" it certainly does not contribute to overall quality or maintainability.

In short, ALL source code gets uglier with time. For many reasons it has to. A solid developer knows that he or she can do much better in a rewrite with hindsight as our guide. An experienced (pre-agile) developer will architect classes with some degree of foresight (and bloat) to help mitigate this. The experienced agile developer (working with an organization that uses the agile philosophy) will write the bare minimum such that the affected classes need to be refactored for any major change to mitigate hacking around.

Planning for dealing with these future changes is what can help lessen the ugliness of the underlying code. In my opinion, the agile refactoring philosophy is one of them. Too many development organizations fear refactoring as "introducing risk" from 1.0 to 1.0.1 instead of fearing future effects of hack-arounds. This fear is unfounded (since it is easily mitigated with automated unit testing), and the tradeoff in having quality code vs. unmaintainable goo to propagate forward into the next major version is a no-brainer. Consider that the 1.0.1 fixes will be integrated back into the mainline. Is the fix you are making the correct one for the future? Does the fixed code look the same as it would have been written in 1.0 had it worked?

This is where Frank and I start converging again. "...total product quality, as Edwards Deming noted, is not the result of merely improving the quality of a single activity, but is rather the outcome of a set of processes focusing on the quality of the total output... Developer testing, agile development methods, quality assurance, continuous integration - these are all processes that facilitate a high quality of total output." We begin to diverge from there almost immediately.

To use an analogy that Steve McConnell did not, overall software quality is similar to the "Fire Triangle." To have fire, there needs to be Oxygen, Heat, and Fuel. Note that you can have all three without actually having fire - as fire is the result of the chemical exothermic reaction that occurs when all three of the other elements are present under the right conditions. Once fire occurs, take any one of these elements away, and there is no more fire.

In software development, I propose the "Total Software Product Quality" triangle. The three components are "Solid Code", "Complete Unit Testing," and "Continuous Integration Testing." In the presence of a "solid management process" that combines the three elements under the right conditions, we can have "Total Software Product Quality." Take any one of these elements away, and there is no more total quality - only fires that will need to be put out later at a tremendous cost.

Thursday, February 17, 2005

Random thoughts

I apologize for not posting much lately. I've been fairly busy are work and some other side projects. I do have some nice articles planned for the upcoming weeks - from some installation related stuff to some specific Win32 programming topics (http.sys is one of them). Plus, I plan to finally publish the custom action dll sample for MSI that I've been promising since forever.

First, let me thank "G-Man" Geoffrey for offering some server space to store the custom action stuff. Also, thanks to Tim for kicking me in the behind for not addressing the Steeler's loss after the last posting - we simply were beat by a better team. Google's Ad program thinks this blog is completely sports related now! As a side note, Tim touched on the whole Mark Jen story, and I concur 100% with his thoughts, especially his 'fourth criteria'. You will notice that I don't even mention my employer in any way nor blog about work related items that are not general domain knowledge.

Looking at some blog stats, my largest referral was from Joel on Software. Second was referrals related to a tablet pc review I did a while back. G-Man is the third best referral, closely followed by Aaron Stebner. I don't get too many off-topic Google search queries, and MSN Search ignores me completely. Heck, there are 12 referral URL's in their index, plus I submitted the URL months ago, yet not one page was indexed yet!

I'm actually surprised that the MSI Custom Action in script topic keeps coming up elsewhere. Of course, when you look at some strange behaviors in the Scripting engine, I can see why! Not that any of us would write code like that anyway...