tags:

views:

6932

answers:

33

I have exceptions created for every condition that my application does not expect. UserNameNotValidException, PasswordNotCorrectException etc.

However I was told I should not create exceptions for those conditions. In my UML those ARE exceptions to the main flow, so why should it not be an exception?

Any guidance or best practices for creating exceptions?

+9  A: 

Exceptions are a somewhat costly effect, if for example you have a user that provides an invalid password, it is typically a better idea to pass back a failure flag, or some other indicator that it is invalid.

This is due to the way that exceptions are handled, true bad input, and unique critical stop items should be exceptions, but not failed login info.

Mitchel Sellers
+84  A: 

Because they're things that will happen normally. Exceptions are not control flow mechanisms. Users often get passwords wrong, it's not an exceptional case. Exceptions should be a truly rare thing, UserHasDiedAtKeyboard type situations.

blowdart
beware, throwing the UserHasDiedAtKeyboard exception can kill a senior user who is just a slow typer.
Darren Kopp
hehe - nice answer :o)
Andrew
Or like PrinterOnFireException http://en.wikipedia.org/wiki/Lp0_on_fire
soulmerge
Hmm, no. Exceptions can be used as control flow mechanisms if maximum performance isn't required, which is true of most web-apps. Python uses the exception 'StopIteration' to terminate iterators, and it works very well. The cost is nothing compared to IO, etc.
Seun Osewa
+14  A: 

It is NOT an exception if the username is not valid or the password is not correct. Those are things you should expect in the normal flow of operation. Exceptions are things that are not part of the normal program operation and are rather rare.

EDIT: I do not like using exceptions because you can not tell if a method throws an exception just by looking at the call. Thats why exceptions should only be used if you can't handle the situation in a decent manner (think "out of memory" or "computer is on fire").

EricSchaefer
"I do not like using exceptions because you can not tell if a method throws an exception just by looking at the call. " this is why there are checked exceptions for languages that support them.
Newtopian
Checked exceptions have their own set of problems. I'd still rather use exceptions of "exceptional circumstances", not for things that are part of the normal workflow.
EricSchaefer
In response to your edit. I always put in my xml docs at the end of the summary section the exceptions that the function throws so that I can see that information in intellisense.
Matthew Vines
+5  A: 

I think you should only throw an exception when there's nothing you can do to get out of your current state. For example if you are allocating memory and there isn't any to allocate. In the cases you mention you can clearly recover from those states and can return an error code back to your caller accordingly.

Jon
+11  A: 

One rule of thumb is to use exceptions in the case of something you couldn't normally predict. Examples are database connectivity, missing file on disk, etc. For scenarios that you can predict, ie users attempting to log in with a bad password you should be using functions that return booleans and know how to handle the situation gracefully. You don't want to abruptly end execution by throwing an exception just because someone mistyped their password.

japollock
you needn't stop the program execution on an exception... throw the exception, the caller then catches the exeption and should handle it, if possible, log and error and move on. It is 'bad form' to just keep throwing exceptions up the call stack - catch it where it occurs, and deal with it there
Krakkos
+5  A: 

Exception classes are like "normal" classes. You create a new class when it "is" a different type of object, with different fields and different operations.

As a rule of thumb, you should try balance between the number of exceptions and the granularity of the exceptions. If your method throws more than 4-5 different exceptions, you can probably merge some of them into more "general" exceptions, (e.g. in your case "AuthenticationFailedException"), and using the exception message to detail what went wrong. Unless your code handles each of them differently, you needn't creates many exception classes. And if it does, may you should just return an enum with the error that occured. It's a bit cleaner this way.

Shachar
+3  A: 

Hi, the main reason for avoiding throwing an exception is that there is a lot of overhead involved with throwing an exception.

One thing the article below states is that an exception is for an exceptional conditions and errors.

A wrong user name is not necessarily a program error but a user error...

Here is a decent starting point for exceptions within .NET: http://msdn.microsoft.com/en-us/library/ms229030(VS.80).aspx

Sam
+2  A: 

In general you want to throw an exception for anything that can happen in your application that is "Exceptional"

In your example, both of those exceptions look like you are calling them via a password / username validation. In that case it can be argued that it isn't really exceptional that someone would mistype a username / password.

They are "exceptions" to the main flow of your UML but are more "branches" in the processing.

If you attempted to access your passwd file or database and couldn't, that would be an exceptional case and would warrant throwing an exception.

Gord
+2  A: 

Firstly, if the users of your API aren't interested in specific, fine-grained failures, then having specific exceptions for them isn't of any value.

Since it's often not possible to know what may be useful to your users, a better approach is to have the specific exceptions, but ensure they inherit from a common class (e.g., std::exception or its derivatives in C++). That allows your client to catch specific exceptions if they choose, or the more general exception if they don't care.

Jason Etheridge
+4  A: 

If it's code running inside a loop that will likely cause an exception over and over again, then throwing exceptions is not a good thing, because they are pretty slow for large N. But there is nothing wrong with throwing custom exceptions if the performance is not an issue. Just make sure that you have a base exception that they all inherite, called BaseException or something like that. BaseException inherits System.Exception, but all of your exceptions inherit BaseException. You can even have a tree of Exception types to group similar types, but this may or may not be overkill.

So, the short answer is that if it doesn't cause a significant performance penalty (which it should not unless you are throwing a lot of exceptions), then go ahead.

Charles Graham
+1  A: 

You may use a little bit generic exceptions for that conditions. For e.g. ArgumentException is meant to be used when anything goes wrong with the parameters to a method (with the exception of ArgumentNullException). Generally you would not need exceptions like LessThanZeroException, NotPrimeNumberException etc. Think of the user of your method. The number of the conditions that she will want to handle specifically is equal to the number of the type of the exceptions that your method needs to throw. This way, you can determine how detailed exceptions you will have.

By the way, always try to provide some ways for users of your libraries to avoid exceptions. TryParse is a good example, it exists so that you don't have to use int.Parse and catch an exception. In your case, you may want to provide some methods to check if user name is valid or password is correct so your users (or you) will not have to do lots of exception handling. This will hopefully result in more readble code and better performance.

Serhat Özgel
A: 

Throwing exceptions causes the stack to unwind, which has some performance impacts (admitted, modern managed environments have improved on that). Still repeatedly throwing and catching exceptions in a nested situation would be a bad idea.

Probably more important than that, exceptions are meant for exceptional conditions. They should not be used for ordinary control flow, because this will hurt your code's readability.

Arno
A: 

Ultimately the decision comes down to whether it is more helpful to deal with application-level errors like this using exception handling, or via your own home-rolled mechanism like returning status codes. I don't think there's a hard-and-fast rule about which is better, but I would consider:

  • Who's calling your code? Is this a public API of some sort or an internal library?
  • What language are you using? If it's Java, for example, then throwing a (checked) exception puts an explicit burden on your caller to handle this error condition in some way, as opposed to a return status which could be ignored. That could be good or bad.
  • How are other error conditions in the same application handled? Callers won't want to deal with a module that handles errors in an idiosyncratic way unlike anything else in the system.
  • How many things can go wrong with the routine in question, and how would they be handled differently? Consider the difference between a series of catch blocks that handle different errors and a switch on an error code.
  • Do you have structured information about the error you need to return? Throwing an exception gives you a better place to put this information than just returning a status.
eli
+57  A: 

My personal guideline is: an exception is thrown when a fundamental assumption of the current code block is found to be false.

Example 1: say I have a function which is supposed to examine an arbitrary class and return true if that class inherits from List<>. This function asks the question, "Is this object a descendant of List?" This function should never throw an exception, because there are no gray areas in its operation - every single class either does or does not inherit from List<>, so the answer is always "yes" or "no".

Example 2: say I have another function which examines a List<> and returns true if its length is more than 50, and false if the length is less. This function asks the question, "Does this list have more than 50 items?" But this question makes an assumption - it assumes that the object it is given is a list. If I hand it a NULL, then that assumption is false. In that case, if the function returns either true or false, then it is breaking its own rules. The function cannot return anything and claim that it answered the question correctly. So it doesn't return - it throws an exception.

This is comparable to the "loaded question" logical fallacy. Every function asks a question. If the input it is given makes that question a fallacy, then throw an exception. This line is harder to draw with functions that return void, but the bottom line is: if the function's assumptions about its inputs are violated, it should throw an exception instead of returning normally.

The other side of this equation is: if you find your functions throwing exceptions frequently, then you probably need to refine their assumptions.

The Digital Gabeg
what an excellent way to explain what exceptions are for !!! Thanks I will keep that and cherish it !! :-)
Newtopian
RE: Example 2 - Not that you suggested it, but I would not recommend explicitly testing for NULL or type - rather perform the operation and let the casted assignment or the .Count invocation on a null reference throw the exception.
Hafthor
@Hafthor: I do prefer to check for NULL and for type, because I don't like wrapping try / catch around everything. I expect that the time-cost of a type and null check will be a lot less than the time-cost of an exception throw and catch. As blowdart stated above, exceptions are not flow control mechanisms.
The Digital Gabeg
This is the best explanation I've seen on when to throw exceptions. +10!
kizzx2
+7  A: 

Others propose that exceptions should not be used because the bad login is to be expected in a normal flow if the user mistypes. I disagree and I don't get the reasoning. Compare it with opening a file.. if the file doesn't exist or is not available for some reason then an exception will be thrown by the framework. Using the logic above this was a mistake by Microsoft. They should have returned an error code. Same for parsing, webrequests, etc., etc..

I don't consider a bad login part of a normal flow, it's exceptional. Normally the user types the correct password, and the file does exist. The exceptional cases are exceptional and it's perfectly fine to use exceptions for those. Complicating your code by propagating return values through n levels up the stack is a waste of energy and will result in messy code. Do the simplest thing that could possibly work. Don't prematurely optimize by using error codes, exceptional stuff by definition rarely happens, and exceptions don't cost anything unless you throw them.

Bjorn Reppen
Except you can check that the file exists before calling open (depending on your framework of course). So that facility exists and thus if the file vanishes between the check and you attempting to open it then that is exception.
blowdart
The file existing does not mean the user is allowed to write to the file for example. Checking for every possible problem is really tedious and error prone. + you are duplicating the code (DRY).
Bjorn Reppen
One point with the invalid password Exception is that any slowness compared with the return code solution isn't going to be perceptible for the human user typing in a password.
paperhorse
+1  A: 

I have three type of conditions that I catch.

  1. Bad or missing input should not be an exception. Use both client side js and server side regex to detect, set attributes and forward back to the same page with messages.

  2. The AppException. This is usually an exception that you detect and throw with in your code. In other words these are ones you expect (the file does not exist). Log it, set the message, and forward back to the general error page. This page usually has a bit of info about what happened.

  3. The unexpected Exception. These are the ones you don't know about. Log it with details and forward them to a general error page.

Hope this helps

+1  A: 

Exceptions are intended for events that are abnormal behaviors, errors, failures, and such. Functional behavior, user error, etc., should be handled by program logic instead. Since a bad account or password is an expected part of the logic flow in a login routine, it should be able to handle those situations without exceptions.

Joe Skora
A: 

It depends on the context (or your taste). If you are building a reusable component that can be used in different applications or is a part of a framework, then it is preferable to use exceptions instead of error codes etc. It increases the decoupling of the client code and your component. Of course, you must follow the guideline that Shachar already proposed and have a common base exception class. In that sense, I also agree with Bjorn Reppen's answer, which I think is misunderstood from the guys that down-vote it.

And a final thought: If you have (and usually must have) an exception handling mechanism in your program, why not using it also for situations like that (UserNameNotValidException) instead of having a second mechanism like error codes?

Panos
A: 

The exceptions versus returning error code argument should be about flow control not philosophy (how "exceptional" an error is):

void f1() throws ExceptionType1, ExceptionType2 {}

void catchFunction() {
  try{
    while(someCondition){
      try{
        f1(); 
      }catch(ExceptionType2 e2){
        //do something, don't break the loop
      }
    }
  }catch(ExceptionType1 e1){
    //break the loop, do something else
  }

}

A: 

Security is conflated with your example: You shouldn't tell an attacker that a username exists, but the password is wrong. That's extra information you don't need to share. Just say "the username or password is incorrect."

+6  A: 

I would say there are no hard and fast rules on when to use exceptions. However there are good reasons for using or not using them:

Reasons to use exceptions:

  • The code flow for the common case is clearer
  • Can return complex error information as an object (although this can also be achieved using error "out" parameter passed by reference)
  • Languages generally provide some facility for managing tidy cleanup in the event of the exception (try/finally in Java, using in C#, RAII in C++)
  • In the event no exception is thrown, execution can sometimes be faster than checking return codes
  • In Java, checked exceptions must be declared or caught (although this can be a reason against)

Reasons not to use exceptions:

  • Sometimes it's overkill if the error handling is simple
  • If exceptions are not documented or declared, they may be uncaught by calling code, which may be worse than if the the calling code just ignored a return code (application exit vs silent failure - which is worse may depend on the scenario)
  • In C++, code that uses exceptions must be exception safe (even if you don't throw or catch them, but call a throwing function indirectly)
  • In C++, it is hard to tell when a function might throw, therefore you must be paranoid about exception safety if you use them
  • Throwing and catching exceptions is generally significantly more expensive compared to checking a return flag

In general, I would be more inclined to use exceptions in Java than in C++ or C#, because I am of the opinion that an exception, declared or not, is fundamentally part of the formal interface of a function, since changing your exception guarantee may break calling code. The biggest advantage of using them in Java IMO, is that you know that your caller MUST handle the exception, and this improves the chance of correct behaviour.

Because of this, in any language, I would always derive all exceptions in a layer of code or API from a common class, so that calling code can always guarantee to catch all exceptions. Also I would consider it bad to throw exception classes that are implementation-specific, when writing an API or library (i.e. wrap exceptions from lower layers so that the exception that your caller receives is understandable in the context of your interface).

Note that Java makes the distinction between general and Runtime exceptions in that the latter need not be declared. I would only use Runtime exception classes when you know that the error is a result of a bug in the program.

Robert
+2  A: 

I agree with japollock way up there--throw an acception when you are uncertain about the outcome of an operation. Calls to APIs, accessing filesystems, database calls, etc. Anytime you are moving past the "boundaries" of your programming languages.

I'd like to add, feel free to throw a standard exception. Unless you are going to do something "different" (ignore, email, log, show that twitter whale picture thingy, etc), then don't bother with custom exceptions.

dclaysmith
A: 

There are two main classes of exception:

1) System exception (eg Database connection lost) or 2) User exception. (eg User input validation, 'password is incorrect')

I found it helpful to create my own User Exception Class and when I want to throw a user error I want to be handled differently (ie resourced error displayed to the user) then all I need do in my main error handler is check the object type:

            If TypeName(ex) = "UserException" Then
               Display(ex.message)
            Else
               DisplayError("An unexpected error has occured, contact your help  desk")                   
               LogError(ex)
            End If
Crusty
+1  A: 

A while back I wrote a blog post about precisely this subject. Here it is:

http://typethinker.blogspot.com/2007/04/checks-exceptions-and-assertions.html

But don't just listen to what I say; be sure to read what Eric Lippert has to say on this topic:

http://blogs.msdn.com/ericlippert/archive/2008/09/10/vexing-exceptions.aspx

Thomas
A: 

Some useful things to think about when deciding whether an exception is appropriate:

  1. what level of code you want to have run after the exception candidate occurs - that is, how many layers of the call stack should unwind. You generally want to handle an exception as close as possible to where it occurs. For username/password validation, you would normally handle failures in the same block of code, rather than letting an exception bubble up. So an exception is probably not appropriate. (OTOH, after three failed login attempts, control flow may shift elsewhere, and an exception may be appropriate here.)

  2. Is this event something you would want to see in an error log? Not every exception is written to an error log, but it's useful to ask whether this entry in an error log would be useful - i.e., you would try to do something about it, or would be the garbage you ignore.

Mike Kantor
A: 

The simple answer is, whenever an operation is impossible (because of either application OR because it would violate business logic). If a method is invoked and it impossible to do what the method was written to do, throw an Exception. A good example is that constructors always throw ArgumentExceptions if an instance cannot be created using the supplied parameters. Another example is InvalidOperationException, which is thrown when an operation cannot be performed because of the state of another member or members of the class.

In your case, if a method like Login(username, password) is invoked, if the username is not valid, it is indeed correct to throw a UserNameNotValidException, or PasswordNotCorrectException if password is incorrect. The user cannot be logged in using the supplied parameter(s) (i.e. it's impossible because it would violate authentication), so throw an Exception. Although I might have your two Exceptions inherit from ArgumentException.

Having said that, if you wish NOT to throw an Exception because a login failure may be very common, one strategy is to instead create a method that returns types that represent different failures. Here's an example:

{ // class
    ...

    public LoginResult Login(string user, string password)
    {
     if (IsInvalidUser(user))
     {
      return new UserInvalidLoginResult(user);
     }
     else if (IsInvalidPassword(user, password))
     {
      return new PasswordInvalidLoginResult(user, password);
     }
     else
     {
      return new SuccessfulLoginResult();
     }
    }

    ...
}

public abstract class LoginResult
{
    public readonly string Message;

    protected LoginResult(string message)
    {
     this.Message = message;
    }
}

public class SuccessfulLoginResult : LoginResult
{
    public SucccessfulLogin(string user)
     : base(string.Format("Login for user '{0}' was successful.", user))
    { }
}

public class UserInvalidLoginResult : LoginResult
{
    public UserInvalidLoginResult(string user)
     : base(string.Format("The username '{0}' is invalid.", user))
    { }
}

public class PasswordInvalidLoginResult : LoginResult
{
    public PasswordInvalidLoginResult(string password, string user)
     : base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
    { }
}

Most developers are taught to avoid Exceptions because of the overhead caused by throwing them. It's great to be resource-conscious, but usually not at the expense of your application design. That is probably the reason you were told not to throw your two Exceptions. Whether to use Exceptions or not usually boils down to how frequently the Exception will occur. If it's a fairly common or an fairly expectable result, this is when most developers will avoid Exceptions and instead create another method to indicate failure, because of the supposed consumption of resources.

Here's an example of avoiding using Exceptions in a scenario like just described, using the Try() pattern:

public class ValidatedLogin
{
    public readonly string User;
    public readonly string Password;

    public ValidatedLogin(string user, string password)
    {
     if (IsInvalidUser(user))
        {
            throw new UserInvalidException(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            throw new PasswordInvalidException(password);
        }

     this.User = user;
     this.Password = password;
    }

    public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
    {
     if (IsInvalidUser(user) || 
         IsInvalidPassword(user, password))
        {
            return false;
        }

     validatedLogin = new ValidatedLogin(user, password);

     return true;
    }
}
Chris
A: 

On my favorite blog for September I found this post:

Exception design relativity

klasbas
+1  A: 

Hi,

I just want to add 2 Links here, both blogpost writen by Paul Houle:

Both an interessting read, there is no "real" answer, but this should get you on your way.

HuibertGill
+1  A: 

I'd say that generally every fundamentalism leads to hell.

You certainly wouldn't want to end up with exception driven flow, but avoiding exceptions altogether is also a bad idea. You have to find a balance between both approaches. What I would not do is to create an exception type for every exceptional situation. That is not productive.

What I generally prefer is to create two basic types of exceptions which are used throughout the system: LocicalException and TechnicalException. These can be further distinguished by subtypes if needed, but it is not generally not necessary.

The technical exception denotes the really unexpected exception like database server being down, the connection to the web service threw the IOException and so on.

On the other hand the logical exceptions are used to propagate the less severe erroneous situation to the upper layers (generally some validation result).

Please note that even the logical exception is not intended to be used on regular basis to control the program flow, but rather to highlight the situation when the flow should really end. When used in Java, both exception types are RuntimeException subclasses and error handling is highly aspect oriented.

So in the login example it might be wise to create something like AuthenticationException and distinguish the concrete situations by enum values like UsernameNotExisting, PasswordMismatch etc. Then you won't end up in having a huge exception hierarchy and can keep the catch blocks on maintainable level. You can also easily employ some generic exception handling mechanism since you have the exceptions categorized and know pretty well what to propagate up to the user and how.

Our typical usage is to throw the LogicalException during the Web Service call when the user's input was invalid. The Exception gets marshalled to the SOAPFault detail and then gets unmarshalled to the exception again on the client which is resulting in showing the validation error on one certain web page input field since the exception has proper mapping to that field.

This is certainly not the only situation: you don't need to hit web service to throw up the exception. You are free to do so in any exceptional situation (like in the case you need to fail-fast) - it is all at your discretion.

Petr Macek
+3  A: 

My little guidelines are heavily influenced by the great book "Code complete": - Use exceptions to notify about things that should not be ignored. - Don't use exceptions if the error can be handled locally - Make sure the exceptions are at the same level of abstraction as the rest of your routine. - Exceptions should be reserved for what's truly exceptional.

Commander Keen
+1  A: 

I have philosophical problems with the use of exceptions. Basically, you are expecting a specific scenario to occur, but rather than handling it explicitly you are pushing the problem off to be handled "elsewhere." And where that "elsewhere" is can be anyone's guess.

Dan
A: 

Create new exceptions when you'd like to express two error states or more in your return value.

yogman
A: 

To my mind, the fundamental question should be whether one would expect that the caller would want to continue normal program flow if a condition occurs. If you don't know, either have separate doSomething and trySomething methods, where the former returns an error and the latter does not, or have a routine that accepts a parameter to indicate whether an exception should be thrown if it fails). Consider a class to send commands to a remote system and report responses. Certain commands (e.g. restart) will cause the remote system to send a response but then be non-responsive for a certain length of time. It is thus useful to be able to send a "ping" command and find out whether the remote system responds in a reasonable length of time without having to throw an exception if it doesn't (the caller would probably expect that the first few "ping" attempts would fail, but one would eventually work). On the other hand, if one has a sequence of commands like:

  exchange_command("open tempfile");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("write tempfile data {whatever}");
  exchange_command("close tempfile");
  exchange_command("copy tempfile to realfile");

one would want failure of any operation to abort the whole sequence. While one could check each operation to ensure it succeeded, it's more helpful to have the exchange_command() routine throw an exception if a command fails.

Actually, in the above scenario it may be helpful to have a parameter to select a number of failure-handling modes: never throw exceptions, throw exceptions for communication errors only, or throw exceptions in any cases where a command does not return a "success" indication.

supercat