Friday, September 30, 2011

Negative testcases

This past week proved me that the way I test my code is not good enough. The QA Engineer who tested my code logged many bugs on the negative test cases. I test mostly positive test cases and the negative test cases the user should see on some errors and the ones I think are *possible*. How do I decide that it is possible? Intuition. The code kept hitting different asserts and crashed because I did not handle those error conditions.
        After looking at all the crashes I changed my way of testing a little bit. I first test the positive test cases, user perceivable error cases. Then either instrument the code or assign error values to the relevant variables in gdb so that the execution will hit the remaining negative test cases  for the functions I modify. 
       This method already gave good result for my recent commit. I found a new bug lingering in the code. It is very difficult to hit that test case with normal testing, may be a good code reviewer could find it out.
         If this model does not scale well, may be I should introduce Fault Injection Points into the code so that the bugs in -ve test cases are caught.

How do you go about testing -ve test cases in your code?.

Sunday, September 25, 2011

learning Software Design

I have been working as software Developer for 4 years. There was very little improvement for the first 2 years in my programming style, code organizing skills, design in general. There were functions spanning thousands of lines. I wrote code with for loop inside a conditional inside a big while loop. There would be multiple duplicate functions iterating over the same data structures just to check different condition. It resulted in multiple similar bugs in different places, generally due to the same bug in all those duplicate functions.
        Of-course there were code reviews, problem was that there were multiple reviewers for different bugs. The tools try to show only the diff for the current fix, so the reviewer used to verify if it fixes that particular bug. After the first year the feature I was working on got so big and delicate, no one knew what new bugs would result in changing a line. It was re-written, but after a few months of the re-write the project started going in similar direction.
        I figured out that the problem was with the way I was writing/testing code. I started reading books on programming, software design etc. Some improvements were easy to implement, like making sure the function length is < 80 lines (language is C). Have tab width as 8 spaces, if any line is going beyond 80 chars then the logic/code needs to be restructured etc. Then came the difficult things like, coupling, cohesion etc. I found it difficult to think about those things at the time of changing the code to accommodate new requirements/fixes. I did not realize that the complexity of the code is increasing.
        I came across the tactical design presentation given by Glenn Vanderburg about an year back. This changed the way I write/think about code significantly. Watching it was one of the valuable hours spent in improving myself.
        He suggests building the right value system while coding. These are the quote from Ralph Johnson about life he shows in one of the slides:
"With the right value system, making good short-term decisions leads to good long-term results".
"I think that is the purpose of a value system. We need to figure out the way to live so that when we are in the middle of life we 'do the right thing.' When our neighbor comes over to argue with us, we are not going to start thinking about how this will affect our lives 10 years from now, but we react according to the way we were taught, and the way we taught ourselves."
         We need to build a value system that makes short-term decisions at the level of functions and lines of code that will lead to good long-term results in terms of overall design.

This is that system:
The two coding rules:
1) Short methods/ functions (80 line function rule)
2) Few methods per class (Have fewer functions with a structure as primary argument).

Three Principles:
1) Do one thing (Helps to construct different basic functions for the operations that can be done on a structure/class)
2) DRY (Don't repeat yourself, Helps in avoiding duplication)
3) Uniform level of Abstraction (Helps in coding at the same level of abstraction)

I will elaborate on how these principles improved my coding skills in the future posts.

PS: I am not very good at English, Let me know if you find any mistakes, I will correct them.

Friday, September 23, 2011

Hello World

Have been postponing this post for an year now. Better late than never. This is the place where I will share my thoughts, things I learn in career and life.