Exceptions and Interfaces

I

Iain

Hey folks,

(I posted this in microsoft.public.dotnet.csharp.general yesterday,
but it appears that this group is rather more lively)

For the application I am developing, I have a data access layer that
handles all the talking to the database. There are only certain
exceptions that I want to excape from this class, and all of them
should have sensible meanings - for instance, there should be a "The
database is not happy" and "There is a bug here, because we got this
wacky exception", but not a IndexException or whatever - that is, I
want to make it very obvious what exceptions can escape from a
provider of the data access layer interface.

Unfortunately, the data access layer is currently at about 20 methods;
I don't want to put an indentical try catch block into each method,
because that would be a daft bit of code duplication. There is
obviously going to be a certain set of exceptions thrown, and any
other exception means bug. That means I want to surround every single
function with something like this:

try
{
//do work
}
except (DataAccessLayerException e)
{
throw;
}
except (Exception e)
{
throw new DataAccessLayerInternalException(typeof(e).toString(),
e);
}

but to put that into every method would be stupid.

I can see the following solutions:
- The post at http://primates.ximian.com/~lluis/blog/archives/000183.html
details some funky interception stuff, which may be a way forward.
However, "Calls may be slow for some applications, since all calls go
through the remoting infrastructure."
- A code generator that creates a wrapper class that provides that bit
of exception magic for each method

What I think I really want, though, is a default exception handler for
a class. Does c# or the framework offer such things?

Is there some approach that I am missing?
 
D

Dave

Iain said:
Hey folks,

(I posted this in microsoft.public.dotnet.csharp.general yesterday,
but it appears that this group is rather more lively)

For the application I am developing, I have a data access layer that
handles all the talking to the database. There are only certain
exceptions that I want to excape from this class, and all of them
should have sensible meanings - for instance, there should be a "The
database is not happy" and "There is a bug here, because we got this
wacky exception", but not a IndexException or whatever - that is, I
want to make it very obvious what exceptions can escape from a
provider of the data access layer interface.

This sounds like a reasonable approach.
Unfortunately, the data access layer is currently at about 20 methods;
I don't want to put an indentical try catch block into each method,
because that would be a daft bit of code duplication. There is
obviously going to be a certain set of exceptions thrown, and any
other exception means bug. That means I want to surround every single
function with something like this:

try
{
//do work
}
except (DataAccessLayerException e)
{
throw;
}
except (Exception e)
{
throw new DataAccessLayerInternalException(typeof(e).toString(),
e);
}

but to put that into every method would be stupid.

That doesn't mean it's stupid, only that it is repetitious. It may be a lot
of boilerplate code but given the current state of the runtime and C# it is
the easiest way to do it.

If this were C or C++ I would use a data-driven approach; use a table of
function pointers and call through a common function with an index into the
table. Something like this...

try { _gGlobalTable[x](args) } catch(...){...}

There probably is a way to do the same thing with C#; perhaps someone else
can come up with a generic way of doing this.

A more fundamental question is what exceptions you should allow to escape
from your class; this is generally a more difficult question to answer. You
have already thought about and answered it but there may be disagreement
about the answer you came up with.

For example, if all you are doing with a DataAccessLayerException is to
rethrow it, then unless you are doing other things in the handler, such as
logging error information to the event log, then there is no point in even
catching it. There's also the danger of using a form of throw that discards
the original stack so that useful debugging information is lost. There is a
difference between catch(...}{ throw; } and catch(...){ throw e; }

Another issue is the backstop catch (Exception e) {} ...
Unless you are adding context information when you create a new exception
and include the original as the inner exception you are not adding useful
information. The type of the inner exception is already known, so doing
typeof(e).toString() does not add anything of value. In fact all that does
is tell you that the object is of type Exception so I would not use the form
you have there. I prefer to use something like this...
catch(Exception e){ throw new Exception("Unable to connect to database.",e);

(Also, your keywords are incorrect...the correct term is "catch", not
"except").

Another school if thought is that you should not catch anything unless your
handler can repair the damage or take some other corrective action. This
leads to a design where most exceptions are left uncaught so they percolate
up to higher levels of code where some action can be taken. There are useful
distinctions to be made between library code and application code, and
between code running on a server (i.e. no GUI) and code running on a
client. There are a lot of different strategies that can be used.

I prefer to surround logical areas with catch handlers, provide context
information, wrap and throw it up further up the code chain until a level
that has sufficient context can deal with the problem.

I've seen statements from MSFT guidelines that there should be ten times as
many try-finally constructs as there are try-catch constructs. I think these
tend to be silly pronouncements but perhaps there's some wisdom there.
I can see the following solutions:
- The post at http://primates.ximian.com/~lluis/blog/archives/000183.html
details some funky interception stuff, which may be a way forward.

This does not provide exception interception, it provides method
interception. Exceptions use a completely different mechanism for invoking
exception handlers.
However, "Calls may be slow for some applications, since all calls go
through the remoting infrastructure."
- A code generator that creates a wrapper class that provides that bit
of exception magic for each method

This is a good idea. If you have common logic that all routines must use
then this may be one way to provide it.
What I think I really want, though, is a default exception handler for
a class. Does c# or the framework offer such things?
Not at the class level. The runtime's current implementation of exception
handling is built on top of MSVC's exception handling, which in turn is
built on top of NT's Structured Exception Handling. This is a stack
frame-based model for which try-catch-finally semantics can be produced.
Each thread gets its own chain of handlers, and there is a default handler
for each thread. In addition to the default per-thread handler there is a
default application handler; the runtime and the operating system provides
their own default handlers as a backstop, so even if you don't install a
default handler one is provided for you.

Here's a link that describe this in great detail.
http://blogs.gotdotnet.com/cbrumme/commentview.aspx/d5fbb311-0c95-46ac-9c46-8f8c0e6ae561

Is there some approach that I am missing?

I don't think so.

Dave
 
P

Paul Robson

Iain said:
Hey folks,

(I posted this in microsoft.public.dotnet.csharp.general yesterday,
but it appears that this group is rather more lively)

For the application I am developing, I have a data access layer that
handles all the talking to the database. There are only certain
exceptions that I want to excape from this class, and all of them
should have sensible meanings - for instance, there should be a "The
database is not happy"

The database is not happy ?
 
I

Iain

Dave said:
This sounds like a reasonable approach.


That doesn't mean it's stupid, only that it is repetitious. It may be a lot
of boilerplate code but given the current state of the runtime and C# it is
the easiest way to do it.
I know it would be the easiest way if I was happy to assume that I
have the boilerplate right so that it can be put into every function,
but I'm not willing to do that; I'm not willing to assume that the
boilerplate will never change.
If this were C or C++ I would use a data-driven approach; use a table of
function pointers and call through a common function with an index into the
table. Something like this...

try { _gGlobalTable[x](args) } catch(...){...}

There probably is a way to do the same thing with C#; perhaps someone else
can come up with a generic way of doing this.

I imagine you could do this with delegates, but there'd probably be a
pile of stuff to set the delegates up
A more fundamental question is what exceptions you should allow to escape
from your class; this is generally a more difficult question to answer. You
have already thought about and answered it but there may be disagreement
about the answer you came up with.

Not likely - I'm a one man band, so there's nobody to disagree with me
:) (except me, of course)
For example, if all you are doing with a DataAccessLayerException is to
rethrow it, then unless you are doing other things in the handler, such as
logging error information to the event log, then there is no point in even
catching it. There's also the danger of using a form of throw that discards
the original stack so that useful debugging information is lost. There is a
difference between catch(...}{ throw; } and catch(...){ throw e; }

Hm. For some reason I thought that throw; was equivalent to throw e;
Another issue is the backstop catch (Exception e) {} ...
Unless you are adding context information when you create a new exception
and include the original as the inner exception you are not adding useful
information. The type of the inner exception is already known, so doing
typeof(e).toString() does not add anything of value. In fact all that does
is tell you that the object is of type Exception so I would not use the form
you have there. I prefer to use something like this...
catch(Exception e){ throw new Exception("Unable to connect to database.",e);
Oops again; I thought typeof(e) would get the actual type, not the
base type. I think my code was pretty shoddy. What I meant to have was
to let data access layer exceptions escape untouched, but to throw an
exception to signify a bug for any other exception, logging the
problem and including the exception that caused it as an inner
exception. I think that should allow everything to be handled
sensibly.
(Also, your keywords are incorrect...the correct term is "catch", not
"except").

Oh. That's because I've been doing some experiments in python lately;
python has try except blocks.
Another school if thought is that you should not catch anything unless your
handler can repair the damage or take some other corrective action. This
leads to a design where most exceptions are left uncaught so they percolate
up to higher levels of code where some action can be taken. There are useful
distinctions to be made between library code and application code, and
between code running on a server (i.e. no GUI) and code running on a
client. There are a lot of different strategies that can be used.

I prefer to surround logical areas with catch handlers, provide context
information, wrap and throw it up further up the code chain until a level
that has sufficient context can deal with the problem.
Yeah, that's basically the model I'm working with. I want to have more
logical layers, because it seems to lead to cleaner code in general. I
want to let the exceptions percolate up, but I need to give them
context.
I've seen statements from MSFT guidelines that there should be ten times as
many try-finally constructs as there are try-catch constructs. I think these
tend to be silly pronouncements but perhaps there's some wisdom there.


This does not provide exception interception, it provides method
interception. Exceptions use a completely different mechanism for invoking
exception handlers.
No, but I was thinking that it might be possible to intercept each
method and let it run surrounded by the exception handling template.
This is a good idea. If you have common logic that all routines must use
then this may be one way to provide it.

Not at the class level. The runtime's current implementation of exception
handling is built on top of MSVC's exception handling, which in turn is
built on top of NT's Structured Exception Handling. This is a stack
frame-based model for which try-catch-finally semantics can be produced.
Each thread gets its own chain of handlers, and there is a default handler
for each thread. In addition to the default per-thread handler there is a
default application handler; the runtime and the operating system provides
their own default handlers as a backstop, so even if you don't install a
default handler one is provided for you.

Here's a link that describe this in great detail.
http://blogs.gotdotnet.com/cbrumme/commentview.aspx/d5fbb311-0c95-46ac-9c46-8f8c0e6ae561



I don't think so.

Dave

Thanks for your help.
 
D

Dave

Hm. For some reason I thought that throw; was equivalent to throw e;

Nope. The statements
{ throw; }
and
{ throw e; }

are similar but have different side-effects. The first form rethrows the
original exception and maintains the original stack trace information. The
second form rethrows the original exception but the stack trace will now
indicate that the faulting line is the throw statement itself, not the
original line where the exception was actually caused. This form has little
to recommned it as information is lost.

In both cases if you are running under a debugger the original context is
gone by the time the catch handler is invoked. The stack below the catch
handler has been popped and cleaned up so all local references are gone. For
debugging purposes it is sometimes better to set the debugger to break on
first-chance exceptions so it will stop on the line of code where the
exception is actually created.
Oops again; I thought typeof(e) would get the actual type, not the
base type. I think my code was pretty shoddy. What I meant to have was
to let data access layer exceptions escape untouched, but to throw an
exception to signify a bug for any other exception, logging the
problem and including the exception that caused it as an inner
exception. I think that should allow everything to be handled
sensibly.

I like logging all exceptions; all too often these "breadcrumbs" are
extremely valuable in tracking down problems.

I think your general concept is valid.


No, but I was thinking that it might be possible to intercept each
method and let it run surrounded by the exception handling template.

I'm not familiar enough with those classes to be able to offer advice.
 
C

Chris

Dave, regarding
There is a
difference between catch(...}{ throw; } and catch(...){ throw e; }
Nope. The statements
{ throw; }
and
{ throw e; }

Is there any benefit to catch(Exception e) as opposed to simply catch()?
I've been using catch(Exception e) as a standard, but if it just gets in the
way, I'll stop it.

Incidentally, there is one benefit to using { throw e; } as opposed to {
throw; } -- using the first causes the error to be displayed in the Locals
window during debugging.

Regards,
Chris
 
D

Dave

Is there any benefit to catch(Exception e) as opposed to simply catch()?
I've been using catch(Exception e) as a standard, but if it just gets in the
way, I'll stop it.

I think you should stick with catch(Exception ex). You should probably never
use catch without catching an exception type, even if the type is only
System.Exception. There are some exceptions, such as hardware exceptions,
that you will catch if all you have is an empty catch clause. Also, not
specifying an object prevents you from wrapping and rethrowing it in a new
exception.

Incidentally, there is one benefit to using { throw e; } as opposed to {
throw; } -- using the first causes the error to be displayed in the Locals
window during debugging.

I think you mean the Auto window, don't you? Anyway, you can still see the
exception object in the Local window without using it in the throw
statement. The loss of data doesn't make up for the slight gain in debugging
use.

Dave
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

catch exceptions 2
Handling exceptions 37
Throwing Exceptions 4
Unexpected Exceptions 1
Catching Exceptions 5
Exceptions 1
Exceptions and static constructors. 4
Throwing Exceptions 8

Top