Best return type for an exception from a library or data layer

E

Earl

I have all of my data operations in a separate library, so I'm looking for
what might be termed "best practices" on a return type from those classes.
For example, let's say I send an update from the UI layer to a method in a
library class that calls the stored procedure. Best to return a boolean
indicating success/failure, return a string with the exception message, or
just return the entire exception?
 
R

Rad [Visual C# MVP]

I have all of my data operations in a separate library, so I'm looking for
what might be termed "best practices" on a return type from those classes.
For example, let's say I send an update from the UI layer to a method in a
library class that calls the stored procedure. Best to return a boolean
indicating success/failure, return a string with the exception message, or
just return the entire exception?

Hey Earl,

Personally i'd return an exception with the details in the exception
message
 
D

David Browne

Rad said:
Hey Earl,

Personally i'd return an exception with the details in the exception
message

No! You don't "return" an exception, a success flag, a message or anything
else to indicate success or failure. Functions should return data, if
appropriate, or return void. If there is a failure an exception should be
"thrown".

David
 
R

Rad [Visual C# MVP]

No! You don't "return" an exception, a success flag, a message or anything
else to indicate success or failure. Functions should return data, if
appropriate, or return void. If there is a failure an exception should be
"thrown".

David

Semantics friend, semantics. You know perfectly well what i meant!
 
G

Guest

Generally speaking, an exception is something that is not an expected
condition (such as being unable to open a database connection, as opposed to
just "not getting any data"). So, good defensive coding practice dictates
that the caller of the method should be prepared to handle not only expected
return types from the method call, but to catch the exception as well.

In other words, if an exception is caught, throw it, or add more information
and throw that.
Peter
 
E

Earl

Thanks Peter, David, and Rad. Even with Try-Catch in both the library and
the calling method, I was not getting exceptions out of the library. Simply
adding the throw to the Catch in the library class gave me most of what I
needed, particularly forcing the exception up the stack where I could see
it.
 
M

Michael C

Earl said:
I have all of my data operations in a separate library, so I'm looking for
what might be termed "best practices" on a return type from those classes.
For example, let's say I send an update from the UI layer to a method in a
library class that calls the stored procedure. Best to return a boolean
indicating success/failure, return a string with the exception message, or
just return the entire exception?

The third option is the only real option, the first 2 should only be used in
rare cases I think.

Michael
 
D

Dave Sexton

Hi,

If you explicitly throw an exception, don't catch it in the same library
code unless you're wrapping it with another exception, possibly logging it
for debugging purposes, and immediately throwing it or the wrapped
exception. It sounds to me like you have too many try..catch blocks
floating around.

If you haven't written code to actually handle the exception (log it and
display a message to the user, or try the operation again, for example), or
if you're not wrapping it with more information, then you shouldn't be
catching it in the first place. When the exception is thrown it may
indicate a bug in the calling code, so you'll want to see the exception when
it occurs, not suppress it.
 
W

William \(Bill\) Vaughn

In data processing there are exceptions and there are exceptions. It's
perfectly normal for an action query to fail when there are duplicate rows,
valuation fails or a litany of other reasons. These "ordinary" events should
not be handled by calling 911--throwing an exception. That's because it's
simply too expensive. Use return codes (or if necessary) RAISERROR (via the
InfoMessageEvent) to pick up these return states.

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
INETA Speaker
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________
Visit www.hitchhikerguides.net to get more information on my latest book:
Hitchhiker's Guide to Visual Studio and SQL Server (7th Edition)
and Hitchhiker's Guide to SQL Server 2005 Compact Edition (EBook)
 
D

David Browne

William (Bill) Vaughn said:
In data processing there are exceptions and there are exceptions. It's
perfectly normal for an action query to fail when there are duplicate
rows, valuation fails or a litany of other reasons. These "ordinary"
events should not be handled by calling 911--throwing an exception. That's
because it's simply too expensive. Use return codes (or if necessary)
RAISERROR (via the InfoMessageEvent) to pick up these return states.

Bill,

Gotta disagree rather vehemently there.

The assertion that exceptions are "too expensive" is often repeated, but
rarely true. With modern computers and especially in the realm of "data
processing" where waits are dominated by IO waits, the cost of exceptions is
rarely even measurable, let alone relevant.

Using exceptions simplifies programs. It allows you to ignore errors in
most scopes, concentrating on the paradigm case. Increasing program
complexity, even a little bit, is just not worth the tiny performance
difference avoiding exceptions brings.

David
 
W

William \(Bill\) Vaughn

Tell, ya what. I'll recheck with the framework people on campus that told me
to avoid exceptions--you know, the people that wrote the code. My tests
clearly show that throwing an exception is very expensive in the framework
but I could be wrong. Let's ask another expert...

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
INETA Speaker
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________
Visit www.hitchhikerguides.net to get more information on my latest book:
Hitchhiker's Guide to Visual Studio and SQL Server (7th Edition)
and Hitchhiker's Guide to SQL Server 2005 Compact Edition (EBook)
-----------------------------------------------------------------------------------------------------------------------
 
R

Rad [Visual C# MVP]

In data processing there are exceptions and there are exceptions. It's
perfectly normal for an action query to fail when there are duplicate rows,
valuation fails or a litany of other reasons. These "ordinary" events should
not be handled by calling 911--throwing an exception. That's because it's
simply too expensive. Use return codes (or if necessary) RAISERROR (via the
InfoMessageEvent) to pick up these return states.

I don't think duplicate rows or any sort of failure is an ordinary event!!
An broad definition of an exception is something that you don't expect to
happen!

As to the expense of exception, I beg to differ as well. I think the
overheads, if any, are negligible. Coupled with the benefits it gives you
over structured error handling, I'd go exceptions any day!
 
W

William \(Bill\) Vaughn

In the course of working with data, there are a variety of ways to deal with
the stuff that happens. The vast majority of these occurrences are perfectly
normal. Duplicate rows can happen and while some use unique indexes to
handle this issue, others can't and choose alternative means to do so. In
some cases, duplicates might be allowed and require more extensive handling.
Business rule validation can also be done on the server and these too can
trigger error handling code. Throwing a code-stopping exception is one way
to deal with them--most serious developers need more as their applications
get more sophisticated. This is where RAISERROR comes in along with
InfoMessage events and RETURN codes.

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
INETA Speaker
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________
Visit www.hitchhikerguides.net to get more information on my latest book:
Hitchhiker's Guide to Visual Studio and SQL Server (7th Edition)
and Hitchhiker's Guide to SQL Server 2005 Compact Edition (EBook)
 
D

David Browne

William (Bill) Vaughn said:
Tell, ya what. I'll recheck with the framework people on campus that told
me to avoid exceptions--you know, the people that wrote the code. My tests
clearly show that throwing an exception is very expensive in the framework
but I could be wrong. Let's ask another expert...

Here's an short and interesting bit on the cost of exceptions from Jon Skeet

Exceptions and Performance
http://www.yoda.arachsys.com/csharp/exceptions.html

Where a simple sample can throw/catch something like 100 exceptions/ms.

David
 
B

Bruce Wood

William said:
Tell, ya what. I'll recheck with the framework people on campus that told me
to avoid exceptions--you know, the people that wrote the code. My tests
clearly show that throwing an exception is very expensive in the framework
but I could be wrong. Let's ask another expert...

Oh dear. Name dropping is so... gauche. I'm impressed when people make
good arguments, not when they pull rank.

First, let me say that I agree with you in a limited way: some kinds of
errors should be handled via return messages or return codes, others
via exceptions. One example of the former would be bad user input: it
is expected and normal that users type garbage into applications, so
throwing an exception when the user does something "wrong" is overkill.
In my apps I return an error message string from the validation
routine, and then display that string to the user via an ErrorProvider
or a MessageBox. Score one for error returns.

However, the OP is talking about a data layer. Data layers often (but
not always) run off across networks and fetch volumes of information
from SQL databases. Compared to all of that, the cost of throwing an
exception from the data layer code is trifling. The point is, it's "too
expensive" compared to what? In what context? In the context of a
remote DB call, an exception doesn't even rate.

If you want to take a cue from somewhere, take a look at Microsoft's
own code: what does ADO.NET do when you do something that violates a
unique key constraint? It throws an exception. In fact, ADO.NET returns
error codes in very few cases. Mostly it throws exceptions, and that's
because compared to the cost of most ADO.NET operations, putting
together an exception and handling it isn't really all that costly.

The only place I've seen in which MS wrote code that throws exceptions
and then later backed off was the case of the Parse routines. In .NET
1.1 the only (reasonable) way to detect invalid input in some cases was
to do a .Parse() from the appropriate target type and then catch the
resulting FormatException. .NET 2.0 introduced TryParse() for types
that didn't have it before, simply because _in that case_ the cost of
an exception was too high _compared to the cost of the parse_.

Yes, one should not use exceptions willynilly. However, one must
consider the cost of throwing an exception with the cost of the
operation that failed. The more expensive the operation, in real and
CPU time, the less one should worry about the additional cost of
exceptions.
 
W

Willy Denoyette [MVP]

David Browne said:
Here's an short and interesting bit on the cost of exceptions from Jon Skeet

Exceptions and Performance
http://www.yoda.arachsys.com/csharp/exceptions.html

Where a simple sample can throw/catch something like 100 exceptions/ms.

This sample is based on an older versions of the framework, throwing exceptions is actually
a lot more expensive in V2 of the framework. Note also that the costs of a throw, is
actually more expensive than a simple test that executes a for loop that throws the same
exception (cached code path) from a single frame deep stack will reveal. The average cost
of a throw is something like > 100.000 CPU cycles in V2, not *that* expensive, but
certainly not inexpensive either.

Willy.
 
D

David Browne

Willy Denoyette said:
This sample is based on an older versions of the framework, throwing
exceptions is actually a lot more expensive in V2 of the framework. Note
also that the costs of a throw, is actually more expensive than a simple
test that executes a for loop that throws the same exception (cached code
path) from a single frame deep stack will reveal. The average cost of a
throw is something like > 100.000 CPU cycles in V2, not *that* expensive,
but certainly not inexpensive either.

100,000 CPU cycles? Let's round it up to 1,000,000 CPU cycles. With
2,000,000,000 CPU cycles per second, that's about 0.5ms of CPU time, round
that up to 1ms. Sill significantly less than an IO, and a small fraction of
a single timeslice.

So a reasonable performance-related best practice might be: if your code
would throw more than a few tens of exceptions per second, change your code
to not throw/catch.

David
 
D

Dave Sexton

Hi Bill,

You don't really need experts here. My testing showed 18 exceptions per
millisecond on Vista Beta 2 and 17 on Windows XP (one hyperthreaded CPU;
same machine for both tests; .NET 2.0) using Jon Skeet's program [1]
(already cited in this thread by David Browne). Here is a conversation
discussing my tests results, in its original context:

http://groups.google.com/group/micr...m"+author:dave+sexton&rnum=1#5518b8e9442b4113

If a program throws a single exception, even for input validation (Bruce
Wood mentioned in this thread that he'll use return codes instead), the
performance hit pales in comparison to any of the other consequently
slow-performing design choices you see riddled in common code, such as not
coding long-running processes to run on a background thread, for example.
In other words, performance should probably be the least of a developer's
concern when determining whether an exception should be thrown.

The problem, to paraphrase Jon Skeet, is that a stigma has become of
throwing exceptions so much that people adamantly recommend to avoid
throwing them, probably due to testing in a debugger (Jon's article points
out the difference in performance with and without a debugger attached);
however, this comes with a price by making code that much harder to debug -
debugging is the point of having an exception with a message, stack trace
and corresponding error data in the first place.

I'd say, instead of recommending that exceptions be avoided, recommend that
exceptions should be used where appropriate and that developers should
rethink their design only after seeing any unacceptable performance
degradation in a program while testing (without a debugger attached).
Naturally, as bugs are being fixed, less and less exceptions will be thrown
anyway. But if simply throwing exceptions is causing a program to run
slowly, then the author will probably want to rethink the entire
architecture since any program that is throwing 17000 exceptions per second
has some major architectural flaw, IMO :)

Anyway, did the MS people ever get back to you with their opinions on this
matter?
 
J

Jon Skeet [C# MVP]

This sample is based on an older versions of the framework, throwing
exceptions is actually a lot more expensive in V2 of the framework.

Indeed. I'm attempting to find time to rewrite the article, including
the v2 numbers and restating the case with more context. I still
believe the main point of the article, but it needs a bit more
explanation...
 
M

Michael C

David Browne said:
100,000 CPU cycles? Let's round it up to 1,000,000 CPU cycles. With
2,000,000,000 CPU cycles per second, that's about 0.5ms of CPU time, round
that up to 1ms. Sill significantly less than an IO, and a small fraction
of a single timeslice.

So a reasonable performance-related best practice might be: if your code
would throw more than a few tens of exceptions per second, change your
code to not throw/catch.

I suspect thinking like yours is how we end up with OSs that take literally
several minutes to delete a single file (which should just be a matter of
altering a few bytes on the hdd). :)

Michael
 

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

Top