Re: Some questions about handling exceptions and when to throw them
- From: "Steve" <sss@xxxxxxx>
- Date: Fri, 7 Jul 2006 12:19:32 -0700
Hi Vaibhav,
Thank you very much for taking the time to respond, I will review your
answers a couple more times and think about ways I can adapt some of your
suggestions.
I never thought of status codes and when I do think of them it reminds me of
older libraries and APIs I have used, they just don't feel "Latest and
greatest", but I know that doesn't mean it's not a good solution. I think I
will try implementing them in a single library and go form there.
Thanks again,
Steve
"V" <vaibhav.gadodia@xxxxxxxxx> wrote in message
news:1152261942.234820.45840@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Steve,
I will attempt to answer your questions based on what I get implemented
in our projects at work:
1. NO, you should not be using exceptions for Logic in your code. As
for the Application Block, those are more like an extension to the
framework, and are meant to be used by loads of developers. Its like
the framework throwing exception on illeagal use of a class. Not
finding a customer is by no means an illegal use of a class.
Additionally, this code is your own and for your own consumption, so
you should not be using exceptions to drive application logic.
2. For a scenario like this, you can always examine the stack trace
property of an exception to determine where the exception actually
happened. Another way for this is to build up a system of status codes,
and return status codes instead of exceptions to pass information up a
stack.
3. The way I tell my developers is: Catch any exception that you can
imagine occuring and can therefore handle. By handle, I mean that the
exception can be caught and an alternative action can be taken to
address the situation. This could simply even mean building up correct
error messages, or it could mean triggering some other program logic.
As a rule, a global exception handler should be present which catches
all exceptions (which you may not be handling), and handles them, and
logs them, etc.
4. Once again, build a status code framework for usage across your app.
- Vaibhav
Steve wrote:
I have read a couple articles online, read my Jesse Liberty book but I am
still confused as to just what the best practices are for using
exceptions.
I keep changing how I'm working with them and it has now, after 15k lines
of
code resulted in a royal mess!
It's my hope to ask some specific questions with scenario examples and
that
some of you might offer a little guidance or general suggestions.
1) string GetCustomerFirmwarePath(string serialNumber) - This is a
method
in a class library I have written and it is called from my UI "Presenter"
class' (In case you aren't familiar, Model View Presenter is very
similar
to Model View Controller pattern). In the event that a customer can't be
located from the serialNumber parameter, is it a better choice to return
null and check for it or to throw an exception from
GetCustomerFirmwarePath()? Possibly even my own exception, IE:
"CustomerNotFoundException"? I have read that exceptions shouldn't be
used
for logic, but I have been spending a lot of time with the Patterns and
Practices group's Composite Application Block and in one of the examples,
they use exceptions in this manner.
2) methodA calls MethodB which calls MethodC, MethodD and MethodE. IE:
PrinterInfo GetEmployeeDefaultPrinter(string employeeFullName)
calls EmployeeInfo GetEmployeeInfo(employeeFullName)
calls ComputerInfo GetEmployeeComputerInfo(EmployeeInfo info)
returns ComputerInfo.DefaultPrinter
So that is a massively stupid design, but I couldn't think of an example
that is easy to visualize (mine is very confusing and wouldn't be a good
example) Point is, if the call to GetEmployeeComputerInfo fails, there
is
no clean way to return that error back from GetEmployeeDefaultPrinter()
or
if the call to GetEmployeeInfo() fails, same thing. I can return null
all
the back down the stack, but short of looking at the log (assuming I'm
logging) there is no clean way to determine where the problem was. This
example makes me think that throwing an "ComputerInfoNotFoundException"
might be a good idea, then I could could catch it in GetEmployeeInfo and
throw a "EmployeeInfoNotFound" exception with the
"ComputerInfoNotFoundException" as the inner exception. Does that makes
sense? Is it a good design? Seems like a lot of exceptions! But what
other clean way could you handle this? Please don't suggest anything
like
overriding GetEmployeeComputerInfo(string employeeFullName) and avoiding
the
whole call stack, it's just an example, my actual situation has a good
reason for breaking things apart like this.
3) How do you decide what exceptions to catch and which ones not to? I
have read that if I know I can handle it(IE: FileNotFound) then I can
catch
it and act accordingly, but that would suggest that it's OK to let all
others bubble up... bubble up to where? Application.Run()? What
guidelines
are there?
4) One last one. As I think I mentioned earlier, I'm using the
Composite
Application Block. Using the CAB encourages breaking logic into separate
assemblies to be shared by other assemblies for code reuse, etc. There
is a
concept of a "Service" which is a basically a singleton that will perform
tasks related to a Workitem. For example, I have a service called
"FirmwareService" and it is responsible for adding new versions of
firmware
for our products to the database, retrieving older version, assigning a
particular version to specific customers, etc, etc. An example method
is:
string GetCustomerFirmwarePath(Customer customer);
This function is similiar to GetEmployeeDefaultPrinter() in that it makes
a
lot of other calls that could result in an error, either acceptable or
fatal. What I have tried to do in my design is avoid having code like
this
scattered throughout my Presenters and other task code:
<code>
// Presenter method to get a customer's firmware path and display in the
view
// All manufactured products have a record of what customer they are for
and from that, what firmware should be loaded
ProductInfo productInfo =
_productionService.GetProductRecordFromSerialNum(serialNumber);
if(productInfo == null)
{
// show error
return false;
}
Customer customer =
_firmwareService.GetCustomerFromProductInfo(productInfo
;
if(customer == null)
{
// show an error
return false;
}
string firmwarePath = _firmwareService.GetCustomerFirmwarePath(customer);
if(firmwarePath == null || firmwarePath.Length < 1)
{
// show an error
return false;
}
</code>
(that was not real code, so if there are errors, please excuse me)
What I DO want to have is something like this:
<code>
string firmwarePath =
_firmwareService.GetFirmwarePathFromSerialNum(serialNum);
if(firmwarePath == null || firmwarePath.Length < 1)
{
// show an error
return false;
}
</code>
This question is ending up to be a duplicate of #2, but I guess that is
my
main question. Given the example above assuming that
GetFirmwarePathFromSerialNum() performs all the tasks in the example code
before it, how do gracefully return errors and handle the exceptions?
For
example, if the Customer record was found but not the firmware path, I
might
want to do something like allow the user to add firmware for the customer
or
something... I dunno, I've written too much, I'll stop.
Hopefully someone will take notice of this very long email and respond
with
some insights for me :0)
Thanks for reading,
Steve
.
- References:
- Prev by Date: Re: New to C#
- Next by Date: Re: How does "new" work in a loop?
- Previous by thread: Re: Some questions about handling exceptions and when to throw them
- Next by thread: Re: Some questions about handling exceptions and when to throw them
- Index(es):
Relevant Pages
|