I've recently been involved in a project focused on developing teaching materials for High School Computer Science courses. As I've thought more and more about my experiences as a student and professor in high school and college CS, I've noticed some clear patterns in my evolution as a developer and those I've worked with over the years. Reading Alfred Thompson's recent blog entries on teaching students to comment (here and here) got me thinking specifically about how commenting and other non-algorithmic techniques have really improved the quality of my development experience over the years.
While teachers can try to pound away at why students should follow certain coding practices, it seems as though everyone needs to have their own personal epiphany before they can truly appreciate why certain mechanisms exist in CS. I think the reason that most students shrug off many of these development best practices is that they are primarily useful during debugging, which is where the vast majority of professional developers spend the vast majority of their time. Students, however, can often get away with completing their assignments on a single printed page, so debugging barely even enters the equation.
Thinking about how I've changed over the years, I can identify three specific ways (in evolutionary order) I've grown:
So how does this all of this relate to my title, "Why I Hate Debug.Assert"?
As I've mentioned, the Debug class is awesome because it enables you to do debugging stuff at runtime (such as logging and breaking into debug mode). When you compile and build in "release" mode, all of the debugging stuff gets stripped out, leaving you with more optimized code. This makes it very easy for you to develop and test in debug mode, and then not have to do anything besides change the build configuration when deploying (in other words, you don't need to comment out or delete the Debug class calls).
This is where the problem occurs. When I see code like this:
public void MyMethod(MyClass myClass){ Debug.Assert(myClass != null, "myClass is null in MyMethod"); myClass.DoSomething();}
I end up screaming "You were SO close!!!".
In this scenario, a null might get passed in as myClass and the developer will hit the assert, which will pop the Assert dialog that they can use to stop execution and discover why myClass was null when MyMethod was called. They'll fix the calling code and run it again. Everything will work, they'll build it for Release, and toss it over the wall. Unfortunately, this code isn't robust because it's still possible that null could be passed in (unless you have absolute faith in every caller, which you shouldn't).
Alternatively, the better solution is:
public void MyMethod(MyClass myClass){ if (myClass == null) { Debug.Fail("myClass is null in MyMethod"); // either return here or throw and exception, but don't let execution continue in release mode! } myClass.DoSomething();}
Now we get all of the benefits of the Debug class, but maintain a level of robustness for Release code. Sure, if this comes up you'll still need to debug, but at least you'll get better detail than a NullReferenceException. It's also possible you could even recover from this somewhere up the stack.
I can't really think of any place Debug.Assert is better than Debug.WriteLine (if just logging) or Debug.Fail (as described above). Then again, I could be wrong!
Remember Me
© Copyright 2010 Ed Kaim Theme Design by Bryan Bell newtelligence dasBlog 1.7.5016.2 || | Page rendered at 9/2/2010 10:58:00 AM (Pacific Standard Time, UTC-08:00) Reset | Candid Blue | Movable Radio Heat | DasBlog | Movable Radio Blue | Just Html | sharpLogic | Slate | Discreet Blog Blue