Patrick Smacchia [MVP C#]

Sponsors

The Lounge

Wicked Cool Jobs

News

  • NDepend v3 is fully integrated in Visual Studio, and is now available for download! Software dependencies visualization, 82 .NET software metrics, continuous rule validations, assembly version diff, declarative code queries and more ! http://ndepend.com

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Towards Bug-Free Code

 

The only way to have bug-free code is to mathematically prove the code. Very few programs in the world are mathematically proved. Some industry can afford the price of a mathematical proof, especially when bugs would turn into human death, such as embedded software in planes, trains or cars. Most of us are working on projects that cannot afford the cost of a mathematical proof. We then rely on some tricks to maintain our bug rate as low as possible. I classify these tricks into 6 categories.
  • Contract
  • Automatic test
  • Empirical approach
  • Code review
  • Prioritizing bugs fix over new features development
  • Programming style and code quality
  • Static Analysis Tools

 

 

Contract

 

The idea of contracts is to insert correctness information inside the code. When contract is violated it means that your code contains a bug somewhere. Typically, the .NET world is very poor in terms of contracts. Our only way to express contract is to use the System.Diagnostics.Debug.Assert(…) method. This is very unfortunate because not only our code is blurred with numerous Debug.Assert(…) calls, but also the compilers cannot check contracts at compile-time. For example the Spec# non-nullable types is an excellent form of contract at language level that help a lot avoiding pesky NullReferenceException. And Spec# is far from being the only language that propose contract facilities, think about what Eiffel proposed more than twenty years ago in terms of contract!

 

As I believe in contract, I personally use a lot Debug.Assert(…). This represents around 15% of my code. I will likely blog more on this because with all the buzz actually made around automatic tests, I feel that contracts should deserve more attention.

 

 

Automatic test

 

I won’t enumerate the numerous benefits of automatic tests and high code coverage ratio here. The important thing to remember is that having a solid battery of automatic tests is an excellent way to decrease significantly the bug rate on tested code, but also to avoid new bugs when code gets refactored. As many, my opinion is that the cost of writing automatic tests is worth the price compared to the cost of maintaining not automatically tested code.

 

 

Empirical approach

 

What I call empirical approachis a simple tenet that every seasoned programmer know:

  • Most of bugs in a new version are coming from modified code and brand new code
  • Unchanged code that works well for a long time in production won't likely crash within the next release (what we call stable code). We don't say that stable code don't contain bug, but discovering a bug in stable code is rare.

How do you know that some code works well for a long time in production? Simply by listening to users. If they didn’t report problems on some features for a long time then you can be confident that underlying code is stable. Some might say that I consider here users as testers but don’t take me wrong, we don’t have the choice. If you have real users, they will complain when they will find a bug and they will remain silent when they consider that the product is working fine. You are responsible to deliver correct code that will satisfy users but why wouldn’t you infer statistics from their feedbacks to asses where is your stable/unstable code?

 

I wrote an article about how we (the NDepend team) use this simple but effective idea and our own dog-food to avoid regression bugs while adding new features. Basically we focus our code reviews mainly on code that have been added or code that have been changed since the last release and of course.

 

Code review

 

Code reviews are good to enhance quality and to educate programmers but I don’t believe in the efficiency of code reviews to anticipate bugs. Even though some portions of code can be fascinating to read, the bulk of a code base is tedious and will make you lose your focus in less than an hour. The problem of code review comes from the mass of code to read. This is why I advise to only focus your review on not stable code, i.e added code and modified code. If you release new versions often, the mass of code to review before each release will quickly become an epsilon of the size of your entire code base. Doing so can also be seen as a way to capitalize on code reviews made during previous iterations.

 

Prioritizing bugs fix over new features development


This popular methodology directly results from the concept of stable code. Prioritizing bugs fix over new features development can be seen as a way to constantly struggle to maximize the surface of stable code in our code base.

 

Programming style and code quality

 

The recent buzz around LINQ or F# comes from the fact that object style programming is more bug-prone than functional style programming. This fact results from the expressiveness of functional style. In other words, functional code is easier to read and understand. A major aspect of the expressiveness of functional programming style is IMHO the concept of immutability that I described in a previous blog post Immutable types: understand their benefits and use them. That’s a fact, it is hard to write, understand and maintain code that mutates states at runtime (for example this is why global variables are so harmful). And this becomes much harder in concurrent environment.

 

Obviously, code quality has also a direct impact on code correctness. Anti pattern such as methods with high LOC, high Cyclomatic Complexity or high Nesting Depth, entangled components, methods with multiple concerns, classes with multiple responsibilities… leads to code harder to debug and to test.

 

 

Static Analysis Tools

 

We all dream of a static analyzer that could pinpoint automatically bugs in our code by just pushing an Analyze button. Some tools are already able to detect naïve mistakes, such as calling a method with a null reference as parameters where there are no tests of parameter nullity (i.e interprocedural analysis).

 

But most bugs are not that easy to pinpoint. By just analyzing the code a tool cannot distinguish between a feature and a bug because it doesn’t know how the application should behave. Some heuristic exists but still, to be efficient, a bug finder static analyzer needs to be feed with more information than just the code. Typically, this extra information can be found in contracts and unit-tests code. As far as I know, in the .NET area there are 2 projects revolving around this idea NStatic and Pex, and I am really looking forward to use them on my own code.

 

 

Conclusion

 

From what I understand from the agile trend, having a bug-free product to release shouldn’t be the goal. Anyway, every program not mathematically proved has bugs. The goal should then be to tend toward a bug-free product by applying as many correctness tricks as possible.


Posted Sun, Mar 30 2008 9:02 PM by Patrick Smacchia
Filed under:

[Advertisement]

Comments

DotNetKicks.com wrote Towards Bug-Free Code
on Sun, Mar 30 2008 4:17 PM

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Rob wrote re: Towards Bug-Free Code
on Sun, Mar 30 2008 4:32 PM

A good read, and looking forward to reading more on how you work with contracts and Debug.Assert. I am looking to become more agile and keen to see as much of what other people are doing as possible!

Thanks again,

Rob

Dew Drop - March 30, 2008 | Alvin Ashcraft's Morning Dew wrote Dew Drop - March 30, 2008 | Alvin Ashcraft's Morning Dew
on Sun, Mar 30 2008 5:05 PM

Pingback from  Dew Drop - March 30, 2008 | Alvin Ashcraft's Morning Dew

Steve Thompson wrote re: Towards Bug-Free Code
on Sun, Mar 30 2008 6:45 PM

For Design by Contract, unit testing, asserts, and simplicity of expression, I would encourage you to have a look at the Cobra programming language, as I am now:

http://cobra-language.com

The author has made it possible to easily include full Eiffel DbC into his language.  In addition, unit tests can be specified at varying levels.  I think that these two properties do much to help in the development of correct code.

Cheers,

Steve

Joe Chung wrote re: Towards Bug-Free Code
on Sun, Mar 30 2008 8:46 PM

"Beware of bugs in the above code; I have only proved it correct, not tried it." -Donald Knuth

Reflective Perspective - Chris Alcock » The Morning Brew #62 wrote Reflective Perspective - Chris Alcock » The Morning Brew #62
on Mon, Mar 31 2008 3:14 AM

Pingback from  Reflective Perspective - Chris Alcock  » The Morning Brew #62

Patrick Smacchia wrote re: Towards Bug-Free Code
on Mon, Mar 31 2008 3:27 AM

Thanks Steve for the tips,

it is interesting but the bulk of my code is written in C#,

what I want is DbC in the mainstream, in C# and VB.NET syntax and compiler.

Steve Thompson wrote re: Towards Bug-Free Code
on Mon, Mar 31 2008 8:48 AM

"what I want is DbC in the mainstream, in C# and VB.NET syntax and compiler."

Me too.  Unfortunately, as I see it, there are two problems:

1) I'm tired of waiting.  Since Eiffel I have waited for another language to support DbC.  There have been some attempts, but they were always things like adding attributes to code that translated into assertions, or there were little caveats like 'doesn't work with inheritance like it should'.  Cobra, since it is a .Net language, seems like the perfect solution in which to write reusable DbC verified assemblies at the very least, where correctness is (in my mind) paramount.

2) Quite frankly, I'm a bit tired of the one file for code, one file for unit test division with tools like NUnit, JUnit, TestNG, et al.  Cobra's idea of making it easy to declare unit tests near the code itself is supposed to mean that I will be more likely to do it (according to its author) and I believe that this is indeed the case.

3) With C# this isn't so much the case, but with VB.Net in particular, I find that the verbosity of the syntax really gets in the way of easy visual inspection.  It took me a little bit of time to come up to speed with Cobra, but the syntax is incredibly spartan and reads quite well.

We can talk about having such features in the 'mainstream' where they do not exist, or we can simply use a language that supports them today. It never hurts to take a pragmatic look at the situation :-)

Patrick Smacchia wrote re: Towards Bug-Free Code
on Mon, Mar 31 2008 12:20 PM

I understand your point Steve but adapting to a new language comes at a high cost:

Education and market of programmers. And who wants to be an expert in Cobra when most of job offers ask for C#/VB.NET/Java expert?

Legacy code. Most of us work on C# or VB.NET project and we are reluctant to migration. Developers with MS techno still remeber the trauma it was to migrate from unmanaged to managed.

But don't take me wrong: it is great and sane that some new languages are challenging the well-established ones. It is just that the inertie is high.

Who Cares wrote re: Towards Bug-Free Code
on Tue, Apr 1 2008 9:26 AM

"Bug Free" and "code" can not be used in same sentence without the word "not".  Remember, Every program has atleast one more bug.

Jokes aside, good article.

Ilja Preuß wrote re: Towards Bug-Free Code
on Tue, Apr 1 2008 12:36 PM

"The only way to have bug-free code is to mathematically prove the code." - Only if you can prove that your prove is correct. Do I smell an endless recursion? ;)

"Prioritizing bugs fix over new features development" - Lean Software Development is taking this even one step further with the "stop the line" approach: you not only prioritize bug fixes over new development, the whole team also analyses why the bug was introduced in the first place and fixes the root cause.

Paul Kinlan’s .Net Development Blog » Goolgle Reader Shared items for 1970-01-01 wrote Paul Kinlan’s .Net Development Blog » Goolgle Reader Shared items for 1970-01-01
on Fri, Apr 4 2008 5:40 PM

Pingback from  Paul Kinlan’s .Net Development Blog » Goolgle Reader Shared items for 1970-01-01

Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01 wrote Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01
on Fri, Apr 4 2008 5:47 PM

Pingback from  Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01

Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01 wrote Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01
on Fri, Apr 4 2008 5:49 PM

Pingback from  Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01

Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01 wrote Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01
on Fri, Apr 4 2008 5:51 PM

Pingback from  Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01

Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01 wrote Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01
on Fri, Apr 4 2008 5:51 PM

Pingback from  Paul Kinlan’s .Net Development Blog » Goohle Reader Updates for 1970-01-01

Paul Kinlan’s Development Blog » Shared Google Reader Items for 2008-04-04 wrote Paul Kinlan’s Development Blog » Shared Google Reader Items for 2008-04-04
on Fri, Apr 4 2008 9:55 PM

Pingback from  Paul Kinlan’s Development Blog » Shared Google Reader Items for 2008-04-04

Raffles wrote re: Towards Bug-Free Code
on Sat, Apr 5 2008 4:10 AM

Regarding the usefulness of static analysis, there are two points worth making. Firstly its true that vanilla static analysis finds run-time bugs (null pointer dereferences, array bounds overruns, uninitialised memory reads etc.), but it's worth noting that 1. these are generally the bugs with the worst symptoms (often program termination), 2. these are the most common types of bug. In a typical development you can expect to find around twice as many run-time bugs as functional defects. 3. a key benefit of static analysis is that it will search through paths which your tests don't cover and which are hard to spot by inspection (speaking from experience here!) so you can remove bugs on paths which you wouldn't otherwise know were there until the end user comes back to you with a bug report.

Secondly, static anlysis tools can do even better if you have contracts in your code. Now they can find functional defects too, because you told the tool something about how the code is supposed to work. A lot of you are asking for contracts in a mainstream language. I'm not a .net developer myself, but have any of you guys looked at spec# (mentioned in the main article)? This is basically an enhanced version of C# so the cost of "learning a new language" is low:

"Spec# is a programming language with specification language features that extends the capabilities of the C# programming language with Eiffel-like contracts, including object invariants, preconditions and post-conditions. Like ESC/Java, it includes a static checking tool based on a theorem prover that is able to statically verify many of these invariants. It also includes a variety of other minor extensions to the language, such as non-null reference types."

en.wikipedia.org/.../Spec_sharp

Patrick Smacchia wrote re: Towards Bug-Free Code
on Mon, Apr 7 2008 9:58 AM

Yes, Spec# is mentionned.

Raffles, any tool to recommend? (even outside the .NET world)

Patrick Smacchia [MVP C#] wrote Make the most of your test coverage data
on Wed, Apr 9 2008 5:30 AM

I am really glad to announce that now NDepend supports test coverage metrics: PercentageCoverage , NbLinesOfCodeCovered

Coverage » Towards Bug-Free Code wrote Coverage » Towards Bug-Free Code
on Sat, Apr 19 2008 4:21 AM

Pingback from  Coverage » Towards Bug-Free Code

Compilers Eiffel wrote Hubs of Towards Bug-Free Code
on Sun, May 11 2008 7:34 PM

hubs about Compilers Eiffel to calls, but also the compilers cannot check contracts at compile-time. For example the Spec# non-nullable types is an excellent form of contract at language level that help a lot avoiding pesky NullReferenceException. ..

This Week’s Geek Links (May 16th, 2008) wrote This Week’s Geek Links (May 16th, 2008)
on Sat, May 17 2008 9:19 AM

Pingback from  This Week’s Geek Links (May 16th, 2008)

David Nelson wrote re: Towards Bug-Free Code
on Fri, Aug 1 2008 6:46 PM

"If you have real users, they will complain when they will find a bug and they will remain silent when they consider that the product is working fine."

If only that were true! The lesson I have learned from supporting end-user applications is that you have to do everything you can to make sure that you are notified automatically when something goes wrong. You cannot rely on your users to tell you, because more often than not they will simply suffer through it and/or search for a way around the problem; only if a bug actually blocks them from doing their job will they bother reporting it.

Work at home moms. wrote Voyforums work at home moms.
on Sun, Nov 2 2008 5:35 PM

Site build it work at home moms wahm. Work from home moms. Top work at home moms. Moms work from home. Moms work at home center.

money making wrote money making
on Tue, Jul 21 2009 5:06 AM

You need some best tools with your internet marketing to be successful quickly.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us