Exceptions are roaming free, all over the place

E

Elder Hyde

I really don't understand this. Why, oh why, can't methods declare
exceptions in C#? Why can't they force the compiler to slap you when
you're ignoring a checked exception? I think what Heljsberg said about
Exceptions in Java end up getting ignored may be true, but shortsighted.

It's like it boils down to which one is better:
1. Some lazy programmers swallowing exceptions, making exceptions that
should have been thrown invisible from the surface, or
2. A lot of programmers not doing anything about exception (since the
compiler doesn't enforce it), so at run time there can always an
exception that gets thrown, throwing you completely off balance because
you haven't coded the handler for it.

IMO 1 is still better. I'm not a lazy programmer, I diligently handle my
exceptions as required, and I know with confidence that all the things
that I can do to handle exceptions that I'm supposed to handle (i.e.:
checked exceptions), I have done.

For the runtime exceptions, things that I cannot predict, I can do a
catch-all block. This is usually ok because for runtime, two things are
possible:
1. My program is wrong (such as allowing array indexing to go past the end)
2. There's nothing I can do about it anyway (such as a native DLL not
found so my program can't run anyway).

With C#, things that I can and WANT to handle are not enforced :( I
think it was a really bad decision, sigh.
 
D

Daniel O'Connell

This has come up a number of times, if you search google groups you should
find several discussions on it.

I personally don't care for checked exceptions because of lockin potential.
You can either end up with exceptions wrapped in unrelated exceptions or
silly "every class has to have its own exception type" exceptions for
purposes of extensibility. I mean is it really worth it to have
public class MyClass
{
public void method() throws MyClassException;
}

or a

public void method throws NetworkException;

but method no longer accesses the network, the original developer was just
too short sighted to realize that?

Bottom line is, yes an exception management system is needed, but java's is
not the one to use. I've made a few suggestions myself, and I'm sure many
others have as well, but until a better system is designed I feel its better
not to add it to the language and lock yourself in(for example, java will
probably never be able to change the exception system if a better system
comes around(and it will), I'd rather have the better one personally, ;)).
 
J

Jon Skeet [C# MVP]

Daniel O'Connell said:
Bottom line is, yes an exception management system is needed, but java's is
not the one to use. I've made a few suggestions myself, and I'm sure many
others have as well, but until a better system is designed I feel its better
not to add it to the language and lock yourself in(for example, java will
probably never be able to change the exception system if a better system
comes around(and it will), I'd rather have the better one personally, ;)).

On the other hand, we're effectively locked into "no checked
exceptions" mode now. The reason Java is unlikely to change majorly on
this in the future is for backwards compatibility reasons - old code
needs to work with at most minimal changes. The same is true for C# -
there's already far too much C# code out there to be worth breaking it
all. For instance, I doubt that things will be changed in Whidbey to
get rid of all the things like RowCollection, DataColumnCollection etc,
even if generics could make them all obsolete. I know that's not a
language thing so much as a library thing, but it's the same principle.

If some kind of super-duper exception management system were to come in
now, it would have to be pretty much 100% compatible with existing code
to get into C#, I suspect - and that's as unlikely as it being pretty
much 100% compatible with Java's exception handling.
 
D

Daniel O'Connell

Jon Skeet said:
;)).

On the other hand, we're effectively locked into "no checked
exceptions" mode now. The reason Java is unlikely to change majorly on
this in the future is for backwards compatibility reasons - old code
needs to work with at most minimal changes. The same is true for C# -
there's already far too much C# code out there to be worth breaking it
all. For instance, I doubt that things will be changed in Whidbey to
get rid of all the things like RowCollection, DataColumnCollection etc,
even if generics could make them all obsolete. I know that's not a
language thing so much as a library thing, but it's the same principle.

If some kind of super-duper exception management system were to come in
now, it would have to be pretty much 100% compatible with existing code
to get into C#, I suspect - and that's as unlikely as it being pretty
much 100% compatible with Java's exception handling.
You are quite correct, I didn't consider this angle, although I don't think
an ideal exception system should be so strong a breaking change. That is the
rub of it all, any system is going to be flawed and anger probably half of
the target audience. I should have stated a more correct "I'd rather have no
system than an overly flawed one" than what I did however. That is the
primary problem with languages as a whole, once a feature comes in, it
probably cannot ever be removed. In this case I consider Java heavily locked
while C#\.NET is only half locked, in my ideal situation anyway.

The question that sits foremost in my mind is if exception management should
be as black and white as it is in the current checked exceptions design.
There will be times I don't care, or it plain doesn't matter, and
potentially sections of code where an exception cannot or should not be
handled, which is one of the major java failing points IMHO. The ability to
enable or disable the management system across blocks of code may be of
limited value, or perhaps providing exceptions at coarse divisions of
functionality instead of at the finest level possible would suit better(and
would likely be more capable of integrating with the current system). I
think that exception management has two streets as well, specifying an
exception a method may throw is of value to the caller if and only if the
method is properly documented and behaves as documented. The capacity to
specify *when* certain exceptions should occur *within* the language is
important as well. An ideal exception management system should deal with
this for us, and properly managing and documenting *why* an exception is
thrown, and insuring consistency thereof is likely of a great deal more
value than simply forcing a compiler to make sure every exception is caught.
This would'nt be a breaking change...it would just either not be back ported
or result in considerable re-workings of the internals of many libraries
 
E

Elder Hyde

Daniel said:
This has come up a number of times, if you search google groups you should
find several discussions on it.
Yeah.. actually as I got frustrated with this, I was imagining how many
discussions this had generated..
I personally don't care for checked exceptions because of lockin potential.
You can either end up with exceptions wrapped in unrelated exceptions or

But what does "unrelated" mean? I mean, they added this chaining
exception mechanism in Java 1.4 exactly because of that. I was thankful
for that, since I had to add that chaining thing to all my exceptions
before. Aren't an exception and the exception it wraps always unrelated?

I mean, when a database error occurred, at the business level you don't
want to see that, you want to see maybe a, I don't know, something
that's related to the business domain.
silly "every class has to have its own exception type" exceptions for
purposes of extensibility.

I think again, that really depends on the developer. The thing about C#
is that it *scares* me. I never can be sure that I've done what I am
supposed to (or want to) do with exceptions that I want to care about.

Daniel, how do *you* do it? I mean, for significant apps at least you
have one catch-all exception handler at the very top (so it doesn't blow
up), don't you?

I mean is it really worth it to have
public class MyClass
{
public void method() throws MyClassException;
}

or a

public void method throws NetworkException;

but method no longer accesses the network, the original developer was just
too short sighted to realize that?

IMO he should have made it a MyClassException (NetworkException being
the "cause")... I know how one can bring this too far, but usually you
don't have *that* many exceptions. At a business level, I don't usually
have 20 classes and 20 class-specific exceptions. I have probably like
3-6 exceptions that are domain-related.
Bottom line is, yes an exception management system is needed, but java's is
not the one to use. I've made a few suggestions myself, and I'm sure many
others have as well, but until a better system is designed I feel its better
not to add it to the language and lock yourself in(for example, java will
probably never be able to change the exception system if a better system
comes around(and it will), I'd rather have the better one personally, ;)).

Well, I know that Java's not perfect, and it is always possible that I
can't shake this feeling of insecurity that
I-haven't-done-what-I-should-because-the-compiler-doesn't-tell-me
because I come from a Java background, but...

isn't it better to have "you have to handle it" as a default but you can
choose not to when you don't want to (by catching it, logging it and
swallowing it probably), instead of vice versa?

And don't forget that it is easy to handle exception now. You can just
highlight an, ahem, exceptional ;) portion of your code and tell your
IDE to "surround with try/catch". (Wouldn't it be difficult for a C# IDE
to do this? I'm not sure if this thrown exception information is exposed
at all in C#?)

Damn. Sometimes I think things were actually simpler during the C++
days. Memory leak was pretty much everything I had to care about ;)
 
D

Daniel O'Connell

Elder Hyde said:
Yeah.. actually as I got frustrated with this, I was imagining how many
discussions this had generated..
Too many, ;), some spanned quite a huge number of responses as well...days I
don't want to remember.
But what does "unrelated" mean? I mean, they added this chaining
exception mechanism in Java 1.4 exactly because of that. I was thankful
for that, since I had to add that chaining thing to all my exceptions
before. Aren't an exception and the exception it wraps always unrelated?

I mean, when a database error occurred, at the business level you don't
want to see that, you want to see maybe a, I don't know, something
that's related to the business domain.

This I agree with, however I personally don't think that catching a
DatabaseException that wraps an exception you don't understand is worth the
time. For instance, if I got a DatabaseException that wraps a
FileNotFoundException when I was originally writing against a server based
DB, can I handle that even if I already have a catch?
I think again, that really depends on the developer. The thing about C#
is that it *scares* me. I never can be sure that I've done what I am
supposed to (or want to) do with exceptions that I want to care about.

Daniel, how do *you* do it? I mean, for significant apps at least you
have one catch-all exception handler at the very top (so it doesn't blow
up), don't you?
I have, strictly, a set of handlers(whatever it takes, sometimes it requires
listening to events as well) that do little more than log and then allow the
app to crash and burn, albeit a bit more gracefully than just a standard
exception dialog. I don't feel I should *ever* touch or claim to handle any
exception I don't understand, that is just asking for incorrect behaviour.
If an exception reaches the top level, then my program either a) has a bug,
or b) the situation is unrecoverable.

I write for what I can recover, not for what exceptions are possible.
I mean is it really worth it to have

IMO he should have made it a MyClassException (NetworkException being
the "cause")... I know how one can bring this too far, but usually you
don't have *that* many exceptions. At a business level, I don't usually
have 20 classes and 20 class-specific exceptions. I have probably like
3-6 exceptions that are domain-related.
I agree with this, my original post was abit of an exaggeration, ;), however
that doesn't help that you no longer can definitivly rely on consistent
exceptions. I would often prefer getting FileNotFoundException instead of
MyBusinessClassIOErrorException(FileNotFoundException). Whenever I suspect a
file can be missing, I handle the former, while I may not think of the
later.
;)).

Well, I know that Java's not perfect, and it is always possible that I
can't shake this feeling of insecurity that
I-haven't-done-what-I-should-because-the-compiler-doesn't-tell-me
because I come from a Java background, but...

isn't it better to have "you have to handle it" as a default but you can
choose not to when you don't want to (by catching it, logging it and
swallowing it probably), instead of vice versa?
Saying you have to handle it when you don't know what you are doing seems
dangerous to me. I'd rather crash and burn than just make my best guess
about what should happen now.
And don't forget that it is easy to handle exception now. You can just
highlight an, ahem, exceptional ;) portion of your code and tell your
IDE to "surround with try/catch". (Wouldn't it be difficult for a C# IDE
to do this? I'm not sure if this thrown exception information is exposed
at all in C#?)
It wouldn't be realisticly possible in a C# IDE, there is no metadata stored
about exceptions. xmldocs exception tags could be used, but as a whole it
wouldn't work too well. There has been some discussion about what is
possible and what is realistic as well, is it proper to blindly rely on IDE
intellisense and can the intellsense handle broader exception sets(for
instance, perhaps you want to catch IOException instead of
FileNotFoundException and...NetworkReadFailedException(this is just an
example, not sure of the reallity of this, btw)), or even further
derivations of a specified exception.
I did propose a tool at one time that could provide metadata for exceptions
in assemblies in some way, based on analyzing the generated IL and determing
what exceptions were possible. Its not a perfect solution but it would help,
although it is a bit bulkier. As a whole I am more interested in being able
to specify what exceptions a given component throws in what situations
rather than simply specifying what exceptions a component can throw.
Damn. Sometimes I think things were actually simpler during the C++
days. Memory leak was pretty much everything I had to care about ;)

Hehe, of course, it was so easy to ignore return codes. Exceptions are a
pain in alot of cases...still I think my programs are more robust and stable
as a whole because of them.
 
B

Bruno Jouhier [MVP]

Hi Elder,

A while ago, I took part in one of these endless battles between pro and
anti checked expeptions. I wrote a long post about why consciencious
programmers feel guilty about not catching exceptions because they are
trapped into the "error code" mindset, and why they should not. So, I cannot
resist but post it again :

The heart of the debate seems to be the following:

Pro checked exceptions: "Exceptions are error codes. They're the modern way
of reporting errors."
Anti checked exceptions (myself included): "No, exceptions are not error
codes."

Well after thinking about it a bit more, I realized that both sides are
wrong
here and that this is a source of mis-understanding. So, let us look at this
a bit more closely:

1) Yes, exceptions *carry the same information* as error codes. So, in this
sense, you are right when you say that "they are the modern way of reporting
errors". If you compare the .NET APIs and their Win32 or COM equivalents,
you quickly realize that the error codes are gone and have been replaced by
exceptions that carry more or less the same info (usually more because an
exception object is richer than an error code).

2) No, exceptions *do not behave* like error codes. If you ignore an error
code, execution will continue with the next statement and you will lose on
two fronts: bad things will happen (the next statements are likely to crash
or produce wrong results) and worse, you won't know "why" these bad things
happened. If you ignore (do not catch) an exception, and if you have a catch
clause higher on the call stack, the same bad things won't happen (the next
statement will not be executed) and the "why" will not be lost (it will
reach the high level catch clause and be reported and logged there).

So, the pro-checked define exceptions their way because they attach more
importance to 1) and the anti-checked reject this definition because they
attach more importance to 2). Nobody's really right here, and exceptions are
both "error codes" (they carry the same info) and "not error codes" (they
don't behave the same).

Rather than focus all the discussion on "try openFile catch
FileNotFoundException" vs. "if file.exists then else", I think that it is
more interesting to take a close look at:

TextReader reader = File.OpenText(filename);
processFile(reader);

without any try/catch around it, because it helps understand the "error
code" mindset and the "guilt" that I am talking about.

Let us put ourselves in the shoes of a consciencious C developer making his
first steps in the .NET or Java world. In the old days, he was writing
something like:

FILE* file = open(filename);
if (file == null) { reportFileNotFound(fileName); return false; }
processFile(file);
return true;

When he moves to .NET or Java, he will try to be as rigorous (he is a
"consciencious" developer), so he will read the documentation about EH. If
he is told that "exceptions are a replacement for error codes", he will
naturally write something like:

try { TextReader reader = File.OpenText(filename); }
catch (FileNotFoundException e) { reportFileNotFound(fileName); return
false; }
processFile(file);
return true;

and he will feel good about it.

And this is where the anti-checked are saying that he is doing the wrong
thing. Instead of catching the exception locally, he should let it bubble up
and just write:

TextReader reader = File.OpenText(filename);
processFile(file);

But the consciencious C programmer will *not* write this, because in his
previous life this meant: "I am not testing the case where the file open
fails, I am being lousy, etc." He he stuck in the "error code mindset" and
he does not see that the new context is *different* and that the bad things
that were happening before if he was lousy won't happen any more (the "why
it failed" won't be lost). He does not fully understand side 2 of what
exceptions are, or even if he understands it, he won't be bold enough and
and he won't remove the try/catch because he will feel guilty about it.

And if you tell him that "exceptions are error codes, just the modern way",
you are not helping him because you are encouraging him to write a local
try/catch instead of letting the exception bubble up (if all that can be
done about the exception is report it, which is what happens in most cases,
there is absolutely no advantage in reporting locally rather than letting
the exception bubble up, you just end up writing more code).

The sad part of the story is that the "lousy" C programmer has an unfair
advantage. He will just write:

TextReader reader = File.OpenText(filename);
processFile(file);

he will not feel guilty and he will do the right thing!

Bruno.
 
G

Guest

if (File.Exists(blah) == true)
{
File.Open(blah);
}

Exceptions are just that, exceptional cases.

You should still always check for state if thats a deterministic factor in
the execution of code.

Where I see alot of problems arise is due to the lack of Autonomic
components. Every component and object should be self checking.

Sure it will impact performance but so would a crash or worse, inaccurate
results.
 
E

Elder Hyde

Hi Bruno,

I've been reading some of the arguments about this since yesterday--it
seemed that a lot of the arguments against checked exceptions are based
on the assumption that some programmers will be either lazy, or don't
know what they're doing, or even too conscientious (like your example
below), and with checked exceptions, since they are forced to do
something about it, they will be forced to do the wrong thing, and
that's bad.

But here's another perspective: going back to the FileNotFoundException
example, with checked exception, the default is that I have to handle
FileNotFoundException. If at that time I decide that in the context of
code I'm writing I'm not supposed to handle it, I'll just rethrow it (or
don't catch it at all), and let some other code up there who knows how
to handle it, handle it. So I can be "sure" that I'm letting it through
because I don't know what to do with it, in my current context, and that
somebody up there who knows MUST handle it, either by crashing, or by
opening up a dialog to let the user enter the file location.

On the other hand, now pretend that I'm writing a piece of code that
knows how to handle FileNotFoundException. Without checked
exception--because I don't have to do anything, the compiler doesn't
even point out to me that I am supposed to do something about it, it is
more likely for me to forget that there are cases that I AM supposed to
handle, and it won't make sense for me to rethrow them to my superior.
Someone who codes higher up there may assume that I have handled it,
because now the situation is reversed, it doesn't make sense for HIM to
handle it. As such, he doesn't handle it, and he's not prepared for it,
so the application crashes. Which may not be how it is supposed to be.

So with checked exception, I'm always reminded of things that I may need
to handle, and it is in my discretion to decide which one to let go.
Without checked exception, nobody tells me what to handle, it is in my
discretion to decide which one NOT to let go. This is what gives me this
guilt I haven't been able to get rid of :)

That is, taking a probably far-fetched analogy: even without
documentation, checked exception is like having a option dialog for a
GUI application: you see all the options available to you, so you can
see which one you want to change.

But without checked exception, it's like a unix command line app--you
don't even know what options are available to you, you have to sift
through the man page to look for them, and you can always miss one or
two, because it's not so right-in-your-face.

Cheers,
Elder
 
D

Daniel O'Connell

Elder Hyde said:
Hi Bruno,

I've been reading some of the arguments about this since yesterday--it
seemed that a lot of the arguments against checked exceptions are based
on the assumption that some programmers will be either lazy, or don't
know what they're doing, or even too conscientious (like your example
below), and with checked exceptions, since they are forced to do
something about it, they will be forced to do the wrong thing, and
that's bad.

But here's another perspective: going back to the FileNotFoundException
example, with checked exception, the default is that I have to handle
FileNotFoundException. If at that time I decide that in the context of
code I'm writing I'm not supposed to handle it, I'll just rethrow it (or
don't catch it at all), and let some other code up there who knows how
to handle it, handle it. So I can be "sure" that I'm letting it through
because I don't know what to do with it, in my current context, and that
somebody up there who knows MUST handle it, either by crashing, or by
opening up a dialog to let the user enter the file location.

On the other hand, now pretend that I'm writing a piece of code that
knows how to handle FileNotFoundException. Without checked
exception--because I don't have to do anything, the compiler doesn't
even point out to me that I am supposed to do something about it, it is
more likely for me to forget that there are cases that I AM supposed to
handle, and it won't make sense for me to rethrow them to my superior.
Someone who codes higher up there may assume that I have handled it,
because now the situation is reversed, it doesn't make sense for HIM to
handle it. As such, he doesn't handle it, and he's not prepared for it,
so the application crashes. Which may not be how it is supposed to be.

So with checked exception, I'm always reminded of things that I may need
to handle, and it is in my discretion to decide which one to let go.
Without checked exception, nobody tells me what to handle, it is in my
discretion to decide which one NOT to let go. This is what gives me this
guilt I haven't been able to get rid of :)

That is, taking a probably far-fetched analogy: even without
documentation, checked exception is like having a option dialog for a
GUI application: you see all the options available to you, so you can
see which one you want to change.
That is, of course, assuming that the developer that writes the method does
things properly, just knowing it may throw Exception seems pointless to me.
Or as I illustrated earlier, having NetworkException thrown when a file
isn't found. I'd liken it more to an option dialog that has terse names like
Maybeifnotfounddosomethingbutonlyifxisnt6. You have everything in front of
you but you still don't know for sure whats going on. You gotta go to the
docs and read it.
I would rather see something akin to(WARNING: very bad, throw together
syntax)
//ideally, the most of the throws would be compiler handled, an escaped
FileNotFound
//exception would be wrapped in MyMethodFileException, the compiler would
generate
//checks for x and cls, etc. It is a bit out there, but something that has
come to mind.
public MyClassDerived MyMethod(string x, object cls)
throws ArgumentNullException as "$param cannot be null" when x == null, cls
== null
throws ArgumentException as "cls must be derived from MyClass" when !(cls is
MyClass)
throws MyMethodUnspecifiedException as "An unrecoverable, unspecified error
occured in Mymethod" when return == null
throws MyMethodFileException as "the file specified in x was not found"
when catch(FileNotFoundException)
{
//do my work
}

in a system that *does not* require the caller to catch the exceptions, but
requires the thrower to properly explain exceptions(and aide in creating and
managing them). I feel it has far more value and creates something *ALOT*
more like your original analogy.
But without checked exception, it's like a unix command line app--you
don't even know what options are available to you, you have to sift
through the man page to look for them, and you can always miss one or
two, because it's not so right-in-your-face.
This one is probably more correct. More importantly, some exceptions may
never be documented, which is part of the problem above, instead of
documenting, the exceptions are either hidden within documented ones or just
thrown and left to be dealt with.
 
E

Elder Hyde

Daniel said:
That is, of course, assuming that the developer that writes the method does
things properly, just knowing it may throw Exception seems pointless to me.
Or as I illustrated earlier, having NetworkException thrown when a file
isn't found. I'd liken it more to an option dialog that has terse names like
Maybeifnotfounddosomethingbutonlyifxisnt6. You have everything in front of
you but you still don't know for sure whats going on. You gotta go to the
docs and read it.

Yes that's true, again to draw on the GUI Options dialog, sometimes the
options there can be quite obscure (e.g.: "Enable virtual space"). So
there's where you have to go to the documentation.

But for me, I value the fact that even though I may not know at that
time what exactly it means, it is there, in front of me. So I know that
it's there, and I know that if I ignore it, it will have some effect on
my application. At worst, the fact that it is there right in front of
your face is a reminder: "check your documentation!" :)

Also, as my experience grows, I tend to know what an exception mean and
what to do with it after using it several times.

OTOH, without checked exception, you're not even reminded that it's
there--only *if* you go to the doc will you find out what it can
possibly throw. Now, again, this may be because I'm relatively new to
C#--but I feel paranoid because I don't want to check for every
Framework class I'm using to find out whether it throws an exception or
not. And because I don't want to (or rather, don't have the time to), I
*may* miss some of the exceptions I may want/able to handle (hence the
guilt).

Again, drawing to the analogy, in a unix console app, you can forget
three things: whether the option is there at all in the first place (==
no exception spec is exposed), how to specify an option
--enable-virtual-space true? -enablevirtualspace on?
\enable_virtual_space 1? (== no exception spec exposed, you don't even
know the name of the exceptions that can be thrown), and what it
represents (for which you have to see the doc).

In a GUI options dialog, at least you forget only about one thing, i.e.:
what it represents--for which you have to go to the doc. You know it is
there because it's on the screen (== the compiler tells you), and you
know how to specify it, e.g.: by checking the radio button beside the
label (== the compiler tells you).

Of course, as my experience in C# grows, I may also be able to remember
off the top of my head which exceptions a FileStream may throw, for
instance. But checked exceptions approach, just like a GUI options
dialog, requires less brain power (and space!) to keep track of this,
since it is immediately in front of you, right in your code editor,
hence (to me) reducing the probability of error.
I would rather see something akin to(WARNING: very bad, throw together
syntax)
//ideally, the most of the throws would be compiler handled, an escaped
FileNotFound
//exception would be wrapped in MyMethodFileException, the compiler would
generate
//checks for x and cls, etc. It is a bit out there, but something that has
come to mind.
public MyClassDerived MyMethod(string x, object cls)
throws ArgumentNullException as "$param cannot be null" when x == null, cls
== null
throws ArgumentException as "cls must be derived from MyClass" when !(cls is
MyClass)
throws MyMethodUnspecifiedException as "An unrecoverable, unspecified error
occured in Mymethod" when return == null
throws MyMethodFileException as "the file specified in x was not found"
when catch(FileNotFoundException)
{
//do my work
}

Hmmm, but without checked exceptions, won't we just be moving some
documentation into our code this way? It is good though if this can be
achieved and enforced, because then we have a lot more info on what to
do with an exception.
in a system that *does not* require the caller to catch the exceptions, but
requires the thrower to properly explain exceptions(and aide in creating and
managing them). I feel it has far more value and creates something *ALOT*
more like your original analogy.

This one is probably more correct. More importantly, some exceptions may
never be documented, which is part of the problem above, instead of
documenting, the exceptions are either hidden within documented ones or just
thrown and left to be dealt with.

Yes! Again, although with good programming practice this is definitely
avoidable, the compiler doesn't remind you at all if you forget to
document it. With checked exceptions, at least you are forced to
document *something*, because the compiler forces you to declare that
you throw it (although of course you can be nasty and throw a
RuntimeException instance.. a programmer who does this _and_ doesn't
document it deserves to be shot, twice).

Darn.. I'm getting convinced that this is one of those unconcludable
subjects :) I can't imagine how many storage bytes have been dedicated
to this problem since C# came out! I like C# a lot because it respects
me as a developer: "you know what you're doing, so we'll allow you to do
it". Java treats me as a dumb developer sometimes, although for this
exception business, I still can't get over the desire to be treated as a
dumb developer ;)

Cheers,
Elder
 
D

Daniel O'Connell

Elder Hyde said:
Yes that's true, again to draw on the GUI Options dialog, sometimes the
options there can be quite obscure (e.g.: "Enable virtual space"). So
there's where you have to go to the documentation.

But for me, I value the fact that even though I may not know at that
time what exactly it means, it is there, in front of me. So I know that
it's there, and I know that if I ignore it, it will have some effect on
my application. At worst, the fact that it is there right in front of
your face is a reminder: "check your documentation!" :)

Also, as my experience grows, I tend to know what an exception mean and
what to do with it after using it several times.

OTOH, without checked exception, you're not even reminded that it's
there--only *if* you go to the doc will you find out what it can
possibly throw. Now, again, this may be because I'm relatively new to
C#--but I feel paranoid because I don't want to check for every
Framework class I'm using to find out whether it throws an exception or
not. And because I don't want to (or rather, don't have the time to), I
*may* miss some of the exceptions I may want/able to handle (hence the
guilt).

Again, drawing to the analogy, in a unix console app, you can forget
three things: whether the option is there at all in the first place (==
no exception spec is exposed), how to specify an option
--enable-virtual-space true? -enablevirtualspace on?
\enable_virtual_space 1? (== no exception spec exposed, you don't even
know the name of the exceptions that can be thrown), and what it
represents (for which you have to see the doc).

In a GUI options dialog, at least you forget only about one thing, i.e.:
what it represents--for which you have to go to the doc. You know it is
there because it's on the screen (== the compiler tells you), and you
know how to specify it, e.g.: by checking the radio button beside the
label (== the compiler tells you).

Of course, as my experience in C# grows, I may also be able to remember
off the top of my head which exceptions a FileStream may throw, for
instance. But checked exceptions approach, just like a GUI options
dialog, requires less brain power (and space!) to keep track of this,
since it is immediately in front of you, right in your code editor,
hence (to me) reducing the probability of error.

In good practice, you can usually figure out what exceptoins are going to
happen. I advocate throwing FileNotFoundException, for example, rather than
a custom exception because when I access a file I expect that a faliure to
locate the file should result in one(unfortunatly this isn't very wide
spread), I don't like having to figure out if it will be
XmlLoadException(FileNotFoundException) or whatever. If you can't find the
file, it should be FileNotFoundException, nothing else. I feel this
increases the ability to understand what might happen based on what you are
doing and allows reasonable expectations. Of course there are issues with
this, when you pass a file as a url to a method that will use file:// type
urls, what should be thrown, FileNotFound or an Url exception?
I, admittedly, find I catch realtivly few exceptions because I allow any
exception that means bad code bubble up and only catch exceptional
situations which I can recover from(missing files, connction failures, in
some cases conversion or casting failures, etc) instead of catching every
possible exception and simply hoping I actually can keep going. Of course in
library code, I'll often allow things like FileNotFound exceptions bubble
up, etc, depending on the situation(if its a method that takes a file name
as a parameter I will, but if its a private file I'll usually wrap it in a
MyAppConfigurationException(FileNotFOund) for example). In alot of
situations, especially with files, the piece of code that calls
File.OpenText() or whatever *cannot* recover from a missing file, that needs
to be bubbled up to the code that provided incorrect file name.
Hmmm, but without checked exceptions, won't we just be moving some
documentation into our code this way? It is good though if this can be
achieved and enforced, because then we have a lot more info on what to
do with an exception.
It would allow intellisense to provide significant prompts and could allow a
range of exception management levels. Perhaps in level A the compiler
requires all exceptoins to be caught, in level B ArgumentNullException,
ArgumentExceptoin, etc are ignored, level C it ignores all exceptions, level
D issues only warnings, etc. Checked exceptions have their value, but the
black and white *its gotta be there* ideal is a *huge* problem with them.
Having the compiler issuing warnings instead of errors also allows you to
circumvent the versioning issue, the compiler *warns* you that you aren't
handling something, but doesn't force you too. Its not as safe, but I think
it would be a much friendlier middle ground
Also, contracts like above on interfaces would probably increase
consistency. Requiring an inteface method to throw a strict set of
exceptions doesn't guarentee the interface method will do it, or even will
do it when its supposed to(the implementer has to be able to determine the
meaning of the exceptoins just as callers do). I would expect the compiler
to handle null arguments and uncaught exceptions itself, allowing interfaces
to always expose the correct contractual exception system while still
allowing it the flexibility desired by the anti-checked crowd. In these
situations I consider an exception contract to bind the interface to a
specific set of exceptions in a specific set of situations, instead of
strictly binding the interface to a specific set of exceptions. Such
metadata, IMHO, would be of IMMENSE value for unit testing as well.
Yes! Again, although with good programming practice this is definitely
avoidable, the compiler doesn't remind you at all if you forget to
document it. With checked exceptions, at least you are forced to
document *something*, because the compiler forces you to declare that
you throw it (although of course you can be nasty and throw a
RuntimeException instance.. a programmer who does this _and_ doesn't
document it deserves to be shot, twice).

Darn.. I'm getting convinced that this is one of those unconcludable
subjects :) I can't imagine how many storage bytes have been dedicated
to this problem since C# came out! I like C# a lot because it respects
me as a developer: "you know what you're doing, so we'll allow you to do
it". Java treats me as a dumb developer sometimes, although for this
exception business, I still can't get over the desire to be treated as a
dumb developer ;)

Hehe, I too doubt this is going to be resolved anytime soon, if it can be
resolved at all. In this particular way java does treat you a bit dumb(a few
other things in java I think are a little too much "you'll have to figure it
out cause we didn't really feel like making this make sense"), but sometimes
its the stuff that treats you dumb that allows you to get things done
faster. Compiler verifications aren't always bad, it is a java feature that
is useful in java(much as With, another favorite point of disagreement, is
popular in VB and Pascal, but not particuarlly desirable in C#). Alot of the
time its easier if you just write C# code when you are writing C#, java when
you are writing java, and above all...C++ when writing C++ and never when
you are writing something else...then you'll be happy, ;).
 
B

Bruno Jouhier [MVP]

Hi Elder,

But here's another perspective: going back to the FileNotFoundException
example, with checked exception, the default is that I have to handle
FileNotFoundException.

This is where I disagree. Instead, I think that we have to distinguish two
cases:

1) You know the file exists when you try to open it. There may be several
reasons why the file should always exist. For example, it could be a vital
file that gets installed with your application, or it might be a temporary
file that the application has just created, or it might be a file that the
user just selected in an "open file" dialog, or you may have tested that the
file exists before calling Open, etc.

2) You don't know whether the file exists or not at the point where you try
to open it. For example, you application may use a "load path" to locate
some of its files, and the file may only be in one of the directories along
the load path, or it may even be completely absent, in which case the
application will use some defaults instead or reading from the file (this is
just a typical scenario).

I think that the right way to program the file open logic in these two cases
is the following:

1) Just call File.OpenText, don't catch the FileNotFoundException locally.
Instead, let it bubble up, it will be caught by the generic catch handler.

2) Test if the file exists with File.Exists(filename) before calling
File.OpenText.

Why do it this way?

In case 1), the event that the file does not exist is really an exceptional
event, and, 99% of the time, there is nothing you can do locally to handle
this exceptional event. So, the best thing to do is to let it bubble up like
any other exceptional event (bug, other I/O exception) naturally to the
framework catchall handler (event loop, event dispatcher) where it will be
logged and reported. Of course, this assumes that the framework always calls
your code after setting up a proper try/catchall. If it does not, you should
set up one in the entry points of your code (your main, your event
handlers -- for me it is crucial that all exceptions get caught and reported
somewhere higher in the call chain).

In case 2), you could catch FileNotFoundException instead of testing with
File.Exists. But the advantage of testing with File.Exists is that it tells
the reader that you are not dealing with an exceptional case, but with a
condition that you anticipated and that may occur in a "normal" context.
Also, by writing it this way, you clearly separate the logic that deals with
"normal" cases from the logic that deals with "exceptional" cases (try/catch
is only used for exceptional cases)

With this approach, you reduce drastically the number of exception handling
constructs (try/catch) in your code. Basically, all you need is a few
catchall clauses in strategic places in your framework, where you will log
and report all exceptional events in a uniform way, and all your "normal"
logic is expressed with normal control flow statements (if/then/else, while,
foreach, etc.).

Then, you can easily review the "normal" logic on one side, and the
"exception handling" logic on the other side. And check that exceptions are
not intercepted and ignored as some level (which is very bad because
something went wrong and nobody will ever know about it).
If at that time I decide that in the context of
code I'm writing I'm not supposed to handle it, I'll just rethrow it (or
don't catch it at all), and let some other code up there who knows how
to handle it, handle it. So I can be "sure" that I'm letting it through
because I don't know what to do with it, in my current context, and that
somebody up there who knows MUST handle it, either by crashing, or by
opening up a dialog to let the user enter the file location.

Ok. But then, what's the real advantage of catching locally and rethrowing,
instead of letting the exception bubble up naturally.
I can see only one advantage: you can wrap the low level exception into a
higher level exception that gives a more understandable error message to the
user (I use this try/catch/rethrow pattern quite often).
On the other hand, now pretend that I'm writing a piece of code that
knows how to handle FileNotFoundException. Without checked
exception--because I don't have to do anything, the compiler doesn't
even point out to me that I am supposed to do something about it, it is
more likely for me to forget that there are cases that I AM supposed to
handle, and it won't make sense for me to rethrow them to my superior.
Someone who codes higher up there may assume that I have handled it,
because now the situation is reversed, it doesn't make sense for HIM to
handle it. As such, he doesn't handle it, and he's not prepared for it,
so the application crashes. Which may not be how it is supposed to be.

Well, everytime you call some File.Open method, you know that you have to
ask yourself: what if the file does not exist? And then, you have two
answers: either this would be an exceptional event (case 1 above), or this
is a normal event that your logic should test (case 2 above). In the second
case, I think that an if (File.Exists(filename)) test is better than
catching FileNotFoundException, for the reasons stated above.

From a more theoretical standpoint, I think that checked exceptions give the
impression that the compiler will be able to check whether your logic has
holes or not. This is a very attractive idea (the more errors the compile
can check, the better) but it is a only a mirage because the compiler will
report "false positive", i.e. things that it believes are holes in your
logic but that in fact aren't.
Every time you are calling File.Open in a context where you know that the
file exists (or after having checked its existence with File.Exists), your
logic does not have any hole, and the compiler is simply wrong in telling
you that you have to catch FileNotFoundException.
So, I think that the fundamental problem with checked exceptions is that it
gives the impression that the compiler will be able to do some useful
"semantic" checks on the code, but these checks are not so useful because
they are polluted by "false positives". The fundamental problem is with a
piece of code like:

if (File.Exists(filename))
TextReader rd = File.OpenText(filename);

Here, with checked exceptions, the compiler would force you to catch
FileNotFoundException, or to list it in your throws clause, simply because
the compiler is dumb and only does a very shallow analysis of the semantics
of your code. If it knew as much as you do, it would be able to figure out
that this piece of code will never throw FileNotFoundException, and it would
not force you to catch this exception that will never happen (except in real
"exceptional" situations where a separate process would delete the file
between the File.Exists test and the OpenText call, of course).
So with checked exception, I'm always reminded of things that I may need
to handle, and it is in my discretion to decide which one to let go.
Without checked exception, nobody tells me what to handle, it is in my
discretion to decide which one NOT to let go. This is what gives me this
guilt I haven't been able to get rid of :)

I understand, but it forces you to deal with lots of "false positives" too!
That is, taking a probably far-fetched analogy: even without
documentation, checked exception is like having a option dialog for a
GUI application: you see all the options available to you, so you can
see which one you want to change.

But without checked exception, it's like a unix command line app--you
don't even know what options are available to you, you have to sift
through the man page to look for them, and you can always miss one or
two, because it's not so right-in-your-face.

Well, why would you ask for detailed error messages, tracebacks, etc when
you have "access denied" and "core dump"? You are really too demanding :)

Bruno.
 

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