471,337 Members | 1,083 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,337 software developers and data experts.

design discussion: when to throw exceptions

cat
I had a long and heated discussion with other developers on my team on when
it makes sense to throw an exception and when to use an alternate solution.
The .NET documentation recommends that an exception should be thrown only in
exceptional situations. It turned out that each of my colleagues had their
own interpretation about what an "exceptional situation" may actually be.
First of all, myself I’m against using exceptions extensively, because for
complex business applications they make the code very complicated and because
of a long list of other issues I could post here if someone is interested.
The only arguments pro using exceptions that I was presented were that they
force the caller to not ignore them and “this is the trend in the industry so
we must follow”.

To exemplify what an exceptional situation might be, we debated a lot on
this piece of code:

protected void login_Click()
{
try
{
UserSession objSession = _manager.StartUserSession(strUsername,
strPassword);
Session[“userSession”] = objSession;
}
catch ( InvalidUsernameException ex1 ) // username does not comply to
requirements
{
… further processing
}
catch ( InvalidPasswordException ex2 ) // password does not comply to
requirements
{
… further processing
}
catch ( AuthenticationException ex3 ) // user account not found, locked,
disabled, etc.
{
… further processing
}
catch ( Exception ex4 ) // system error or any other exception we don’t
need to handle separately
{
_logger.LogTheError(ex4);
… further processing
}
}

My point was that the above is an example of abusing exceptions as it’s
using them for non-exceptional situations, and it’s using them exactly like
some return values. A user mistyping his password is just one of the
alternate paths in a login/authentication use case, it’s simply part of the
flow. It is expected that from time to time users mistype their username, or
some administrator may lock some account. The counterargument was that user
providing the proper username and password is the normal case while user
mistyping the username or account being locked is the exception, so we should
throw an exception in such cases.

I extensively went through all sorts of information and websites and blogs
on the Internet. However, I couldn’t find much on such difficult and
important issue. Everybody seems to agree that opening a non-existent file or
stuffing a non-numeric string into an integer should throw an exception. But
that’s pretty much it. Most of the applications on the market actually deal
with cases like the above one, yet there is no clear guideline on what could
justify throwing an exception in a business application and what not. What is
your opinion?
Jan 13 '06 #1
8 2075
One logic is that exceptions should be thrown when they can't be
predicted as a natural course of program flow. Another is that
exceptions should be productive in helping the programmer create more
robust code. I think exceptions would be the correct solution this
case because a user not found could occur for many different reasons
but also it depends on how this works in a larger context simply
because it can fail for many different reasons.

If a user not found could only fail because the user made the mistake
in typing their name in wrong then it would seem rational to not make
it an exception. The problem being that the user not found could occur
for many different reasons - perhaps the database is down, perhaps a
network connection is down, and so forth.

And if you follow this logic then by not making those cases exceptions
and treating them as normal then it may hide potential problems in the
code. By using exceptions then you can think around the code better
and when erroneous conditions do occur they are evident.

It is also a matter of style and choice, in C# exceptions are the first
class but in C return values may be better.
Curtis
http://www.ghostclip.com
Premier Popup Notepad & Help System For Developers

PS: robust code typically isn't the most easy to understand - I agree.
In the same fashion, a real world code example is much more difficult
to understand then a stripped down conceptual model.

Jan 13 '06 #2
One approach is to throw an exception when an explicitly stated
pre-condition,
post-condition or invariant is violated. The corollary is that any
pre-condition,
post-condition or invariant that may engender an exception must be
explicitly
stated and documented. This begs the question of when you should
explicitly
state a pre-condition, post-condition or invariant, but it is a start.

Regards,
Jeff

*** Sent via Developersdex http://www.developersdex.com ***
Jan 13 '06 #3
Your colleagues are wrong. You are right.

By definition, anything that the user can type or do is not
"exceptional." It's the user being the user. Mistyping a password is
not "exceptional."

Failing to find the password in the database because the database is
down is "exceptional."

Of course, it's not always so cut-and-dried. What is "exceptional"
often depends upon context. In particular, if you're writing a library
class that is expected to enjoy widespread use, what may be an
exceptional case for one client application may be business as usual
for another.

In _those_ sorts of cases it becomes a question of style, but MS is now
recommending that in cases of validation, for example, you provide an
alternate method that checks valid true / false (viz the new TryParse
methods in 2.0).

Anyway, it's mostly in deeply-buried common code that the exception
versus return value argument becomes one of style. The example you gave
is clearly an abuse of the exception idiom.

Jan 13 '06 #4
Invariably, I think it is possible to replace exceptions/try-catch, with
return-code/if-then-else blocks & vice versa. Some scenarios are easier to

The advantage of exceptions is that they can be bubbled up the function call
stack. This allows for a high level caller to be aware of failure/reason
way deep in the call stack. Often you can examine the stack trace of an
exception & tell exactly what code flow sequence caused a failure. I &
many others I know, often deliberately take advantage of this, by designing
deep method calls.

To your specific example, I think I agree with you. It is overkill.
Part of the reason you might have trouble articulating it is because, your
example suffers from a different object-design problem.
_manager.StartUserSession(strUsername, strPassword);
is doing multiple things -- Authentication, input validation, Session
creation etc. Break them apart might lead to a more semantically
meaningful & fruitful discussion.

E.g.
~~~~~~~~~~~
int iRtnCode
try{
iRtnCode = _manager.Authenticate(strUserName, strPassword)
}
catch( DomainControllerUnavailableException ex1 ) {
//Oh! Oh! What do we do now?
}
if (iRtnCode == "Authentication Failure"){
//further processing.
}

UserSession objSession = _manager.CreateUserSession()
~~~~~~~~~~~~

* I noticed your example of error handling is from the perspective of the
caller. In this particular case, I've found it useful to steer the design
discussion, towards the callee's perspective.

* Writing code with exceptions can be hard to relate to initially. I
believe for most people it feels natural, after a little getting used to.
Of course, abuse - as you've called it out - is always bad & painful.

--
Naraendira Kumar R.R.
~~~~~~~~~~~~~~~~~~~~~~~~~~~
"cat" <ca*@discussions.microsoft.com> wrote in message
news:95**********************************@microsof t.com...I had a long and heated discussion with other developers on my team on when
it makes sense to throw an exception and when to use an alternate
solution.
The .NET documentation recommends that an exception should be thrown only
in
exceptional situations. It turned out that each of my colleagues had their
own interpretation about what an "exceptional situation" may actually be.
First of all, myself I'm against using exceptions extensively, because for
complex business applications they make the code very complicated and
because
of a long list of other issues I could post here if someone is interested.
The only arguments pro using exceptions that I was presented were that
they
force the caller to not ignore them and "this is the trend in the industry
so
we must follow".

To exemplify what an exceptional situation might be, we debated a lot on
this piece of code:

protected void login_Click()
{
try
{
UserSession objSession = _manager.StartUserSession(strUsername,
strPassword);
Session["userSession"] = objSession;
}
catch ( InvalidUsernameException ex1 ) // username does not comply to
requirements
{
. further processing
}
catch ( InvalidPasswordException ex2 ) // password does not comply to
requirements
{
. further processing
}
catch ( AuthenticationException ex3 ) // user account not found, locked,
disabled, etc.
{
. further processing
}
catch ( Exception ex4 ) // system error or any other exception we don't
need to handle separately
{
_logger.LogTheError(ex4);
. further processing
}
}

My point was that the above is an example of abusing exceptions as it's
using them for non-exceptional situations, and it's using them exactly
like
some return values. A user mistyping his password is just one of the
alternate paths in a login/authentication use case, it's simply part of
the
flow. It is expected that from time to time users mistype their username,
or
some administrator may lock some account. The counterargument was that
user
providing the proper username and password is the normal case while user
mistyping the username or account being locked is the exception, so we
should
throw an exception in such cases.

I extensively went through all sorts of information and websites and blogs
on the Internet. However, I couldn't find much on such difficult and
important issue. Everybody seems to agree that opening a non-existent file
or
stuffing a non-numeric string into an integer should throw an exception.
But
that's pretty much it. Most of the applications on the market actually
deal
with cases like the above one, yet there is no clear guideline on what
could
justify throwing an exception in a business application and what not. What
is
your opinion?

Jan 13 '06 #5
cat
Dear Naraendira,

Interesting enough, I presented to my colleagues the following alternate
solution to the exception based code, which is quite similar to what you
proposed:

protected void login_Click()
{
UserSession objSession;
switch ( _manager.StartUserSession(ref objSession,strUsername,strPassword) )
{
case enmSessionResults.InvalidUsernameException:
case enmSessionResults.InvalidPasswordException:
… processing specific to invalid user provided info
goto case enmSessionResults.AuthenticationException
case enmSessionResults.AuthenticationException:
... processing specific to no log in
break;
default:
Session["userSession"] = objSession;
break;
}
}

The drawback to the above solution is that people are more used to a factory
approach ( like CClass obj = factory.GetSomeObject() ) in which case they are
pretty much stuck to throwing exceptions. This could be mitigated by the 2
steps approach suggested by you, where first the authentication is performed
then a reference to a session object is returned. My example is addressing
some of the big problems I found about throwing exceptions: potential for
terrible errors that only during production will be caught because of lack of
type checking, and complex and difficult code. For simple projects, the
exception-based approach is just fine and I won’t argue against it. However,
for large projects containing many classes exceptions spiral up all sorts of
problems:

a. For proper handling of exceptions most of the application thrown
exceptions will have to be custom exceptions. That will tremendously increase
the number of classes in a project. Think of projects with a couple hundred
of classes how complicated they would become.

b. There is no compiler type checking for exceptions (.NET is using the
so-called unchecked exceptions). If one developer adds a new exception or
changes something in one of the existing exceptions, no one else in the team
will know until the code explodes in production. It is like declaring that a
method returns an integer but you tell no one what are the values and what
they mean. As opposed, the above enumeration based approach is safe in the
way that the compiler could detect any change in the returned values so such
changes if undocumented will be still trapped early in the game.

And this is to name just a few of them, but the list is much bigger.
"Naraendira Kuma R.R." wrote:
Invariably, I think it is possible to replace exceptions/try-catch, with
return-code/if-then-else blocks & vice versa. Some scenarios are easier to

The advantage of exceptions is that they can be bubbled up the function call
stack. This allows for a high level caller to be aware of failure/reason
way deep in the call stack. Often you can examine the stack trace of an
exception & tell exactly what code flow sequence caused a failure. I &
many others I know, often deliberately take advantage of this, by designing
deep method calls.

To your specific example, I think I agree with you. It is overkill.
Part of the reason you might have trouble articulating it is because, your
example suffers from a different object-design problem.
_manager.StartUserSession(strUsername, strPassword);

is doing multiple things -- Authentication, input validation, Session
creation etc. Break them apart might lead to a more semantically
meaningful & fruitful discussion.

E.g.
~~~~~~~~~~~
int iRtnCode
try{
iRtnCode = _manager.Authenticate(strUserName, strPassword)
}
catch( DomainControllerUnavailableException ex1 ) {
//Oh! Oh! What do we do now?
}
if (iRtnCode == "Authentication Failure"){
//further processing.
}

UserSession objSession = _manager.CreateUserSession()
~~~~~~~~~~~~

* I noticed your example of error handling is from the perspective of the
caller. In this particular case, I've found it useful to steer the design
discussion, towards the callee's perspective.

* Writing code with exceptions can be hard to relate to initially. I
believe for most people it feels natural, after a little getting used to.
Of course, abuse - as you've called it out - is always bad & painful.

--
Naraendira Kumar R.R.
~~~~~~~~~~~~~~~~~~~~~~~~~~~
"cat" <ca*@discussions.microsoft.com> wrote in message
news:95**********************************@microsof t.com...
I had a long and heated discussion with other developers on my team on when
it makes sense to throw an exception and when to use an alternate
solution.
The .NET documentation recommends that an exception should be thrown only
in
exceptional situations. It turned out that each of my colleagues had their
own interpretation about what an "exceptional situation" may actually be.
First of all, myself I'm against using exceptions extensively, because for
complex business applications they make the code very complicated and
because
of a long list of other issues I could post here if someone is interested.
The only arguments pro using exceptions that I was presented were that
they
force the caller to not ignore them and "this is the trend in the industry
so
we must follow".

To exemplify what an exceptional situation might be, we debated a lot on
this piece of code:

protected void login_Click()
{
try
{
UserSession objSession = _manager.StartUserSession(strUsername,
strPassword);
Session["userSession"] = objSession;
}
catch ( InvalidUsernameException ex1 ) // username does not comply to
requirements
{
. further processing
}
catch ( InvalidPasswordException ex2 ) // password does not comply to
requirements
{
. further processing
}
catch ( AuthenticationException ex3 ) // user account not found, locked,
disabled, etc.
{
. further processing
}
catch ( Exception ex4 ) // system error or any other exception we don't
need to handle separately
{
_logger.LogTheError(ex4);
. further processing
}
}

My point was that the above is an example of abusing exceptions as it's
using them for non-exceptional situations, and it's using them exactly
like
some return values. A user mistyping his password is just one of the
alternate paths in a login/authentication use case, it's simply part of
the
flow. It is expected that from time to time users mistype their username,
or
some administrator may lock some account. The counterargument was that
user
providing the proper username and password is the normal case while user
mistyping the username or account being locked is the exception, so we
should
throw an exception in such cases.

I extensively went through all sorts of information and websites and blogs
on the Internet. However, I couldn't find much on such difficult and
important issue. Everybody seems to agree that opening a non-existent file
or
stuffing a non-numeric string into an integer should throw an exception.
But
that's pretty much it. Most of the applications on the market actually
deal
with cases like the above one, yet there is no clear guideline on what
could
justify throwing an exception in a business application and what not. What
is
your opinion?


Jan 13 '06 #6
An "exceptional situation" is when the software misbehaves. User error does
not constitute an "exceptional situation." Good software *expects* and deals
with user error. Exceptions are expensive in terms of performance. They
should be considered a necessary evil, and therefore, to be avoided when
possible.

Now, as to how to architect your software, there are many ways to skin the
proverbial cat. But if you keep the basic underlying principles in mind, you
will do well. The trick is to know what the underlying principles are, and
to be mindful of them. It is more difficult to work from a basis of
principle than to simply follow a set of pre-written rules. To work from a
basis of principle means that one must calculate the outcome of each
situation based upon all of the underlying principles and factors involved.
The alternative (working from an existing set of rules) is much easier (in
the short run). As humans are inherently lazy, there is often a trend toward
the latter. There are 2 very serious problems with the latter approach,
however:

1. When a situation arises that is outside the bounds of the set of rules
(which will happen eventually), one will not have the understanding of the
underlying principles involved in order to solve the problem correctly.
2. Sets of rules must be memorized, as must underlying principles. However,
where there are relatively few underlying principles, there are many rules
associated with the use of blueprints. In the long run, people often become
so involved with all the rules that they forget the principles.

Case in point: HTML was originally created without extensibility in mind. It
was created with a set of rules. As demand for functionality increased,
more rules were added, and exceptions to those rules proliferated.
Eventually, the rules of HTML became so complex that it is nearly impossible
to parse any HTML document without error. As a reaction to this, XML was
created. XML is strict, and has very few rules. However, like principles,
the rules of XML are without exception. It is nearly infinitely extensible
because it was designed to be so. The DTD used defines the rules of any XML
document, making it self-describing, and independent of any large set of
rules governing all XML documents. Because of this, it is easy to parse any
XML document without error. And it is highly likely that XHTML will
eventually replace HTML worldwide.

There has been a proliferation of patterns and blueprints in the software
world, and many of these have been adopted simply because of their
popularity. They are used without knowledge or understanding by many people.
These patterns and blueprints are sound because they are based upon the
underlying principles. They are simply collections of rules that, within
certain parameters, are derivations of the underlying principles. However,
it is important to note that they are by no means any substitute for
knowledge of those principles. When they become so, these sorts of
Lilliputian arguments are the outcome.

Your instincts are right. All you need to do is to be able to explain what
you're feeling by tying your ideas to the underlying principles, and apply
those principles to a solution.

--
HTH,

Kevin Spencer
Microsoft MVP
..Net Developer
You can lead a fish to a bicycle,
but it takes a very long time,
and the bicycle has to *want* to change.

"cat" <ca*@discussions.microsoft.com> wrote in message
news:95**********************************@microsof t.com...
I had a long and heated discussion with other developers on my team on when
it makes sense to throw an exception and when to use an alternate
solution.
The .NET documentation recommends that an exception should be thrown only
in
exceptional situations. It turned out that each of my colleagues had their
own interpretation about what an "exceptional situation" may actually be.
First of all, myself I'm against using exceptions extensively, because for
complex business applications they make the code very complicated and
because
of a long list of other issues I could post here if someone is interested.
The only arguments pro using exceptions that I was presented were that
they
force the caller to not ignore them and "this is the trend in the industry
so
we must follow".

To exemplify what an exceptional situation might be, we debated a lot on
this piece of code:

protected void login_Click()
{
try
{
UserSession objSession = _manager.StartUserSession(strUsername,
strPassword);
Session["userSession"] = objSession;
}
catch ( InvalidUsernameException ex1 ) // username does not comply to
requirements
{
. further processing
}
catch ( InvalidPasswordException ex2 ) // password does not comply to
requirements
{
. further processing
}
catch ( AuthenticationException ex3 ) // user account not found, locked,
disabled, etc.
{
. further processing
}
catch ( Exception ex4 ) // system error or any other exception we don't
need to handle separately
{
_logger.LogTheError(ex4);
. further processing
}
}

My point was that the above is an example of abusing exceptions as it's
using them for non-exceptional situations, and it's using them exactly
like
some return values. A user mistyping his password is just one of the
alternate paths in a login/authentication use case, it's simply part of
the
flow. It is expected that from time to time users mistype their username,
or
some administrator may lock some account. The counterargument was that
user
providing the proper username and password is the normal case while user
mistyping the username or account being locked is the exception, so we
should
throw an exception in such cases.

I extensively went through all sorts of information and websites and blogs
on the Internet. However, I couldn't find much on such difficult and
important issue. Everybody seems to agree that opening a non-existent file
or
stuffing a non-numeric string into an integer should throw an exception.
But
that's pretty much it. Most of the applications on the market actually
deal
with cases like the above one, yet there is no clear guideline on what
could
justify throwing an exception in a business application and what not. What
is
your opinion?

Jan 13 '06 #7
These two reasons are exactly why exceptions should be reserved for
"exceptional situations" in which you most likely want to take the
whole app down.

Jan 13 '06 #8
There is another way to approach this sort of problem.

You could use the factory approach, exactly as you outlined it.
However, your UserSession object would contain the possibility of being
"Invalid" or "NotAuthenticated" or some property like that. It could
then expose a property or properties that clients could call to
discover _why_ the session was not authenticated.

That way, you just call the factory and always get a UserSession back.
All the client has to do is ask if myUserSession.IsAuthenticated or
some such thing, and if not, ask myUserSession what went wrong.

The only time that this doesn't work is if the result coming back from
the factory is a Framework object that you cannot extend, but even in
that case you could wrap the object in your own wrapper class that can
hold failure / error message information, and then unwrap the Framework
class as soon as you've determined that the action succeeded.

Jan 13 '06 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by fred | last post: by
1 post views Thread by REH | last post: by
1 post views Thread by David Whitney | last post: by
3 posts views Thread by Steve - DND | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.