A quality process should produce close to zero-defect software that meets the user requirements. In this article, we will go through step-by-step, the various practices/techniques that can help you prevent defects in your software, and how to catch them if they already exist.
Understanding Customer Requirements
When a customer provides you a requirement, it’s not that you start working on it there and then (Figure 1, below ). You first need to understand clearly what the customer wants.
Once you have gone through the requirement, put down what you have understood. Then, get your understanding confirmed from the customer. Doubts, if any, in the requirement specification, must be clarified at this stage. Do not procrastinate or hesitate in asking your queries.
|Figure 1. Requirements work flow|
While working on the development of system software tools, I have seen many defects creeping in due to misinterpretation of the requirement specification. Fixing such defects at a later stage can prove costly. So, it is very important that you get your understanding verified from the customer.
Functioning as a team is a skill. Delivering a high quality product is no responsibility of an individual. It's the entire team who is responsible for it. If the product fails, each team member is responsible for it.
Review is an important part of team work. Peer Review refers to participation of team members in the development and assessment of task/activity performed by an individual.
In this process, illustrated in Figure 2 below , a team member requests an artifact to be reviewed. The other team members then provide their review comments which may include corrections, suggestions and doubts on the artifact.
The artifact is then updated based on the review comments. This process is repeated till the artifact is up to satisfaction of all the team members. Of course, in case of any conflict it is the Project Leader who makes the final judgment.
|Figure 2. Hunting for Artifacts|
Reviews are critical at the following stages of software development:
a. Requirement Specification Review . As we discussed in the last point, understanding the customer requirement is very important. So, while you prepare the Requirement Specification, get it reviewed by your team members. Ten people in a team may have ten interpretations of the specification. Discuss it out within your team, and then pass your understanding to the customer for verification.
b. Design Review. Once the requirement specification gets finalized, we move on to the design phase. In the design stage, you would now think about how to approach the problem.
As you will agree, review at this stage is vital. Selection of a wrong strategy can put the entire system in a miserable state. Reviews performed at this stage will help you in:
*Analyzing various strategies to solve the problem.
* Analyzing feasibility of each strategy.
* Knowing advantages/disadvantages of each strategy.
c. Code Review. Code Review involves examining the source code to find defects. While working on development of system software tools, I have been a witness to how code review can really help you find defects.
It is good to let someone in your team walk through you code, and do the review. All the members must review the code changes with respect to other modules and give their feedback in case some side-effect is suspected.
Many defects such as memory leaks, wrong passing of arguments, unreachable code, lack of readability, high complexity and maintainability issues can be identified via code review. Finding defects at the coding stage, and fixing them there and then, would prove to be less expensive than finding them in the testing stage.
Source Code Documentation
Maintaining software is a crucial aspect of the software development process. Poorly documented, or rather undocumented code is quite difficult to maintain. Having somebody modifying your undocumented code can result in disastrous consequences.
So, it’s important to document your code, and the assumptions made by you while coding. Keep the documentation close to the source. Multiple documents are difficult to maintain. A tool such as doxygen is useful for generating source code documentation.
Use a Coding Checklist
A self-review coding checklist must be maintained by the developer. The checklist should be updated as and when defects are found. The checklist should be updated with actionable checklist points, which could ensure that any defect is not introduced. Using the checklist would ascertain that the same defect is not repeated. All members in the team should use that checklist and update it periodically.
Despite the quality processes you adopt, you must admit the fact that defects do come in. After all, software developers are human beings. Now that you have found a defect, the question is, what do you with the defect? Most of the software developers would be tempted to “fix and close it”. But isn’t it important to find out what caused the defect?
Yes it is. Analyzing the cause of a defect, can let you catch some more defects that may exist, and prevent similar defects to be introduced.
I have found the 5 Why’s method (as described in the book Kaizen The Key to Japan's Competitive Success by Masaaki Imai), to be extremely useful to reach the root cause of the defect. Knowing the root cause of the defect can help you to prevent similar defects in future.
Plan for frequent releases. Releases at regular intervals would maintain tempo of the team. At the same time, you would get a chance to refine your processes based on the feedback and the lessons learnt. It would also ensure that there is no slippage in the schedule.
Tests & Testability
Write code that is testable. If you code is not testable, it implies complex code, and hence poor maintainability and high chances of defects.
Do the testing starting with the assumption that there are defects. Take different input combinations. Take not only the positive patterns, but the negative patterns as well. List down the following when you create a test case:
* Purpose of the test case [What it intends to test]
* Expected Output
* Hardware/Software Requirements
For developers, it is highly important to test whatever they code. Performing unit testing is an effective method to find defects in your code. See to it that your code can be isolated from rest of the code for unit testing.
In a team, we have several developers working on different modules. The challenge is to seamlessly integrate all the changes to form a single product. Many times, we fail to analyze the impact of changes in one module with respect to other modules.
What I have experienced is that many defects creep in due to interface problems. Defects come in when interface is either not tested at all, or is not tested fully. So, the Interface must be tested while integrating changes in a module with rest of the modules.
While you test, check whether your code is doing what it is supposed to do. More importantly, check whether it is doing what it is not supposed to do. If it is doing something what it should not be doing, that’s a defect.
By catching defects early, the amount of time spent in later phases, such as Test, is reduced. In summary, the following points should be kept:
* Avoid introducing new defects in the code.
* Use a checklist.
* Code should be simple. Simple code is easy to maintain.
* Avoid global variables and magic numbers.
* Complex design leads to poor testability.
* User should be central to the design.
* Test as you code.
* Change of code should support ease of testing, debugging and modification.
Deepti Chopra (nee Sharma) is a senior software engineer (Team Lead) at MCCI Interconnect Solutions Pvt. Ltd. She has considerable amount of experience in the development of compilers and tools for embedded systems. She can be reached at firstname.lastname@example.org .