When to throw an exception?
Asked Answered
N

33

506

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?

Noleta answered 16/9, 2008 at 21:9 Comment(7)
Please reopen, this is a very sensible and valid question. Any question involves a certain amount of opinion, but in this case I suspect it is a matter of 'best practice'.Saltcellar
+1 for reopen. As many other interesting topics 'it depends' and it is very useful to analyze the tradeoffs when making decisions. The fact that people confuse opinions with facts in the answers does not negate this. Sifting through the mud is an exercise that should be left to the reader.Atmospheric
I also agree this question should be re-opened as it is related to best practices. By the way best practices are always opinions which can help others.Regardant
Microsoft says: "Do not return error codes. Exceptions are the primary means of reporting errors in frameworks." and "...If a member cannot successfully do what it is designed to do, that should be considered an execution failure and an exception should be thrown.". msdn.microsoft.com/library/ms229030%28v=vs.100%29.aspxNicknack
These might be totally sensible exception, it just depends on which methods throws them. A method called IsCredentialsValid(username,password) should not throw an exception if the username or password is invalid, but return false. But say a method which reads data from the database could legitimately throw such an exception, if the authentication fails. In short: You should throw an exception if a method is not able to do the task it is supposed to do.Officialdom
Generally, exceptions should be used if the function that notices the error cannot recover from this.Bernina
@Nicknack Since frameworks usually use OOP, exceptions should be used instead of errors because exceptions are the OOP way to handle something unpredictable. In old procedural programming, errors were the way to deal with unpredictable circumstances. So errors can be considered the old implementation of exceptions. Therefore, in PHP, errors and exceptions are defined as throwable interfaces and thus can be used interchangeably. However, it is recommended not to mix them. Also cut offs like this "do stuff or die(errormsg)" should be avoided.Potash
S
715

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.

Selfreliant answered 16/9, 2008 at 21:9 Comment(8)
Exactly! An exception is thrown when and only when function preconditions (assumptions about arguments) are broken!Archaeology
In linguistics this is sometimes called presupposition failure. The classic example is due to Bertrand Russell: "Is the King of France bald" can't be answered yes or no, (resp. "The King of France is bald" is neither true nor false), because it contains a false presupposition, namely that there is a King of France. Presupposition failure is often seen with definite descriptions, and that's common when programming. E.g. "The head of a list" has a presupposition failure when a list is empty, and then it's appropriate to throw an exception.Dreamy
This is possibly the best explanation!Beilul
Thank you. So. Much. "Is the King of France bald". I've heard this before when researching meinong's jungle.... :) Thank you. @DreamyErective
But what if instead of throwing an exception we print an error message and terminate the program? E.g. in c++ instead of throw we do exit(EXIT_FAILURE) after printing an errorLorikeet
Although the best among dozens of answers, it still doesn't express the simple rule that an exception is to be thrown if and only if a function couldn't fulfill its contract (after, hopefully, doing its best). It's the accepted way of telling your caller that the thing he requested from you didn't happen. Calling that "violated assumptions" comes close, but does not quite hit the point. It's not about internal assumptions, but about the interface to the caller.Preparedness
@Dreamy About the example in your comment "the head of a list", what if I return null instead of throwing an exception? (I'm not claiming anything, just asking as a learner.) I mean it's something absolutely predictable. And also it is different from the second example in the answer(passing a null when a List is expected). In your case, a "List" is passed, but is empty, which is quite non-exceptional. (But I upvoted your comment for "the king of France", such a nice example!).Laity
@Z80 you can return null object and log the error. if your business procedure can not work around, you can throw a exception. but you can check the every step in procedure , when you found some error, you could return early. exception is a out rang of your design or precondition, but you have more choice to correct your business procedure.Silicium
S
301

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.

Sapphism answered 16/9, 2008 at 21:9 Comment(10)
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.Feltonfelts
+1 excellent answer. I am so frustrated by developers working on API's that I have to consume, and throw Exceptions for every little thing. VERY few cases really require exceptions. If you have 25 different kinds of exceptions defined, take a look at your design again, you might be doing it wrong.Remorseless
should there be an exception when user tries an illegal action which he is not permitted to by manipulating the webpage code, for e.g. deleting someone's else posts here at StackOverflow ?Protrude
@user: IMHO, that should be handled by design methodology: en.wikipedia.org/wiki/Poka-yoke Closing the door of making mistake rather than popping up error message when user made mistake.Fearnought
Exceptions ARE control flow mechanisms. You can throw them. You can catch them. You moved control to another piece of code. That's control flow. The only reason languages have exceptions at all is so you can write straightforward code without asking "did that thing just fail?" after everything you do. Haskell, for example, does not have exceptions because the monads and do-notation can automate the error checking for you.Gastropod
um it depends. If the function is logUserIn and user gets password wrong 5 times in a row, it should throw an exception and let the caller deal with the potential attacker. Unless the function is actually logUserInAndThrottleForPotentialAttacks. But what a crappy, non-cohesive function. How "bad" a condition is is inversely proportional to how much a function is responsible for.Pipsqueak
Exception are control flow mechanisms, but that being said, you wouldn't cause your code to branch or react in response to receiving a given exception. You simply want to handle the error condition gracefully. I once wrote a piece of code that used an exception as a conditional. I was then educated about proper exception use. :)Perugia
Exceptions are more than control flow mechanisms. They give to the (method) client useful information about exceptional outcomes that they must be aware of and handled. That is, used properly, exceptions make APIs more robustSacrifice
Exceptions are control flow mechanisms that's equivalent to a non-local goto.Interlude
@Gastropod - I think you abuse (severely) exceptions. Exceptions are for exceptional cases. Don't tell me that you throw an exception if the user failed to input the correct password....Sylas
A
82

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.
Andre answered 16/9, 2008 at 21:9 Comment(0)
P
43

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.

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").

Proverbs answered 16/9, 2008 at 21:9 Comment(6)
"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.Myrtice
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.Proverbs
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.Hygrophilous
should there be an exception when user tries an illegal action which he is not permitted to by manipulating the webpage code, for e.g. deleting someone's else posts here at StackOverflow ?Protrude
@user01 when a user modifies the webpage code with e.g. Firebug or so, that occurs locall. and if he tries that to e.g. access an admin panel or enything outside his permissions then I usually let him run him face-first at the closed door where he can be kicked back to his homepage with an explanation, at least I do that on my page. No exception but some rather nice arrow code.Disseisin
It sounds like you are talking about handling errors (our of memory, computer on fire) vs handling code exceptions (missing record, invalid input type, etc). I think there is a distinct difference between the two.Violaceous
D
32

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.

Dupion answered 16/9, 2008 at 21:9 Comment(3)
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 thereMonseigneur
but why even throw them if you can handle it directly. if the password is wrong or anything is wrong I just let an if return a false and give out an errorDisseisin
"missing file on disk" Most language frameworks, e.g. .NET framework, provides APIs to check for file existence as well. Why not use them before accessing the file directly!Dungeon
B
26

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.

Barbershop answered 16/9, 2008 at 21:9 Comment(6)
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.Sapphism
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).Barbershop
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.Donegal
"Complicating your code by propagating return values through n levels up the stack is a waste of energy and will result in messy code". That, for me, is a very strong reason to use exceptions. Good code is usually comprised of small functions. You do not want to be be passing up that error code over and over from one small function to another.Michelson
I think the confusion results from an assumption perhaps that a predictable result of a login-type method would be that a password may be incorrect, it may be in fact used to determine this, and would not want to have an exception in this case; whereas in a file open type scenario, which has a particular result desired- if the system is unable to deliver the result due to incorrect input parameters or some external factor, that is a perfectly logical use of an exception.Aricaarick
"Complicating your code by propagating return values through n levels up the stack is a waste of energy and will result in messy code". It should be noted that this 'manual' propagation has the huge advantage of being predictable. Exceptions propagate the failure state up to an unpredictable point in the stack (the closest exception handler), which will result in even messier code if handled incorrectly.Alcala
W
22

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.


You will see plenty of advice, including in answers to this question, that you should throw exceptions only in "exceptional" circumstances. That seems superficially reasonable, but is flawed advice, because it replaces one question ("when should I throw an exception") with another subjective question ("what is exceptional"). Instead, follow the advice of Herb Sutter (for C++, available in the Dr Dobbs article When and How to Use Exceptions, and also in his book with Andrei Alexandrescu, C++ Coding Standards): throw an exception if, and only if

  • a precondition is not met (which typically makes one of the following impossible) or
  • the alternative would fail to meet a post-condition or
  • the alternative would fail to maintain an invariant.

Why is this better? Doesn't it replace the question with several questions about preconditions, postconditions and invariants? This is better for several connected reasons.

  • Preconditions, postconditions and invariants are design characteristics of our program (its internal API), whereas the decision to throw is an implementation detail. It forces us to bear in mind that we must consider the design and its implementation separately, and our job while implementing a method is to produce something that satisfies the design constraints.
  • It forces us to think in terms of preconditions, postconditions and invariants, which are the only assumptions that callers of our method should make, and are expressed precisely, enabling loose coupling between the components of our program.
  • That loose coupling then allows us to refactor the implementation, if necessary.
  • The post-conditions and invariants are testable; it results in code that can be easily unit tested, because the post-conditions are predicates our unit-test code can check (assert).
  • Thinking in terms of post-conditions naturally produces a design that has success as a post-condition, which is the natural style for using exceptions. The normal ("happy") execution path of your program is laid out linearly, with all the error handling code moved to the catch clauses.
Winterwinterbottom answered 16/9, 2008 at 21:9 Comment(0)
V
18

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.

Vyner answered 16/9, 2008 at 21:9 Comment(0)
M
10

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.

Marbut answered 16/9, 2008 at 21:9 Comment(0)
A
6

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.

Allsun answered 16/9, 2008 at 21:9 Comment(1)
I really liked your comment about the exceptions inside a loop and thought to give it a try myself. I wrote a sample program running a loop int.MaxValue times and generating 'divide by zero' exception in it. The IF/ELSE version, in which I was checking if the dividend is not zero before division operation, completed in 6082 ms and 15407722 ticks whereas the TRY/CATCH version, in which I was generating the exception and catching the exception, completed in 28174385 ms and 71371326155 ticks: a whopping 4632 times more than the if/else version.Dungeon
O
5

the rule of thumb for throwing exceptions is pretty simple. you do so when your code has entered into an UNRECOVERABLE INVALID state. if data is compromised or you cannot wind back the processing that occurred up to the point then you must terminate it. indeed what else can you do? your processing logic will eventually fail elsewhere. if you can recover somehow then do that and do not throw exception.

in your particular case if you were forced to do something silly like accept money withdrawal and only then check user/pasword you should terminate the process by throwing an exception to notify that something bad has happened and prevent further damage.

Ovotestis answered 16/9, 2008 at 21:9 Comment(0)
E
5

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.

Elrod answered 16/9, 2008 at 21:9 Comment(0)
S
4

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: LogicalException 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.

Sig answered 16/9, 2008 at 21:9 Comment(0)
S
3

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.

Scots answered 16/9, 2008 at 21:9 Comment(0)
H
2

for me Exception should be thrown when a required technical or business rule fails. for instance if a car entity is associated with array of 4 tires ... if one tire or more are null ... an exception should be Fired "NotEnoughTiresException" , cuz it can be caught at different level of the system and have a significant meaning through logging. besides if we just try to flow control the null and prevent the instanciation of the car . we might never never find the source of the problem , cuz the tire isn't supposed to be null in the first place .

Hammond answered 16/9, 2008 at 21:9 Comment(0)
Y
2

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;
    }
}
Yawata answered 16/9, 2008 at 21:9 Comment(0)
B
2

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.

Benumb answered 16/9, 2008 at 21:9 Comment(0)
S
2

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.

Shamrao answered 16/9, 2008 at 21:9 Comment(0)
O
2

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.

Outstrip answered 16/9, 2008 at 21:9 Comment(1)
"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." Most language frameworks, e.g. .NET framework, provides APIs to check for file existence as well. Why not use them before accessing the file directly!Dungeon
C
1

"PasswordNotCorrectException" isn't a good example for using exceptions. Users getting their passwords wrong is to be expected, so it's hardly an exception IMHO. You probably even recover from it, showing a nice error message, so it's just a validity check.

Unhandled exceptions will stop the execution eventually - which is good. If you're returning false, null or error codes, you will have to deal with the program's state all by yourself. If you forget to check conditions somewhere, your program may keep running with wrong data, and you may have a hard time figuring out what happened and where.

Of course, you could cause the same problem with empty catch statements, but at least spotting those is easier and doesn't require you to understand the logic.

So as a rule of thumb:

Use them wherever you don't want or simply can't recover from an error.

Cynosure answered 16/9, 2008 at 21:9 Comment(0)
T
1

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.

Tawnytawnya answered 16/9, 2008 at 21:9 Comment(0)
A
1

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.

Ardellardella answered 16/9, 2008 at 21:9 Comment(0)
C
1

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."

Cucullate answered 16/9, 2008 at 21:9 Comment(0)
M
1

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

Manx answered 16/9, 2008 at 21:9 Comment(0)
H
1

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.

Handbag answered 16/9, 2008 at 21:9 Comment(0)
P
1

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

Pugging answered 16/9, 2008 at 21:9 Comment(0)
J
0

I would say that exceptions should be thrown if an unexpected behaviour is occuring that wasnt meant to be.

Like trying to update or delete a non existing entity. And it should be catched where the Exception can be handled and has meaning. For working in an alternative way to continue, add logging or returning a specific result on Api level.

If you expect something to be the case, you should build code to check and ensure it.

Jobey answered 16/9, 2008 at 21:9 Comment(0)
K
0

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.

Kirstenkirsteni answered 16/9, 2008 at 21:9 Comment(0)
F
0

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.
Fanchet answered 16/9, 2008 at 21:9 Comment(0)
A
0

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.

Ambience answered 16/9, 2008 at 21:9 Comment(0)
L
-1

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
Liegeman answered 16/9, 2008 at 21:9 Comment(0)
P
-2

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
  }

}

Pugging answered 16/9, 2008 at 21:9 Comment(1)
you forgot to finish your answer with a conclusion/enlightenmentRahmann
C
-3

Here are my suggestions:

I don't think it's ALWAYS a good way to throw an exception because it will take more time, memory to process with such exceptions.

In my mind, if something can be processed with a "kind,polite" way (this means if we can "predicate such errors by using if…… or something like this), we should AVOID using "exceptions" but just return a flag like "false" , with an outer parameter value telling him/her the detailled reason.

An example is, we can make a class like this following:

public class ValueReturnWithInfo<T>
{
   public T Value{get;private set;}
   public string errorMsg{get;private set;}
   public ValueReturnWithInfo(T value,string errmsg)
   {
      Value = value;
      errMsg = errmsg;
   }
}

We can use such "multiple-value-returned" classes instead of errors, which seems to be a better,polite way to process with exception problems.

However, notice that if some errors cannot be described so easily (this depends on your programming experience) with "if"……(such as FileIO exceptions), you have to throw exceptions.

Centigrade answered 16/9, 2008 at 21:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.