|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
RevisionsJanuary 3rd, 2003
January 4th, 2003
PrefaceThis article is actually the original document I was working on when I published my earlier article "The Standalone Programmer: Delivering high quality results". I have decided not to delete the earlier article and just leave the duplications intact. I apologize if this is confusing. Also, thank you to all people who responded earlier to this article (and my others) and provided great feedback. IntroductionI have been reading numerous books, magazines and web site articles on the subject of software quality. All of these sources point to the need for detailed processes and staff to design, test and retest software to insure high quality results. This presumption that it takes teams to develop quality software cannot be entirely false? Can it? Surely there is hope for the standalone developer to develop quality software. Unfortunately, the software industry as a whole appears to argue against this possibility. To determine the truth of this assumption, we need to first determine a meaningful and measurable definition of “high quality software”. Part of the problem that I see is that no one defines “high quality software” the same. Everyone has their own standard of quality and not many people agree on the practicalities of implementing “high quality software”. The definitions that I have come across are usually quite vague and not measurable. The definition also appears to differ depending on who is asked the question. In this article I want to attempt to answer the questions “Can standalone programmers develop high quality software? And if so, How?” What is high quality software?Ask a newbie programmer and his definition of high quality software might be software which does not crash. Ask a bean counter and they may say it is “bug free” (what does that really mean anyway?). Ask a maintenance programmer and they will say that high quality software is code which can be easily understood, debugged and updated. Ask someone flying the space shuttle and they will tell you high quality software is software that always works right all the time. Ask a software project manager he/she might say that high quality software is software that does what it is supposed to do flawlessly. Ask an end user and they might say that high quality software does not crash and does what they want it to do when they want it to do it and as quickly as they want it done. To make matters worse, the definition is often different based on what product is being developed. Software that can cause death such as medical support software must be functionally bug free and fault tolerant. Software to run a typical in-house order entry application needs to be feature complete and reasonably stable, but may not need to be fault tolerant at all. Software for a commercial web e-commerce site may need to be fault tolerant and visually bug free. Even if we manage to nail down a definition for high quality software, the word “bug” keeps cropping up. What does “bug” mean? Is a bug a missing or incomplete feature, something that causes a crash, misspelled text, poor performance, etc? Who decides what is a bug and what is not a bug? Obviously, the definition of high quality software up to this point is more an art than a science. However, one fact is always the same: High quality is always important regardless of the meaning. What is needed is not a one-size-fits-all definition but a more generic definition that is refined on a project-by-project (or even component-by-component) basis. From this perspective it becomes clear that what is needed is a plan for every project and every component within a project. Planning for qualityA plan! What is that? Undoubtedly, many of us have “gotten by” without ever writing an architectural design or detailed design document. As a standalone programmer this is easy to do because who is going to see it anyway, right? Besides design documents aren’t our job, right? We’re just hired guns, right? From the perspective of truly high quality software, though, this is the completely wrong approach. High quality software demands definition not just of the code but of the requirements and expectations of the code. If there is no definition, how can we possibly measure the quality of the software we develop? Most (if not all) large software firms such as Microsoft, IBM, SUN have some form of formal design and documentation process that precedes the actual coding of the software. This process typically involves modeling the project in OO terms sometimes using UML or other tools. It also involves listing the functional requirements of the project and often specifies in great detail performance metrics for the various components of the project. How can the standalone programmer compete with this? Obviously we cannot invest the amount of time and resources into design as large corporations can. Fortunately, we are not usually called upon to develop software quite as complex as MS Office. However, the software we do develop can be more critical to our employers or clients (or jobs/careers) than MS Office. MS Office rarely is a direct component of the corporate bottom line, but the software we develop often is. The solution is to scale down the requirements gathering, analysis, design and documentation requirements to reasonable levels for our needs. Instead of treating each stage of design (requirements analysis, architectural design, etc) as separate pieces it is often advantageous to treat them as a single step I call pre-coding. Once we know the requirements, we need to make two more critical. We must make a decision as to what high quality means for THIS PROJECT. Once we have made that decision, we must then decide how we can measure quality for THIS PROJECT. The method of measuring quality must be as quantitative as possible. I am not going to go into detail on how to write a pre-coding document because I am not sure that there is any one “right way” or if there is, that I know it. The critical point is to answer all of the important pre-coding questions and define a metric for measuring quality. Beyond that, I don’t think it matters if you use MS Word, Visio, Rational Rose, etc. Quality of the end productOne of the pitfalls that many software developers fall into is believing that high quality code == high quality software. This is not always the case and in fact is often not the case at all. Just because code is well written does not mean that the end product will be of high quality. Having a definition of high quality for a given product should reveal where the emphasis should be. In many cases, the user experience will be paramount so a speedy and well-designed UI is of the utmost importance. For other applications, fault tolerance and error recovery may be of critical importance while the UI needs to be only minimal. Regardless of where the emphasis is placed, quality software does not begin with the code it begins with an understanding of the expectations and final uses of the software. The code is intended to support those ends. Probably the most misunderstood aspect of quality software is understanding the needs and expectations of the end users and incorporating those needs and expectations into the software at an early stage and at every stage. For E-commerce web site front ends, the end user will be a customer, for in-house order entry applications. For an e-commerce web site back end, you will be the end user and you need to think about that that means as well. I strongly suggest that you not only consider the end-users in your design and development process, but that you make that involvement a format part of the process. Dedicate time and effort to it because it can be the only way to measure quality when user-perception is paramount. If the definition of quality for a give project is "Suzy Q in Cubicle A13 must like it", then you need to have Suzy Q involved from the earliest possible moment. (you may find my earlier articles on usability testing and the myth of efficiency useful.) This brings up another important point. This article is trying to make a subjective word "quality" have a quantitative value. This is entirely possible so long as we do not forget the subjective nature that got us here to start with. Never forget that your perception of quality may not be what the customers or end-users perception is. Be prepared to alter your behavior and practices to better meet the customers expectations because ultimately they are the one paying the bill. This does not mean that important areas of design and code should be sacrificed, but they need to be considered in the light of the customers needs and expectations. Bugs to keep and bugs to killDepending on the definition of high quality that you select for a given project, you must decide which bugs require immediate correction and which should be logged and left for later. I don’t believe that it is possible to develop a non-trivial application and have no bugs. I also don’t believe that it is necessarily the right thing to try and eliminate every known bug. You may be thinking that I am crazy, but I am not alone in this belief. Many highly regarded authors and professionals agree with me on this point. As a standalone developer it is unlikely that you have the resources to develop software on-time, on-budget, of high quality and bug free. We must make good decisions as to the bugs we take time to eliminate and the ones we leave. The ones we eliminate are the ones which affect the quality of the end product according to the definition of quality we selected. Obviously, a bug that prevents the program from executing its intended function under normal circumstances will have to be dealt with, but a problem with the layout of a dialog or a problem with a specific function which is rarely used may need to be ignored at least for the first release. The key to remember is that there are features of the design that are more important that some bugs. The need for excellent logging in a back-end server application may be more important than fixing some bug in a completely non-critical part of the application. High quality codeRegardless of the standard for high-quality code that you adopt for a give project, there are certain standard code quality issues that should always be considered. I have struggled with many basic rules of high-quality software and still do. I sometimes find it tedious to write adequate code comments, I often fail to check return codes, I often start writing code before I adequately design it. Most of us know what these basic rules of “good” coding are but I am going to list some of them here anyway. 1. Commenting the code. Self debugging codeThere are no (or at least very few) totally bug free applications out there that are non-trivial in nature. And even if an application is bug free, that does not mean that it will not crash as a result of a full disk or other problem. The problem with debugging applications is that it takes a lot of time. In fact, according to some sources, it can take as much time to debug an application as the actual code writing takes. And this only accounts for the debugging time spent during the development cycle. What happens after a product is released to the end-users? Problems will undoubtedly arise. Accessing the quality of software that has been released can be a very difficult task and will typically only be an issue when things go wrong. After all, who worries about a light bulb that’s not burned out? This past week, one of the critical software systems at my current employer crashed unexpectedly at a most inopportune time. My first step was to review the log that the program produces to determine if the cause of the problem had been logged. Sure enough, the log contained an Error message along with a brief description of the problem. Also, the log contained the source code file name and line # where the error occurred and the name of the function which trapped the error. It was an access violation (GASP). I was able to review the code and correct the problem in less than 45 minutes thanks to this information. It turns out that I was overwriting an array. The moral to this story, though, is that the application (which happens to be a windows NT Service that drives a web site) basically debugged itself. Without the detailed error log, I could have spent hours or days tracking down the problem while a critical business function remained offline. As you have probably already guessed, the log is the result of previous sleepless nights not the product of some personal genius. Been there, done that, don’t want to do it again. Self-debugging code comes in 2 complementary forms. The first form of self-debugging code applies to all code regardless of whether it is intended for a GUI, console app, web app, etc. This form mostly benefits the developer during the product development cycle but offers little once the product has been shipped. The second form of self-debugging code extends the debugging qualities to the released product through self-reported errors, logs, stack traces, etc. The first form involves applying the techniques of validating function inputs and checking return values. These steps can and should be applied to all code regardless of how critical the code is or where it will be used. When debugging applications which use the assert macro (or similar construct) liberally and validate all function inputs, many bugs are detected immediately and require little time to correct because they were anticipated previously. The additional step of commenting helps to debug problems that asserts don’t automatically detect by helping the developer recall how and why an algorithm is implemented. The second form involves extending the first form to include actively logging application function information, error conditions, catching exceptions (even ones which can’t safely be handled) and providing descriptions for important internal functions and data that can be logged when errors occur. At its simplest form this involves logging critical error conditions such as exceptions. The log should contain enough information to identify where in the code to begin looking. Additionally, details about the data being worked on before the crash can be useful and aide in debugging. Some ideas for this form of self-debugging code include:
This second form of self-debugging code is often not needed and is overboard for many applications. It is however, quite useful for in-house applications and pretty much any server-side application which has to run 24/7. One technique that I have found useful in server-oriented applications is to utilize a custom handle mechanism when working with data. Instead of passing data around as pointers, pass the handles to the data except where performance is absolutely critical. When the handle is assigned to the pointer, assign additional descriptive data to the handle to identify the data. Then, if an error occurs involving the data, instead of trusting that the data or the pointer is valid, retrieve the description from the handle and log that information. Code that expresses intentWhat is he talking about? That's probably what you are thinking about now. I am not really referring to the concept of "Intentional Software" but it's not too far off. What I am referring to is how code in its syntax, structure, format and naming conventions can assist maintenance programmers, integrators and yourself by being as explicit as possible. Whenever possible (as much as the language allows) programmers should strive to be explicit. This can be achieved in very simple ways by following good code-quality guidelines and being consistent. One caveat to this is that although comments represent one means for expressing intent they are the most volatile because they are the least likely to be maintained over time and programmers often overlook them for this very reason. Comments should be used to expound on the intent that the code already expresses, not provide intent to code that exposes none. So, what are some practical ways of achieving this beyond the obvious? Well, here is my list of a few simple and powerful techniques for achieving this: (much of this is duplicated from the code-quality guidelines above. I duplicated it because I believe it deserves more emphasis.) 1. Use well formed variable names (method input parameters) that tell you and others what the variable is used for, its type and when possible its lifetime The cost of qualityIf you're like me you've probably read all of this and are now thinking that implementing some of these concepts and guidelines is going to take allot of extra time and is going to adversely affect the performance of your application as well as your schedules. The reality is that there is always a price to pay for quality. How big a price depends on many factors and as a software designer we must make decisions which will have an impact in various ways. I believe (and have experienced) that by planning for quality and maintaining a continuous commitment to it in everything I do, I can greatly reduce the time cost of using best practices. The issue of performance, however, is bound to come up and rightfully so. Part of the quality of an application will often be measured by its performance. I believe that most code-quality guidelines will not adversely affect performance when used appropriately, However, in the past I have not had any hard and fast performance numbers to measure the cost of various code-quality guidelines (input validation, IsBadReadPtr, IsBadWritePtr, range checking, dog tags, etc), so I have decided to develop a test bed project and write an article on my findings. This article can be found at http://www.codeproject.com/useritems/StandaloneProgrammer4.asp. 12 steps to quality softwareI want to talk a little about something that Colin Davis pointed me to. A man named Dr. W. Edwards Deming listed 14 steps to quality management that I found quite interesting. While his steps are not targeted at software development, they clearly can apply in many cases. (For more info on Deming, search google or follow this link http://www.murtongroup.com/documentation/deming1.htm). What I would like to do is to rewrite his steps so that they target software development. Below is my rewrite of the steps. (Please note that much of the text of these steps was taken directly from the link listed above and is not original to myself.) 1. Maintain a consistent Quality message and purpose towards improvement ConclusionSo, is it possible for a standalone programmer to develop high quality code? The answer is YES with caution. The caution comes from the realization that developing high quality code will mean working smarter, doing pre-coding work and developing better work habits. All of the requirements of high quality software are not self existing in the standalone developers world. Most of us do not have highly structured and detailed requirements documents, most do not have enough control over delivery schedules or feature sets. These issues can frustrate quality. With a commitment to improvement and quality, a good work environment, a willingness to learn and improve oneself and a little time, I believe that standalone programmers can not only compete with teams of programmers but also beat them in many aspects. By being focused on their individual needs and not caught into team politics and problems, individual developers can focus on the end product more and have more control over the decisions made regarding their projects. | ||||||||||||||||||||