CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo [MVP]

Software management consultant and CTO, Headspring Systems

If it takes forever to start your app with the debugger, check for thrown exceptions - level 300


Overview of Exceptions
There are quite of a few things that are just laws of Object-Oriented development, and one of those is that exceptions should be avoided.  If you can prevent an exception from being thrown, do it.  In the world of managed runtimes, particularly Java's JRE and .Net's CLR, objects are "thrown" to communicate errors.  In a try/catch block, the language limits objects that can be thrown to ones that derives from System.Exception, or java.lang.Throwable in Java.  When an object is "thrown", the runtime stops and assembles the callstack and some other information and gives code at all levels of the callstack an opportunity to catch the thrown object (exception) and do something with it.  If the exception is never caught, the runtime with catch it and terminate the program.

Clearly, exceptions being thrown in code is a bad thing, and it signals and unstable state in the program.  It may be a huge bug, or the network may have gone down.  Either way, and exception is thrown.  Proper error handling with catch the exception at a point high enough in the callstack where the program can actually make a decision to do something about it.

Swallowing exceptions (wrapping code in a try/catch where the catch block is empty) leads to less feedback.  An exception will happen, but it will be swallowed, and you won't know about it.  As soon as you start swallowing exceptions, they will start happening without being noticed.  Debuggers pay special attention to exceptions, so swallowed exceptions (thrown, immediately caught, and ignored) will slow down the debugger with each occurrance.

Solution
Go to the Debug menu in Visual Studio and select Exceptions.  CTRL+ALT+E is the shortcut.  Check the checkbox for "Common Language Runtime Exceptions".  Now when you start your debugger, it will break when a managed exception is thrown.  It will break on the line from which the exception originates.  You can use this technique to find all the exceptions that are happing in your software right under your nose.  If you refactor to keep those exceptions from happening, you'll see a marked improvement on debugger load time (provided there were a large number of exceptions happening previously).

Alternatives
The alternative to debugging often is automated tests.  When each small piece of code is verified independently, you don't have much occassion for running the full application in debug mode.  If you have unit tests as part of your automated test suite, a failure will point to the exact place where you have the problem.

Rule to live by
Fail fast.  Fail fast.  If your software is going to fail, make it fail quickly so that you can get the feedback earlier and fix it earlier.  Don't hide the problem by ignoring it or burying it in a log file that's already verbose.  If you are unfamiliar with this concept, read this article by James Shore. 

Don't use an exception as a return value.  In an ideal situation, your application should run with 0 exceptions.  You may have a library that swallows an exception, and that would be unfortunate, but keep your application code clean.  If you can anticipate an exception happening, perform some checks to avoid it being thrown.

How to keep an eye on exceptions
Use Perfmon.  Watch the counter ".Net CLR Exceptions\# of Exceps Thrown".  The number should be zero in an ideal situation.  If you have an app that can't avoid some exceptions, you can watch "# of Exceps Thrown / sec".  This number should be close to zero.  If your application is constantly throwing exceptions under ideal circumstances, you have some work to do.

[tags: exceptions, programming, c#, java, failfast, objectoriented, development, .net, clr]



Comments

Jeffrey Palermo said:

David,
You are absolutely right.  That can tip you off to find out where these exceptions are coming from.

I typically set up my user interfaces to have a global catch all that can communicate to the user that something went wrong and to notify support.  In ASP.NET, I have an Error.ascx user control that I invoke and display if an exception bubbles up.  In Winforms, I'll show a message box.
# August 17, 2006 11:10 AM

Tomas Restrepo said:

I tend to follow Jeffrey's suggestion: Always have an unhandled exception handler in your WinForms app, and make sure you hook up to all relevant events:
http://www.winterdom.com/weblog/2006/08/05/ExceptionHandlingVSTOOutlookAndOtherTopics.aspx
# August 17, 2006 12:18 PM

Ayende Rahien said:

Jeffrey,
How do you handle this in a critical application?
Case in point: I have an application where the defination is that nothing short of a reboot should stop the app. And that means that I need to handle exceptions fairly close to where they start (I have a shallow call stack in this app).
# August 17, 2006 5:40 PM

Jeffrey Palermo said:

Ayende,
I would handle it the same way.  If a class can't make a correct course of action when an error happens, it should report up.  Eventually, you will get high enough where a class does know what to do.

In a Windows service I've worked on, I  had a similar situation.  It would continually work, and it should never stop.  I had a wrapper around the code that started and repeated the work, and if something bubbled up, I'd log it, reinitialize the work, and start it over.  A few times, something major got to that (wrong DB connection string), but the service never stopped.  I had to fix the DB connection string, though.

At the very least, you should have a top-level catch-all for the unexpected.  My advice is to handle exceptions where you can handle them, but no lower.  Ignoring an exception != handling.
# August 17, 2006 5:53 PM

Tomas Restrepo said:

Ayende,

Besides Jeffrey's answer, I think one key point here is that it doesn't necessarily mean that you need to trap the exceptions very close to where they start (though you seem to suggest this might be your case because of your design), but instead it is about identifying key points in the code that should be exception boundaries.

For example, even though you might have a global unhandled exception handler, if you're spawning threads chances are you might want to make the threaded method an exception handling boundary. Or perhaps you're using the threadpool, then you'll want the method fired by the threadpool to be an exception handling boundary as well. If you have command-driven, Unit-Of-Work and facade driven code scenarios, then those are likely candidates as well.

I've had good results applying this.
# August 17, 2006 7:45 PM

Jason Haley said:

# August 17, 2006 10:20 PM

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com
# August 18, 2006 12:51 AM

Ayende Rahien said:

The general path is something like:

Start service:
- Perform Validation on config (include connection string)
- If fail, log and stop
- Start service (basically a work manager)
- An event occurs (time related or file arrival related)
 - Queue on thread pool
 - try:
  - Start task
 - catch:
  - Log error

- Tasks
 - Execute something
  - (Usuaully start transaction)
   - Do Work
 
But some tasks may need to process stuff that are failure prone by their nature (calling Web Service), and raising an exception may rollback existing transactions.
This means that in certain cases I have something like:

- transaction:
  - Get Data
  - try:
   - Send to WS
   - Update status to success
  - catch:
   - log error
   - Update status to failed
 - save
 - commit

I allow myself to ignore the higher level exception handling in those cases because I know what the conditions to failure are, and I know that there is nothing they can do that I can't do locally.
# August 18, 2006 8:38 AM

Tomas Restrepo said:

Ayende,

That sounds good, and seems pretty inline with what I mentioned before: your tasks might be (or are) exception boundaries, and that's seems just fine.
# August 18, 2006 12:06 PM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication