Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Yesterday I was having a heated debate with a coworker on what would be the preferred error reporting method. Mainly we were discussing the usage of exceptions or error codes for reporting errors between application layers or modules.
What rules do you use to decide if you throw exceptions or return error codes for error reporting?
In high-level stuff, exceptions; in low-level stuff, error codes.
The default behaviour of an exception is to unwind the stack and stop the program, if I'm writing a script an and I go for a key that's not in a dictionary it's probably an error, and I want the program to halt and let me know all about that.
If, however, I'm writing a piece of code which I must know the behaviour of in every possible situation, then I want error codes. Otherwise I have to know every exception that can be thrown by every line in my function to know what it will do (Read The Exception That Grounded an Airline to get an idea of how tricky this is). It's tedious and hard to write code that reacts appropriately to every situation (including the unhappy ones), but that's because writing error-free code is tedious and hard, not because you're passing error codes.
Both Raymond Chen and Joel have made some eloquent arguments against using exceptions for everything.
I normally prefer exceptions, because they have more contextual information and can convey (when properly used) the error to the programmer in a clearer fashion.
On the other hand, error codes are more lightweight than exceptions but are harder to maintain. Error checking can inadvertently be omitted. Error codes are harder to maintain because you have to keep a catalog with all error codes and then switch on the result to see what error was thrown. Error ranges can be of help here, because if the only thing we are interested in is if we are in the presence of an error or not, it is simpler to check (e.g., an HRESULT error code greater or equal to 0 is success and less than zero is failure). They can inadvertently be omitted because there is no programmatic forcing that the developer will check for error codes. On the other hand, you cannot ignore exceptions.
To summarize I prefer exceptions over error codes in almost all situations.
I prefer exceptions because
they interupt the flow of logic
they benefit from class hierarchy which gives more features/functionality
when used properly can represent a wide range of errors (e.g. an InvalidMethodCallException is also a LogicException, as both occur when there's a bug in your code that should be detectable before runtime), and
they can be used to enhance the error (i.e. a FileReadException class definition can then contain code to check whether the file exists, or is locked, etc)
Error codes can be ignored (and often are!) by the callers of your functions. Exceptions at least force them to deal with the error in some way. Even if their version of dealing with it is to have an empty catch handler (sigh).
Exceptions over error codes, no doubt about it. You get much of the same benefits from exceptions as you do with error codes, but also much more, without the shortcomings of error codes. The only knock on exceptions is that it is slightly more overhead; but in this day and age, that overhead should be considered negligible for nearly all applications.
Here are some articles discussing, comparing and contrasting the two techniques:
Object Oriented Exception Handling in Perl
Exceptions vs. status returns
There are some good links in those that can give you further reading.
I would never mix the two models...it's too hard to convert from one to the other as you move from one part of the stack which is using error codes, to a higher piece that is using exceptions.
Exceptions are for "anything that stops or inhibits the method or subroutine from doing what you asked it to do" ... NOT to pass messages back about irregularities or unusual circumstances, or the state of the system, etc. Use return values or ref (or out) parameters for that.
Exceptions allow methods to be written (and utilized) with semantics that are dependent on the method's function, i.e. a method that returns an Employee object or List of Employees can be typed to do just that, and you can utilize it by calling.
Employee EmpOfMonth = GetEmployeeOfTheMonth();
With error codes, all methods return an error code, so, for those that need to return something else to be used by the calling code, you have to pass a reference variable to be populated with that data, and test the return value for the error code, and handle it, on every function or method call.
Employee EmpOfMonth;
if (getEmployeeOfTheMonth(ref EmpOfMonth) == ERROR)
// code to Handle the error here
If you code so that each method does one and only one simple thing, then you should throw an exception whenever the method cannot accomplish the method's desired objective. Exceptions are much richer and easier to use in this way than error codes. Your code is much cleaner - The standard flow of the "normal" code path can be devoted strictly to the case where the method IS able to accomplish what you wanted it to do... And then the code to clean up, or handle the "exceptional" circumstances when something bad happens that prevents the method from completing successfully can be siloed away from the normal code. Additionally, if you can't handle the exception where it occurred, and must pass it up the stack to a UI, (or worse, across the wire from a mid-tier component to a UI), then with the exception model, you don't need to code every intervening method in your stack to recognize and pass the exception up the stack... The exception model does this for you automagically.... With error codes, this piece of the puzzle can get onerous very rapidly.
You should use both. The thing is to decide when to use each one.
There are a few scenarios where exceptions are the obvious choice:
In some situations you can't do anything with the error code, and you just need to handle it in an upper level in the call stack, usually just log the error, display something to the user or close the program. In these cases, error codes would require you to bubble up the error codes manually level by level which is obviously much easier to do with exceptions. The point is that this is for unexpected and unhandleable situations.
Yet about situation 1 (where something unexpected and unhandleable happens you just wan't to log it), exceptions can be helpful because you might add contextual information. For example if I get a SqlException in my lower-level data helpers, I will want to catch that error in the low-level (where I know the SQL command that caused the error) so I can capture that information and rethrow with additional information. Please note the magic word here: rethrow, and not swallow.
The first rule of exception handling: do not swallow exceptions. Also, note that my inner catch doesn't need to log anything because the outer catch will have the whole stack trace and may log it.
In some situations you have a sequence of commands, and if any of them fail you should cleanup/dispose resources(*), whether or not this is an unrecoverable situation (which should be thrown) or a recoverable situation (in which case you can handle locally or in the caller code but you don't need exceptions). Obviously it's much easier to put all those commands in a single try, instead of testing error codes after each method, and cleanup/dispose in the finally block. Please note that if you want the error to bubble up (which is probably what you want), you don't even need to catch it - you just use the finally for cleanup/dispose - you should only use catch/retrow if you want to add contextual information (see bullet 2).
One example would be a sequence of SQL statements inside a transaction block. Again, this also a "unhandleable" situation, even if you decide to catch it early (treat it locally instead of bubbling up to the top) it's still a fatal situation from where the best outcome is to abort everything or at least abort a large part of the process.
(*) This is like the on error goto that we used in old Visual Basic
In constructors you can only throw exceptions.
Having said that, in all other situations where you're returning some information on which the caller CAN/SHOULD take some action, using return codes is probably a better alternative. This includes all expected "errors", because probably they should be handled by the immediate caller, and will hardly need to be bubbled up too many levels up in the stack.
Of course it's always possible to treat expected errors as exceptions, and catch then immediately one level above, and it's also possible to encompass every line of code in a try catch and take actions for each possible error. IMO, this is bad design, not only because it's much more verbose, but specially because the possible exceptions that might be thrown are not obvious without reading the source code - and exceptions could be thrown from any deep method, creating invisible gotos. They break code structure by creating multiple invisible exit points that make code hard to read and inspect. In other words, you should never use exceptions as flow-control, because that would be hard for others to understand and maintain. It can get even difficult to understand all possible code flows for testing.
Again: for correct cleanup/dispose you can use try-finally without catching anything.
The most popular criticism about return codes is that "someone could ignore the error codes, but in the same sense someone can also swallow exceptions. Bad exception handling is easy in both methods. But writing good error-code-based program is still much easier than writing an exception-based program. And if one by any reason decides to ignore all errors (the old on error resume next), you can easily do that with return codes and you can't do that without a lot of try-catchs boilerplate.
The second most popular criticism about return codes is that "it's difficult to bubble up" - but that's because people don't understand that exceptions are for non-recoverable situations, while error-codes are not.
Deciding between exceptions and error codes is a gray area. It's even possible that you need to get an error code from some reusable business method, and then you decide to wrap that into an exception (possibly adding information) and let it bubble up. But it's a design mistake to assume that ALL errors should be thrown as exceptions.
To sum it up:
I like to use exceptions when I have an unexpected situation, in which there's not much to do, and usually we want to abort a large block of code or even the whole operation or program. This is like the old "on error goto".
I like to use return codes when I have expected situations in which the caller code can/should take some action. This includes most business methods, APIs, validations, and so on.
This difference between exceptions and error codes is one of the design principles of the GO language, which uses "panic" for fatal unexpected situations, while regular expected situations are returned as errors.
Yet about GO, it also allows multiple return values , which is something that helps a lot on using return codes, since you can simultaneously return an error and something else. On C#/Java we can achieve that with out parameters, Tuples, or (my favorite) Generics, which combined with enums can provide clear error codes to the caller:
public MethodResult<CreateOrderResultCodeEnum, Order> CreateOrder(CreateOrderOptions options)
{
....
return MethodResult<CreateOrderResultCodeEnum>.CreateError(CreateOrderResultCodeEnum.NO_DELIVERY_AVAILABLE, "There is no delivery service in your area");
...
return MethodResult<CreateOrderResultCodeEnum>.CreateSuccess(CreateOrderResultCodeEnum.SUCCESS, order);
}
var result = CreateOrder(options);
if (result.ResultCode == CreateOrderResultCodeEnum.OUT_OF_STOCK)
// do something
else if (result.ResultCode == CreateOrderResultCodeEnum.SUCCESS)
order = result.Entity; // etc...
If I add a new possible return in my method, I can even check all callers if they are covering that new value in a switch statement for example. You really can't do that with exceptions. When you use return codes, you'll usually know in advance all possible errors, and test for them. With exceptions you usually don't know what might happen. Wrapping enums inside exceptions (instead of Generics) is an alternative (as long as it's clear the type of exceptions that each method will throw), but IMO it's still bad design.
EDIT 2020-10-11:
Since C# 7.0 (March 2017) instead of Generics I prefer to use the new Tuples syntax which allows multiple return values (so we can use GO-like syntax where methods return a result OR an error).
public enum CreateUserResultCodeEnum
{
[Description("Username not available")]
NOT_AVAILABLE,
}
public (User user, CreateUserResultCodeEnum? error) CreateUser(string userName)
// (try to create user, check if not available...)
if (notAvailable)
return (null, CreateUserResultCodeEnum.NOT_AVAILABLE);
return (user, null);
}
// How to call and deconstruct tuple:
(var user, var error) = CreateUser("john.doe");
if (user != null) ...
if (error == CreateUserResultCodeEnum.NOT_AVAILABLE) ...
// Or returning a single object (named tuple):
var result = CreateUser("john.doe");
if (result.user != null) ...
if (result.error == CreateUserResultCodeEnum.NOT_AVAILABLE) ...
EDIT 2021-01-09:
A few days ago I wrote this blog post about how we can (in some cases!) use multiple returns instead of exceptions (like golang convention explained above, not supposed to replace all your exceptions but supposed to give you arsenal to decide between when to use exceptions and when to use return codes).
By the end of the post I'm mixing two models - basically I'm using the ValueTuple syntax (which is very concise and elegant) but yet using Generics as the underlying structure.
Basically I use implicit conversion operator and type deconstructors to convert back and forth between ValueTuple and CommandResult<TEntity, TError>.
In the past I joined the errorcode camp (did too much C programming). But now I have seen the light.
Yes exceptions are a bit of a burden on the system. But they simplify the code, reducing the number of errors (and WTF's).
So use exception but use them wise. And they will be your friend.
As a side note. I have learned to document which exception can be thrown by which method. Unfortunately this is not required by most languages. But it increases the chance of handling the right exceptions at the right level.
There may be a few situations where using exceptions in a clean, clear, correct way is cumbersome, but the vast majority of the time exceptions are the obvious choice. The biggest benefit exception handling has over error codes is that it changes the flow of execution, which is important for two reasons.
When an exception occurs, the application is no longer following it's 'normal' execution path. The first reason why this is so important is that unless the author of the code goes well and truly out of their way to be bad, the program will halt and not continue doing unpredictable things. If an error code doesn't get checked and appropriate actions aren't taken in response to a bad error code, the program will keep on doing what it's doing and who knows what the result of that action will be. There are lots of situations where having the program do 'whatever' could wind up being very expensive. Consider a program that retrieves performance information for various financial instruments a company sells, and delivers that information to brokers/wholesalers. If something goes wrong and the program keeps going, it could ship erroneous performance data to the brokers and wholesalers. I don't know about anybody else, but I don't want to be the one sitting in a VPs office explaining why my code caused the company to get 7-figures worth of regulatory fines. Delivering an error message to customers is generally preferable to delivering wrong data that could look to be 'real', and the latter situation is much easier to run into with a much less aggressive approach like error codes.
The second reason why I like exceptions and their breaking of the normal execution is that it makes it much, much easier to keep the 'normal things are happening' logic separate from the 'something went wrong logic'. To me, this:
try {
// Normal things are happening logic
catch (// A problem) {
// Something went wrong logic
}
...is preferable to this:
// Some normal stuff logic
if (errorCode means error) {
// Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
// Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
// Some stuff went wrong logic
}
There are other little things about exceptions that are nice, as well. Having a bunch of conditional logic to keep track of whether any of the methods being called in a function had an error code returned, and return that error code higher up is a lot of boiler plate. In fact, it's a lot of boiler plate that can go wrong. I have a lot more faith in the exception system of most languages than I do a rats nest of if-else-if-else statements that 'Fresh-out-of-college' Fred wrote, and I have a lot better things to do with my time than code reviewing said rat's nest.
My reasoning would be if you are writing a low-level driver that really needs performance, then use error codes. But if you're using that code in a higher-level application and it can handle a bit of overhead, then wrap that code with an interface which checks those error codes and raises exceptions.
In all other cases, exceptions are probably the way to go.
My approach is that we can use both, i.e. Exceptions and Errors codes at the same time.
I'm used to define several types of Exceptions (ex: DataValidationException or ProcessInterruptExcepion) and inside each exception define a more detailed description of each problem.
A Simple Example in Java:
public class DataValidationException extends Exception {
private DataValidation error;
/**
*
*/
DataValidationException(DataValidation dataValidation) {
super();
this.error = dataValidation;
}
}
enum DataValidation{
TOO_SMALL(1,"The input is too small"),
TOO_LARGE(2,"The input is too large");
private DataValidation(int code, String input) {
this.input = input;
this.code = code;
}
private String input;
private int code;
}
In this way i use Exceptions to define category errors, and error codes to define more detailed info about the problem.
I may be sitting on the fence here, but...
It depends on the language.
Whichever model you choose, be consistent about how you use it.
In Python, use of exceptions is standard practice, and I'm quite happy to define my own exceptions. In C you don't have exceptions at all.
In C++ (in the STL at least), exceptions are typically only thrown for truly exceptional errors (I virtually never see them myself). I see no reason to do anything different in my own code. Yes it's easy to ignore return values, but C++ doesn't force you to catch exceptions either. I think you just have to get into the habit of doing it.
The code base I work on is mostly C++ and we use error codes almost everywhere, but there's one module that raises exceptions for any error, including very unexceptional ones, and all the code that uses that module is pretty horrible. But that might just be because we've mixed exceptions and error codes. The code that consistently uses error codes is much easier to work with. If our code consistently used exceptions, maybe it wouldn't be as bad. Mixing the two doesn't seem to work so well.
Since I work with C++, and have RAII to make them safe to use, I use exceptions almost exclusively. It pulls error handling out of the normal program flow and makes the intent more clear.
I do leave exceptions for exceptional circumstances though. If I'm expecting that a certain error is going to happen a lot I'll check that the operation will succeed before performing it, or call a version of the function that uses error codes instead (Like TryParse())
Method signatures should communicate to you what the method does. Something like
long errorCode = getErrorCode();
might be fine, but
long errorCode = fetchRecord();
is confusing.
Exceptions are for exceptional circumstances - ie, when they are not part of the normal flow of the code.
It's quite legitimate to mix Exceptions and error codes, where error codes represent the status of something, rather than an error in the running of the code per se (e.g. checking the return code from a child process).
But when an exceptional circumstance occurs I believe Exceptions are the most expressive model.
There are cases where you might prefer, or have, to use error codes in place of Exceptions, and these have been adequately covered already (other than other obvious constrains such as compiler support).
But going in the other direction, using Exceptions allows you to build even higher level abstractions to your error handling, that can make your code even more expressive and natural. I would highly recommend reading this excellent, yet underrated, article by C++ expert Andrei Alexandrescu on the subject of what he calls, "Enforcements": http://www.ddj.com/cpp/184403864. Although it's a C++ article the principles are generally applicable, and I have translated the enforcements concept to C# quite successfully.
First, I agree with Tom's answer that for high-level stuff use exceptions, and for low-level stuff use error codes, as long as it is not Service Oriented Architecture (SOA).
In SOA, where methods may be called across different machines, exceptions may not be passed over the wire, instead, we use success/failure responses with a structure like below (C#):
public class ServiceResponse
{
public bool IsSuccess => string.IsNullOrEmpty(this.ErrorMessage);
public string ErrorMessage { get; set; }
}
public class ServiceResponse<TResult> : ServiceResponse
{
public TResult Result { get; set; }
}
And use like this:
public async Task<ServiceResponse<string>> GetUserName(Guid userId)
{
var response = await this.GetUser(userId);
if (!response.IsSuccess) return new ServiceResponse<string>
{
ErrorMessage = $"Failed to get user."
};
return new ServiceResponse<string>
{
Result = user.Name
};
}
When these are used consistently in your service responses it creates a very nice pattern of handling success/failures in the application. This allows easier error handling in async calls within services as well as across services.
I would prefer Exceptions for all error cases, except when a failure is an expectable bug-free result of a function that returns a primitive datatype. E.g. finding the index of a substring within a larger string would usually return -1 if not found, instead of raising a NotFoundException.
Returning invalid pointers that might be dereferenced (e.g. causing NullPointerException in Java) is not acceptable.
Using multiple different numerical error codes (-1, -2) as return values for the same function is usually bad style, as clients might do a "== -1" check instead of "< 0".
One thing to keep in mind here is the evolution of APIs over time. A good API allows to change and extend failure behavior in several ways without breaking clients. E.g. if a client error handle checked for 4 error cases, and you add a fifth error value to your function, the client handler may not test this and break. If you raise Exceptions, this will usually make it easier for clients to migrate to a newer version of a library.
Another thing to consider is when working in a team, where to draw a clear line for alldevelopers to make such a decision. E.g. "Exceptions for high-level stuff, error codes for low-level stuff" is very subjective.
In any case, where more than one trivial type of error is possible, the source code should never use the numeric literal to return an error code or to handle it (return -7, if x == -7 ...), but always a named constant (return NO_SUCH_FOO, if x == NO_SUCH_FOO) .
If you work under big project, you can't use only exceptions or only error codes. In different cases you should use different approaches.
For example, you decide to use exceptions only. But once you decide to use async event processing. It is bad idea to use exceptions for error handling in this situations. But use error codes everywhere in application is tedious.
So my opinion that it is normal to use both exceptions and error codes simultaneous.
For most applications, exceptions are better. The exception is when the software has to communicate with other devices. The domain I work in is industrial controls. Here errors codes are preferred and expected. So my answer is that it does depend on the situation.
I think it also depends on whether you really need information like stack trace from the result. If yes, you definitely go for Exception which provide object full with lots of information about problem. However, if you are just interested in result and don't care why that result then go for error code.
e.g. When you are processing file and face IOException, client might interested in knowing from where this was triggered, in opening file or parsing file etc. So better you return IOException or its specific subclass. However, scenario like you have login method and you want to know it was successful or not, there either you just return boolean or to show correct message, return error code. Here Client is not interested in knowing which part of logic caused that error code. He just know if its Credential invalid or account lock etc.
Another usecase I can think of is when data travels on network. Your remote method can return just error code instead of Exception to minimize data transfer.
My general rule is:
Only one error could appear in a function: use error code (as parameter of the function)
More than one specific error could appear: throw exception
Error codes also don't work when your method returns anything other than a numeric value...
Related
I tried to find resources on what is the standardised and accepted idiomatic D-way of handling errors, but I couldn't find any. If one is reading the official documentation on error handling, then one finds the following very important statements there:
Errors are not part of the normal flow of a program. Errors are exceptional, unusual, and unexpected.
Because errors are unusual, execution of error handling code is not performance critical.
The normal flow of program logic is performance critical.
I call them important, because the reasoning on using exceptions for such, well, exceptional cases is what leads the article towards the conclusion, that errors are special cases after all, and exceptions are the way to go, no matter what the costs are. Again from the same article:
Because errors are unusual, execution of error handling code is not performance critical. Exception handling stack unwinding is a relatively slow process.
In some special cases, where the exceptions may not be handled explicitly, but their presence should effect the state of things anyway, one should use the exception safe scope guards.
My main problem is, the above mentioned solutions and their examples in the documentations are indeed exceptional cases, which are pretty useful when we are hitting for example memory-related problems, but we don't want our program to fail, we want to maintain integrity and recover from those scenarios if possible, but what about other cases?
As we all know errors are not only used for exceptional cases and unexpected scenarios, but they are ways of communicating between callers and callees. For example errors can be used in a sanitiser. Let's say we want to implement a schema validation for an associative array. The type system alone is not capable of defining the constraints of the keys and values, so we create a function to check such objects during run time. So what should happen if the schema fails? Since we are interested on how it fails, the error that happened in it (that is, invalid data found) should also contain the information on what went wrong, therefore the caller would know how to act upon on it. Using exceptions is an expensive abstraction according to the author of the first article. Using the C-style function conventions, where the return values are all used for error states is the wrong way according to the same author in the same article.
So, what is the proper and idiomatic way of handling errors that are not exceptions in D?
Well, the TLDR version is that using exceptions is the idiomatic way to handle error conditions in D, but of course, the details get a bit more complicated than that.
Part of the question is what constitutes an error. The term error is used for many things, and as a result, talking about errors can be quite confusing. Some classes of errors are programmatic errors (and thus the result of bugs in the program), others aren't programmatic errors but are so catastrophic that the program can't continue, and others depend on stuff like user input and can often be recovered from.
For programmatic errors and catastrophic errors, D has the Error class, which derives from Throwable. Two of the commonly used subclasses of Error are AssertError and RangeError - AssertError being the result of a failed assertion, and RangeError being what you get when you try to index an array with an index that's out-of-bounds. Both of those are programmatic errors; they're the result of bugs in your program, and recovering from them makes no sense, because by definition, your program is in an invalid state at that point. An example of an error that's not a bug but which is generally catastrophic enough that your program should be terminated is MemoryError, which is thrown when new fails to allocate memory.
When an Error is thrown, there is no guarantee that any clean-up code will be run (e.g. destructors and scope statements may be skipped, because the assumption is that because your code is in an invalid state, the clean-up code could actually make things worse). The program simply unwinds the stack, prints out the Error's message and stack trace, and terminates your program. So, attempting to catch an Error and have the program continue is almost always a terrible idea, because the program is in an unknown and invalid state. If something is considered an Error, then it is the sort of condition where the error condition is considered unrecoverable, and programs should not be attempting to recover from it.
For the most part, you probably won't do anything explicit with Errors. You'll put assertions in your code to catch bugs when not compiling with -release, but you probably won't be throwing any Errors explicitly. They're mostly the result of D's runtime or assertions in code you're running catching bugs in your program.
The other class that derives from Throwable is Exception. It's used for cases where the problem is not a bug in your program but rather a problem due to user input or the environment (e.g. the XML that the user provided is invalid, or a file that your program attempts to open does not exist). Exceptions provide a way for a function to report that its input was invalid or that it's unable to complete its task due to issues outside its control. The program can then choose to catch that Exception and try to recover from it, or it can let it bubble up to the top and kill the program (though typically, it's more user-friendly to catch them and print out something more user-friendly than a message with a stack trace). Unlike Errors, Exceptions do result in all clean-up code being run. So, it's completely safe to catch them and continue executing.
However, what the program can do in response to the exception and whether it can do more than report to the user that an error occurred and terminate depends on what the exception was and what the program is doing (which is part of why some code subclasses Exception - it provides a way to report what went wrong beyond just an error message and allows the program to respond to it programmatically based on the type of thing that went wrong rather than simply responding to the fact that "something" went wrong). By using exceptions to report when something goes wrong, it allows for code to not directly handle errors unless it's the place in the code that you want to be handling errors, resulting in much cleaner code overall but with the downside that you can sometimes get exceptions being thrown that you weren't expecting if you weren't familiar enough with what could be thrown when. But that also means that errors that are reported don't get missed like they can be with error codes. If you forget to handle an exception, you'll know it when it happens, whereas with something like an error code, it's easy to forget to check it or not realize that you need to, and errors can be missed. So, while unexpected exceptions can be annoying, they help ensure that you catch problems in your program when they occur.
Now, the best time to use assertions vs exceptions can be a bit of an art. For instance, with Design by Contract, you use assertions to check the input to a function, because any code that calls that function with invalid arguments is in violation of the contract and therefore considered buggy, whereas in defensive programming, you don't assume that the input is valid, so the function always checks its input (not just when not compiling with -release), and it throws an Exception on failure. Which approach makes more sense depends on what you're doing and where the input for the function is likely to come from. But it's never appropriate to use assertions to check user input or anything that is outside of the program's control, because bad input is not a bug in the program.
However, while in general, the idiomatic way to handle error cases in D may be to throw an exception, there are times where that really doesn't make sense. For instance, if the error condition is actually extremely likely to occur, throwing an exception is an awfully expensive way to handle it. Exceptions are generally fast enough for cases that aren't happening all the time, but for something that happens frequently - especially in performance-critical code - they can be too expensive. And in such cases, doing something like an error code can make more sense - or doing something like returning a Nullable and having it be null when the function failed to get a result.
In general, exceptions make the most sense when it's reasonable to assume that the function will succeed and/or when it streamlines the code to make it so that it doesn't have to worry about the error condition.
For instance, imagine writing an XML parser that used error codes instead of exceptions. Each function in its implementation would have to be checking whether any function it called succeeded and return whether it itself succeeded, which would not only be error-prone, but it would mean that you'd essentially have error-handling code everywhere throughout the parser. On the other hand, if you use exceptions, then most of the parser doesn't have to care about errors in the XML. Instead of code that encounters invalid XML having to return an error code that the function calling it has to deal with, it can just throw an exception, and whatever code in the call chain is actually a good place to handle the error (probably the code that called the parser in the first place) is then the only code that has to deal with the error. The only error handling code in your program is then code that needs to deal with errors rather than most of your program. The code is much cleaner that way.
Another example where exceptions really clean up code would be a function like std.file.isDir. It returns whether the file name it's given corresponds to a directory and throws a FileException when something goes wrong (e.g. the file doesn't exist, or the user doesn't have permission to access it). For that to work with an error code, you'd be stuck doing something like
int isDir(string filename, ref bool result);
which means that you can't simply put it in a condition like
if(file.isDir)
{
...
}
You'd be stuck with something ugly like
bool result;
immutable error = file.isDir(result);
if(error != 0)
{
...
}
else if(result)
{
...
}
It's true that in many cases, there's a high risk of the file not existing, which would be an argument for using error codes, but std.file.exists makes it possible to easily check for that condition before calling isDir and thus ensure that isDir failing is the uncommon case - or if the code in question is written in a way that it's highly likely that the file exists (e.g. it was gotten from dirEntries), then you don't have to bother checking whether the file exists. Either way, the result is much cleaner and less error-prone than dealing with error codes.
In any case, the most appropriate solution depends on what your code is doing, and there are cases where exceptions really don't make sense, but in general, they are the idiomatic way to deal with errors that are not bugs in your program or catastrophic errors like running out of memory, and Error's are normally the best way to deal with encountering bugs in your program or catastrophic errors. Ultimately though, it is a bit of art to know when and how to use exceptions vs other techniques, and it generally takes experience to have a good feel for it, which is part of why questions about when to use exceptions, assertions, and error codes pop up from time to time.
I have always been of the belief that if a method can throw an exception then it is reckless not to protect this call with a meaningful try block.
I just posted 'You should ALWAYS wrap calls that can throw in try, catch blocks.' to this question and was told that it was 'remarkably bad advice' - I'd like to understand why.
A method should only catch an exception when it can handle it in some sensible way.
Otherwise, pass it on up, in the hope that a method higher up the call stack can make sense of it.
As others have noted, it is good practice to have an unhandled exception handler (with logging) at the highest level of the call stack to ensure that any fatal errors are logged.
As Mitch and others stated, you shouldn't catch an exception that you do not plan on handling in some way. You should consider how the application is going to systematically handle exceptions when you are designing it. This usually leads to having layers of error handling based on the abstractions - for example, you handle all SQL-related errors in your data access code so that the part of the application that is interacting with domain objects is not exposed to the fact that there is a DB under the hood somewhere.
There are a few related code smells that you definitely want to avoid in addition to the "catch everything everywhere" smell.
"catch, log, rethrow": if you want scoped based logging, then write a class that emits a log statement in its destructor when the stack is unrolling due to an exception (ala std::uncaught_exception()). All that you need to do is declare a logging instance in the scope that you are interested in and, voila, you have logging and no unnecessary try/catch logic.
"catch, throw translated": this usually points to an abstraction problem. Unless you are implementing a federated solution where you are translating several specific exceptions into one more generic one, you probably have an unnecessary layer of abstraction... and don't say that "I might need it tomorrow".
"catch, cleanup, rethrow": this is one of my pet-peeves. If you see a lot of this, then you should apply Resource Acquisition is Initialization techniques and place the cleanup portion in the destructor of a janitor object instance.
I consider code that is littered with try/catch blocks to be a good target for code review and refactoring. It indicates that either exception handling is not well understood or the code has become an amœba and is in serious need of refactoring.
Because the next question is "I've caught an exception, what do I do next?" What will you do? If you do nothing - that's error hiding and the program could "just not work" without any chance to find what happened. You need to understand what exactly you will do once you've caught the exception and only catch if you know.
You don't need to cover every block with try-catches because a try-catch can still catch unhandled exceptions thrown in functions further down the call stack. So rather than have every function have a try-catch, you can have one at the top level logic of your application. For example, there might be a SaveDocument() top-level routine, which calls many methods which call other methods etc. These sub-methods don't need their own try-catches, because if they throw, it's still caught by SaveDocument()'s catch.
This is nice for three reasons: it's handy because you have one single place to report an error: the SaveDocument() catch block(s). There's no need to repeat this throughout all the sub-methods, and it's what you want anyway: one single place to give the user a useful diagnostic about something that went wrong.
Two, the save is cancelled whenever an exception is thrown. With every sub-method try-catching, if an exception is thrown, you get in to that method's catch block, execution leaves the function, and it carries on through SaveDocument(). If something's already gone wrong you likely want to stop right there.
Three, all your sub-methods can assume every call succeeds. If a call failed, execution will jump to the catch block and the subsequent code is never executed. This can make your code much cleaner. For example, here's with error codes:
int ret = SaveFirstSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
ret = SaveSecondSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
ret = SaveThirdSection();
if (ret == FAILED)
{
/* some diagnostic */
return;
}
Here's how that might be written with exceptions:
// these throw if failed, caught in SaveDocument's catch
SaveFirstSection();
SaveSecondSection();
SaveThirdSection();
Now it's much clearer what is happening.
Note exception safe code can be trickier to write in other ways: you don't want to leak any memory if an exception is thrown. Make sure you know about RAII, STL containers, smart pointers, and other objects which free their resources in destructors, since objects are always destructed before exceptions.
Herb Sutter wrote about this problem here. For sure worth reading.
A teaser:
"Writing exception-safe code is fundamentally about writing 'try' and 'catch' in the correct places." Discuss.
Put bluntly, that statement reflects a fundamental misunderstanding of exception safety. Exceptions are just another form of error reporting, and we certainly know that writing error-safe code is not just about where to check return codes and handle error conditions.
Actually, it turns out that exception safety is rarely about writing 'try' and 'catch' -- and the more rarely the better. Also, never forget that exception safety affects a piece of code's design; it is never just an afterthought that can be retrofitted with a few extra catch statements as if for seasoning.
As stated in other answers, you should only catch an exception if you can do some sort of sensible error handling for it.
For example, in the question that spawned your question, the questioner asks whether it is safe to ignore exceptions for a lexical_cast from an integer to a string. Such a cast should never fail. If it did fail, something has gone terribly wrong in the program. What could you possibly do to recover in that situation? It's probably best to just let the program die, as it is in a state that can't be trusted. So not handling the exception may be the safest thing to do.
If you always handle exceptions immediately in the caller of a method that can throw an exception, then exceptions become useless, and you'd better use error codes.
The whole point of exceptions is that they need not be handled in every method in the call chain.
The best advice I've heard is that you should only ever catch exceptions at points where you can sensibly do something about the exceptional condition, and that "catch, log and release" is not a good strategy (if occasionally unavoidable in libraries).
I was given the "opportunity" to salvage several projects and executives replaced the entire dev team because the app had too many errors and the users were tired of the problems and run-around. These code bases all had centralized error handling at the app level like the top voted answer describes. If that answer is the best practice why didn't it work and allow the previous dev team to resolve issues? Perhaps sometimes it doesn't work? The answers above don't mention how long devs spend fixing single issues. If time to resolve issues is the key metric, instrumenting code with try..catch blocks is a better practice.
How did my team fix the problems without significantly changing the UI? Simple, every method was instrumented with try..catch blocked and everything was logged at the point of failure with the method name, method parameters values concatenated into a string passed in along with the error message, the error message, app name, date, and version. With this information developers can run analytics on the errors to identify the exception that occurs the most! Or the namespace with the highest number of errors. It can also validate that an error that occurs in a module is properly handled and not caused by multiple reasons.
Another pro benefit of this is developers can set one break-point in the error logging method and with one break-point and a single click of the "step out" debug button, they are in the method that failed with full access to the actual objects at the point of failure, conveniently available in the immediate window. It makes it very easy to debug and allows dragging execution back to the start of the method to duplicate the problem to find the exact line. Does centralized exception handling allow a developer to replicate an exception in 30 seconds? No.
The statement "A method should only catch an exception when it can handle it in some sensible way." This implies that developers can predict or will encounter every error that can happen prior to release. If this were true a top level, app exception handler wouldn't be needed and there would be no market for Elastic Search and logstash.
This approach also lets devs find and fix intermittent issues in production! Would you like to debug without a debugger in production? Or would you rather take calls and get emails from upset users? This allows you to fix issues before anyone else knows and without having to email, IM, or Slack with support as everything needed to fix the issue is right there. 95% of issues never need to be reproduced.
To work properly it needs to be combined with centralized logging that can capture the namespace/module, class name, method, inputs, and error message and store in a database so it can be aggregated to highlight which method fails the most so it can be fixed first.
Sometimes developers choose to throw exceptions up the stack from a catch block but this approach is 100 times slower than normal code that doesn't throw. Catch and release with logging is preferred.
This technique was used to quickly stabilize an app that failed every hour for most users in a Fortune 500 company developed by 12 Devs over 2 years. Using this 3000 different exceptions were identified, fixed, tested, and deployed in 4 months. This averages out to a fix every 15 minutes on average for 4 months.
I agree that it is not fun to type in everything needed to instrument the code and I prefer to not look at the repetitive code, but adding 4 lines of code to each method is worth it in the long run.
I agree with the basic direction of your question to handle as many exceptions as possible at the lowest level.
Some of the existing answer go like "You don't need to handle the exception. Someone else will do it up the stack." To my experience that is a bad excuse to not think about exception handling at the currently developed piece of code, making the exception handling the problem of someone else or later.
That problem grows dramatically in distributed development, where you may need to call a method implemented by a co-worker. And then you have to inspect a nested chain of method calls to find out why he/she is throwing some exception at you, which could have been handled much easier at the deepest nested method.
The advice my computer science professor gave me once was: "Use Try and Catch blocks only when it's not possible to handle the error using standard means."
As an example, he told us that if a program ran into some serious issue in a place where it's not possible to do something like:
int f()
{
// Do stuff
if (condition == false)
return -1;
return 0;
}
int condition = f();
if (f != 0)
{
// handle error
}
Then you should be using try, catch blocks. While you can use exceptions to handle this, it's generally not recommended because exceptions are expensive performance wise.
If you want to test the outcome of every function, use return codes.
The purpose of Exceptions is so that you can test outcomes LESS often. The idea is to separate exceptional (unusual, rarer) conditions out of your more ordinary code. This keeps the ordinary code cleaner and simpler - but still able to handle those exceptional conditions.
In well-designed code deeper functions might throw and higher functions might catch. But the key is that many functions "in between" will be free from the burden of handling exceptional conditions at all. They only have to be "exception safe", which does not mean they must catch.
I would like to add to this discussion that, since C++11, it does make a lot of sense, as long as every catch block rethrows the exception up until the point it can/should be handled. This way a backtrace can be generated. I therefore believe the previous opinions are in part outdated.
Use std::nested_exception and std::throw_with_nested
It is described on StackOverflow here and here how to achieve this.
Since you can do this with any derived exception class, you can add a lot of information to such a backtrace!
You may also take a look at my MWE on GitHub, where a backtrace would look something like this:
Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"
I feel compelled to add another answer although Mike Wheat's answer sums up the main points pretty well. I think of it like this. When you have methods that do multiple things you are multiplying the complexity, not adding it.
In other words, a method that is wrapped in a try catch has two possible outcomes. You have the non-exception outcome and the exception outcome. When you're dealing with a lot of methods this exponentially blows up beyond comprehension.
Exponentially because if each method branches in two different ways then every time you call another method you're squaring the previous number of potential outcomes. By the time you've called five methods you are up to 256 possible outcomes at a minimum. Compare this to not doing a try/catch in every single method and you only have one path to follow.
That's basically how I look at it. You might be tempted to argue that any type of branching does the same thing but try/catches are a special case because the state of the application basically becomes undefined.
So in short, try/catches make the code a lot harder to comprehend.
Besides the above advice, personally I use some try+catch+throw; for the following reason:
At boundary of different coder, I use try + catch + throw in the code written by myself, before the exception being thrown to the caller which is written by others, this gives me a chance to know some error condition occured in my code, and this place is much closer to the code which initially throw the exception, the closer, the easier to find the reason.
At the boundary of modules, although different module may be written my same person.
Learning + Debug purpose, in this case I use catch(...) in C++ and catch(Exception ex) in C#, for C++, the standard library does not throw too many exception, so this case is rare in C++. But common place in C#, C# has a huge library and an mature exception hierarchy, the C# library code throw tons of exception, in theory I(and you) should know every exceptions from the function you called, and know the reason/case why these exception being thrown, and know how to handle them(pass by or catch and handle it in-place)gracefully. Unfortunately in reality it's very hard to know everything about the potential exceptions before I write one line of code. So I catch all and let my code speak aloud by logging(in product environment)/assert dialog(in development environment) when any exception really occurs. By this way I add exception handling code progressively. I know it conflit with good advice but in reality it works for me and I don't know any better way for this problem.
You have no need to cover up every part of your code inside try-catch. The main use of the try-catch block is to error handling and got bugs/exceptions in your program. Some usage of try-catch -
You can use this block where you want to handle an exception or simply you can say that the block of written code may throw an exception.
If you want to dispose your objects immediately after their use, You can use try-catch block.
I understand that "Exceptions are for exceptional cases" [a], but besides just being repeated over and over again, I've never found an actual reason for this fact.
Being that they halt execution, it makes sense that you wouldn't want them for plain conditional logic, but why not input validation?
Say you were to loop through a group of inputs and catch each exception to group them together for user notification... I continually see that this is somehow "wrong" because users enter incorrect input all the time, but that point seems to be based on semantics.
The input is Not what was expected and hence is exceptional. Throwing an exception allows me to define exactly what was wrong like StringValueTooLong or or IntegerValueTooLow or InvalidDateValue or whatever. Why is this considered wrong?
Alternatives to throwing an exception would be to either return (and eventually collect) an error code or far worse an error string. Then I would either show those error strings directly, or parse the error codes and then show corresponding error messages to the user. Wouldn't a exception be considered a malleable error code? Why create a separate table of error codes and messages, when these could be generalized with the exception functionality already built into my language?
Also, I found this article by Martin Fowler as to how to handle such things - the Notification pattern. I'm not sure how I see this as being anything other than Exceptions that don't halt execution.
a: Everywhere I've read anything about Exceptions.
--- Edit ---
Many great points have been made. I've commented on most and +'d the good points, but I'm not yet completely convinced.
I don't mean to advocate Exceptions as the proper means to resolve Input Validation, but I would like to find good reasons why the practice is considered so evil when it seems most alternate solutions are just Exceptions in disguise.
Reading these answers, I find it very unhelpful to say, "Exceptions should only be used for exceptional conditions". This begs the whole question of what is an "exceptional condition". This is a subjective term, the best definition of which is "any condition that your normal logic flow doesn't deal with". In other words, an exceptional condition is any condition you deal with using exceptions.
I'm fine with that as a definition, I don't know that we'll get any closer than that anyway. But you should know that that's the definition you are using.
If you are going to argue against exceptions in a certain case, you have to explain how to divide the universe of conditions into "exceptional" and "non-exceptional".
In some ways, it's similar to answering the question, "where are the boundaries between procedures?" The answer is, "Wherever you put the begin and end", and then we can talk about rules of thumb and different styles for determining where to put them. There are no hard and fast rules.
A user entering 'bad' input is not an exception: it's to be expected.
Exceptions should not be used for normal control flow.
In the past many authors have said that Exceptions are inherently expensive. Jon Skeet has blogged contrary to this (and mentioned a few time in answers here on SO), saying that they are not as expensive as reported (although I wouldn’t advocate using them in a tight loop!)
The biggest reason to use them is ‘statement of intent’ i.e. if you see an exception handling block you immediately see the exceptional cases which are dealt with outside of normal flow.
There is one important other reason than the ones mentioned already:
If you use exceptions only for exceptional cases you can run in your debugger with the debugger setting "stop when exception is thrown". This is extremely convenient because you drop into the debugger on the exact line that is causing the problem. Using this feature saves you a fair amount of time every day.
In C# this is possible (and I recommend it wholeheartedly), especially after they added the TryParse methods to all the number classes. In general, none of the standard libraries require or use "bad" exception handling. When I approach a C# codebase that has not been written to this standard, I always end up converting it to exception-free-for-regular cases, because the stop-om-throw is so valuable.
In the firebug javascript debugger you can also do this, provided that your libraries don't use exceptions badly.
When I program Java, this is not really possible because so many things uses exceptions for non-exceptional cases, including a lot of the standard java libraries. So this time-saving feature is not really available for use in java. I believe this is due to checked exceptions, but I won't start ranting about how they are evil.
Errors and Exceptions – What, When and Where?
Exceptions are intended to report errors, thereby making code more robust. To understand when to use exceptions, one must first understand what errors are and what is not an error.
A function is a unit of work, and failures should be viewed as errors or otherwise based on their impact on functions. Within a function f, a failure is an error if and only if it prevents f from meeting any of its callee’s preconditions, achieving any of f’s own postconditions, or reestablishing any invariant that f shares responsibility for maintaining.
There are three kinds of errors:
a condition that prevents the function from meeting a precondition (e.g., a parameter restriction) of another function that must be called;
a condition that prevents the function from establishing one of its own postconditions (e.g., producing a valid return value is a postcondition); and
a condition that prevents the function from re-establishing an invariant that it is responsible for maintaining. This is a special kind of postcondition that applies particularly to member functions. An essential postcondition of every non-private member function is that it must re-establish its class’s invariants.
Any other condition is not an error and should not be reported as an error.
Why are Exceptions said to be so bad for Input Validation?
I guess it is because of a somewhat ambiguous understanding of “input” as either meaning input of a function or value of a field, where the latter should’t throw an exception unless it is part of a failing function.
Maintainability - Exceptions create
odd code paths, not unlike GOTOs.
Ease of Use (for other classes) -
Other classes can trust that
exceptions raised from your user
input class are actual errors
Performance - In most languages, an
exception incurs a performance and
memory usage penalty.
Semantics - The meaning of words
does matter. Bad input is not
"exceptional".
I think the difference depends on the contract of the particular class, i.e.
For code that is meant to deal with user input, and program defensively for it (i.e. sanitise it) it would be wrong to throw an exception for invalid input - it is expected.
For code that is meant to deal with already sanitised and validated input, which may have originated with the user, throwing an exception would be valid if you found some input that is meant to be forbidden. The calling code is violating the contract in that case, and it indicates a bug in the sanitising and/or calling code.
When using exceptions, the error handling code is separated from the code causing the error. This is the intent of exception handling - being an exceptional condition, the error can not be handled locally, so an exception is thrown to some higher (and unknown) scope. If not handled, the application will exit before any more hard is done.
If you ever, ever, ever throw exception when you are doing simple logic operations, like verifying user input, you are doing something very, very very, wrong.
The input is Not what was expected and
hence is exceptional.
This statement does not sit well with me at all. Either the UI constrains user input (eg, the use of a slider that bounds min/max values) and you can now assert certain conditions - no error handling required. Or, the user can enter rubbish and you expect this to happen and must handle it. One or the other - there is nothing exception going here whatsoever.
Throwing an exception allows me to
define exactly what was wrong like
StringValueTooLong or or
IntegerValueTooLow or InvalidDateValue
or whatever. Why is this considered
wrong?
I consider this beyond - closer to evil. You can define an abstract ErrorProvider interface, or return a complex object representing the error rather than a simple code. There are many, many options on how you retrieve error reports. Using exceptions because the are convenient is so, so wrong. I feel dirty just writing this paragraph.
Think of throwing an exception as hope. A last chance. A prayer. Validating user input should not lead to any of these conditions.
Is it possible that some of the disagreement is due to a lack of consensus about what 'user input' means? And indeed, at what layer you're coding.
If you're coding a GUI user interface, or a Web form handler, you might well expect invalid input, since it's come direct from the typing fingers of a human being.
If you're coding the model part of an MVC app, you may have engineered things so that the controller has sanitised inputs for you. Invalid input getting as far as the Model would indeed be an exception, and may be treated as such.
If you're coding a server at the protocol level, you might reasonably expect the client to be checking user input. Again, invalid input here would indeed be an exception. This is quite different from trusting the client 100% (that would be very stupid indeed) - but unlike direct user input, you predict that most of the time inputs would be OK. The lines blur here somewhat. The more likely it is that something happens, the less you want to use exceptions to handle it.
This is a linguistic pov( point of view) on the matter.
Why are Exceptions said to be so bad for Input Validation?
conclusion :
Exceptions are not defined clearly enough, so there are different opinions.
Wrong input is seen as a normal thing, not as an exception.
thoughts ?
It probably comes down to the expectations one takes about the code that is created.
the client can not be trusted
validation has to happen at the server's side.
stronger : every validation happens at server's side.
because validation happens at the server's side it is expected to be done there and what is expected is not an exception, since it is expected.
However,
the client's input can not to be trusted
the client's input-validation can be trusted
if validation is trusted it can be expected to produce valid input
now every input is expected to be valid
invalid input is now unexpected, an exception
.
exceptions can be a nice way to exit the code.
A thing mentioned to consider is if your code is left in a proper state.
I would not know what would leave my code in an improper state.
Connections get closed automatically, leftover variables are garbage-collected, what's the problem?
Another vote against exception handling for things that aren't exceptions!
In .NET the JIT compiler won't perform optimizations in certain cases even when exceptions aren't thrown. The following articles explain it well.
http://msmvps.com/blogs/peterritchie/archive/2007/06/22/performance-implications-of-try-catch-finally.aspx
http://msmvps.com/blogs/peterritchie/archive/2007/07/12/performance-implications-of-try-catch-finally-part-two.aspx
When an exception gets thrown it generates a whole bunch of information for the stack trace which may not be needed if you were actually "expecting" the exception as is often the case when converting strings to int's etc...
In general, libraries throw exceptions and clients catch them and do something intelligent with them. For user input I just write validation functions instead of throwing exceptions. Exceptions seem excessive for something like that.
There are performance issues with exceptions, but in GUI code you won't generally have to worry about them. So what if a validation takes an extra 100 ms to run? The user isn't going to notice that.
In some ways it's a tough call - On the one hand, you might not want to have your entire application come crashing down because the user entered an extra digit in a zip code text box and you forgot to handle the exception. On the other, a 'fail early, fail hard' approach ensures that bugs get discovered and fixed quickly and keeps your precious database sane. In general I think most frameworks recommend that you don't use exception handling for UI error checking and some, like .NET Windows Forms, provide nice ways to do this (ErrorProviders and Validation events) without exceptions.
Exceptions should not be used for input validation, because not only should exceptions be used in exceptional circumstances (which as it has been pointed out incorrect user entry is not) but they create exceptional code (not in the brilliant sense).
The problem with exceptions in most languages is they change the rules of program flow, this is fine in a truly exceptional circumstance where it is not necessarily possible to figure our what the valid flow should be and therefore just throw an exception and get out however where you know what the flow should be you should create that flow (in the case listed it would be to raise a message to the user telling them they need to reenter some information).
Exceptions were truly overused in an application I work on daily and even for the case where a user entered an incorrect password when logging in, which by your logic would be an exception result because it is not what the application wants. However when a process has one of two outcomes either correct or incorrect, I dont think we can say that, incorrect, no matter how wrong, is exceptional.
One of the major problems I have found with working with this code is trying to follow the logic of the code without getting deeply involved with the debugger. Although debuggers are great, it should be possible to add logic to what happens when a user enters an incorrect password without having to fire one up.
Keep exceptions for truly exceptional execution not just wrong. In the case I was highlighting getting your password wrong is not exceptional, but not being able to contact the domain server may be!
When I see exceptions being thrown for validation errors I often see that the method throwing the exception is performing lots of validations all at once. e.g.
public bool isValidDate(string date)
{
bool retVal = true;
//check for 4 digit year
throw new FourDigitYearRequiredException();
retVal = false;
//check for leap years
throw new NoFeb29InANonLeapYearException();
retVal = false;
return retVal;
}
This code tends to be pretty fragile and hard to maintain as the rules pile up over the months and years. I usually prefer to break up my validations into smaller methods that return bools. It makes it easier to tweak the rules.
public bool isValidDate(string date)
{
bool retVal = false;
retVal = doesDateContainAFourDigitYear(date);
retVal = isDateInALeapYear(date);
return retVal;
}
public bool isDateInALeapYear(string date){}
public bool doesDateContainAFourDigitYear(string date){}
As has been mentioned already, returning an error struct/object containing information about the error is a great idea. The most obvious advantage being that you can collect them up and display all of the error messages to the user at once instead of making them play Whack-A-Mole with the validation.
i used a combination of both a solution:
for each validation function, i pass a record that i fill with the validation status (an error code).
at the end of the function, if a validation error exists, i throw an exception, this way i do not throw an exception for each field, but only once. i also took advantage that throwing an exception will stop execution because i do not want the execution to continue when data is invalid.
for example
procedure Validate(var R:TValidationRecord);
begin
if Field1 is not valid then
begin
R.Field1ErrorCode=SomeErrorCode;
ErrorFlag := True;
end;
if Field2 is not valid then
begin
R.Field2ErrorCode=SomeErrorCode;
ErrorFlag := True;
end;
if Field3 is not valid then
begin
R.Field3ErrorCode=SomeErrorCode;
ErrorFlag := True;
end;
if ErrorFlag then
ThrowException
end;
if relying on boolean only, the developer using my function should take this into account writing:
if not Validate() then
DoNotContinue();
but he may forgot and only call Validate() (i know that he should not, but maybe he might).
so, in the code above i gained the two advantages:
1-only one exception in the validation function.
2-exception, even uncaught, will stop the execution, and appear at test time.
8 years later, and I'm running into the same dilemma trying to apply the CQS pattern. I'm on the side that input validation can throw an exception, but with an added constraint. If any input fails, you need to throw ONE type of exception: ValidationException, BrokenRuleException, etc. Don't throw a bunch of different types as it'll be impossible to handle them all. This way, you get a list of all the broken rules in one place. You create a single class that is responsible for doing validation (SRP) and throw an exception if at least 1 rule is broken. That way, you handle one situation with one catch and you know you are good. You can handle that scenario no matter what code is called. This leaves all the code downstream much cleaner as you know it is in a valid state or it wouldn't have gotten there.
To me, getting invalid data from a user is not something you would normally expect. (If every user sends invalid data to you the first time, I'd take a second look at your UI.) Any data that prevents you from processing the true intent whether it is user or sourced elsewhere needs to abort processing. How is it any different than throwing an ArgumentNullException from a single piece of data if it was user input vs. it being a field on a class that says This is required.
Sure, you could do validation first and write that same boilerplate code on every single "command", but I think that is a maintenance nightmare than catching invalid user input all in one place at the top that gets handled the same way regardless. (Less code!) The performance hit will only come if the user gives invalid data, which should not happen that often (or you have bad UI). Any and all rules on the client side have to be re-written on the server, anyway, so you could just write them once, do an AJAX call, and the < 500 ms delay will save you a ton of coding time (only 1 place to put all your validation logic).
Also, while you can do some neat validation with ASP.NET out of the box, if you want to re-use your validation logic in other UIs, you can't since it is baked into ASP.NET. You'd be better off creating something below and handling it above regardless of the UI being used. (My 2 cents, at least.)
I agree with Mitch that that "Exceptions should not be used for normal control flow". I just want to add that from what I remember from my computer science classes, catching exceptions is expensive. I've never really tried to do benchmarks, but it would be interesting to compare performance between say, an if/else vs try/catch.
One problem with using exceptions is a tendency to detect only one problem at a time. The user fixes that and resubmits, only to find another problem! An interface that returns a list of issues that need resolving is much friendlier (though it could be wrapped in an exception).
My question is what do most developers prefer for error handling, Exceptions or Error Return Codes. Please be language(or language family) specific and why you prefer one over the other.
I'm asking this out of curiosity. Personally I prefer Error Return Codes since they are less explosive and don't force user code to pay the exception performance penalty if they don't want to.
update: thanks for all the answers! I must say that although I dislike the unpredictability of code flow with exceptions. The answer about return code (and their elder brother handles) do add lots of Noise to the code.
For some languages (i.e. C++) Resources leak should not be a reason
C++ is based on RAII.
If you have code that could fail, return or throw (that is, most normal code), then you should have your pointer wrapped inside a smart pointer (assuming you have a very good reason to not have your object created on stack).
Return codes are more verbose
They are verbose, and tend to develop into something like:
if(doSomething())
{
if(doSomethingElse())
{
if(doSomethingElseAgain())
{
// etc.
}
else
{
// react to failure of doSomethingElseAgain
}
}
else
{
// react to failure of doSomethingElse
}
}
else
{
// react to failure of doSomething
}
In the end, you code is a collection of idented instructions (I saw this kind of code in production code).
This code could well be translated into:
try
{
doSomething() ;
doSomethingElse() ;
doSomethingElseAgain() ;
}
catch(const SomethingException & e)
{
// react to failure of doSomething
}
catch(const SomethingElseException & e)
{
// react to failure of doSomethingElse
}
catch(const SomethingElseAgainException & e)
{
// react to failure of doSomethingElseAgain
}
Which cleanly separate code and error processing, which can be a good thing.
Return codes are more brittle
If not some obscure warning from one compiler (see "phjr" 's comment), they can easily be ignored.
With the above examples, assume than someone forgets to handle its possible error (this happens...). The error is ignored when "returned", and will possibly explode later (i.e. a NULL pointer). The same problem won't happen with exception.
The error won't be ignored. Sometimes, you want it to not explode, though... So you must chose carefully.
Return Codes must sometimes be translated
Let's say we have the following functions:
doSomething, which can return an int called NOT_FOUND_ERROR
doSomethingElse, which can return a bool "false" (for failed)
doSomethingElseAgain, which can return an Error object (with both the __LINE__, __FILE__ and half the stack variables.
doTryToDoSomethingWithAllThisMess which, well... Use the above functions, and return an error code of type...
What is the type of the return of doTryToDoSomethingWithAllThisMess if one of its called functions fail ?
Return Codes are not a universal solution
Operators cannot return an error code. C++ constructors can't, too.
Return Codes means you can't chain expressions
The corollary of the above point. What if I want to write:
CMyType o = add(a, multiply(b, c)) ;
I can't, because the return value is already used (and sometimes, it can't be changed). So the return value becomes the first parameter, sent as a reference... Or not.
Exception are typed
You can send different classes for each kind of exception. Ressources exceptions (i.e. out of memory) should be light, but anything else could be as heavy as necessary (I like the Java Exception giving me the whole stack).
Each catch can then be specialized.
Don't ever use catch(...) without re-throwing
Usually, you should not hide an error. If you do not re-throw, at the very least, log the error in a file, open a messagebox, whatever...
Exception are... NUKE
The problem with exception is that overusing them will produce code full of try/catches. But the problem is elsewhere: Who try/catch his/her code using STL container? Still, those containers can send an exception.
Of course, in C++, don't ever let an exception exit a destructor.
Exception are... synchronous
Be sure to catch them before they bring out your thread on its knees, or propagate inside your Windows message loop.
The solution could be mixing them?
So I guess the solution is to throw when something should not happen. And when something can happen, then use a return code or a parameter to enable to user to react to it.
So, the only question is "what is something that should not happen?"
It depends on the contract of your function. If the function accepts a pointer, but specifies the pointer must be non-NULL, then it is ok to throw an exception when the user sends a NULL pointer (the question being, in C++, when didn't the function author use references instead of pointers, but...)
Another solution would be to show the error
Sometimes, your problem is that you don't want errors. Using exceptions or error return codes are cool, but... You want to know about it.
In my job, we use a kind of "Assert". It will, depending on the values of a configuration file, no matter the debug/release compile options:
log the error
open a messagebox with a "Hey, you have a problem"
open a messagebox with a "Hey, you have a problem, do you want to debug"
In both development and testing, this enable the user to pinpoint the problem exactly when it is detected, and not after (when some code cares about the return value, or inside a catch).
It is easy to add to legacy code. For example:
void doSomething(CMyObject * p, int iRandomData)
{
// etc.
}
leads a kind of code similar to:
void doSomething(CMyObject * p, int iRandomData)
{
if(iRandomData < 32)
{
MY_RAISE_ERROR("Hey, iRandomData " << iRandomData << " is lesser than 32. Aborting processing") ;
return ;
}
if(p == NULL)
{
MY_RAISE_ERROR("Hey, p is NULL !\niRandomData is equal to " << iRandomData << ". Will throw.") ;
throw std::some_exception() ;
}
if(! p.is Ok())
{
MY_RAISE_ERROR("Hey, p is NOT Ok!\np is equal to " << p->toString() << ". Will try to continue anyway") ;
}
// etc.
}
(I have similar macros that are active only on debug).
Note that on production, the configuration file does not exist, so the client never sees the result of this macro... But it is easy to activate it when needed.
Conclusion
When you code using return codes, you're preparing yourself for failure, and hope your fortress of tests is secure enough.
When you code using exception, you know that your code can fail, and usually put counterfire catch at chosen strategic position in your code. But usually, your code is more about "what it must do" then "what I fear will happen".
But when you code at all, you must use the best tool at your disposal, and sometimes, it is "Never hide an error, and show it as soon as possible". The macro I spoke above follow this philosophy.
I use both actually.
I use return codes if it's a known, possible error. If it's a scenario that I know can, and will happen, then there's a code that gets sent back.
Exceptions are used solely for things that I'm NOT expecting.
According to Chapter 7 titled "Exceptions" in Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, numerous rationales are given for why using exceptions over return values is necessary for OO frameworks such as C#.
Perhaps this is the most compelling reason (page 179):
"Exceptions integrate well with object-oriented languages. Object-oriented languages tend to impose constraints on member signatures that are not imposed by functions in non-OO languages. For example, in the case of constructors, operator overloads, and properties, the developer has no choice in the return value. For this reason, it is not possible to standardize on return-value-based error reporting for object-oriented frameworks. An error reporting method, such as exceptions, which is out of band of the method signature is the only option."
My preference (in C++ and Python) is to use exceptions. The language-provided facilities make it a well-defined process to both raise, catch and (if necessary) re-throw exceptions, making the model easy to see and use. Conceptually, it's cleaner than return codes, in that specific exceptions can be defined by their names, and have additional information accompanying them. With a return code, you're limited to just the error value (unless you want to define an ReturnStatus object or something).
Unless the code you're writing is time-critical, the overhead associated with unwinding the stack is not significant enough to worry about.
Exceptions should only be returned where something happens that you were not expecting.
The other point of exceptions, historically, is that return codes are inherently proprietary, sometimes a 0 could be returned from a C function to indicate success, sometimes -1, or either of them for a fail with 1 for a success. Even when they are enumerated, enumerations can be ambiguous.
Exceptions can also provide a lot more information, and specifically spell out well 'Something Went Wrong, here's what, a stack trace and some supporting information for the context'
That being said, a well enumerated return code can be useful for a known set of outcomes, a simple 'heres n outcomes of the function, and it just ran this way'
Always use exceptions by default, BUT consider providing an additional tester-doer option (TryX)!
For me the answer is really clear. When the context dictates a Try or Tester-Doer pattern (ie cpu intensive or public api), I will ADDITIONALLY provide those methods to the exception throwing version. I think blanket rules of avoiding exceptions are misguided, unsupported, and likely cause far more expense in terms of bugs, than any performance issues they claim to prevent.
No, Microsoft does NOT say to not use exceptions (common misinterpretation).
It says if you're designing an API provide ways to help a user of that API to avoid THROWING exceptions if they need too (Try and Tester-Doer patterns)
❌ DO NOT use exceptions for the normal flow of control, if possible.
Except for system failures and operations with potential race
conditions, framework designers should design APIs so users can write
code that does not throw exceptions. For example, you can provide a
way to check preconditions before calling a member so users can write
code that does not throw exceptions.
What is inferred here is that the non-tester-doer/non-try implementation SHOULD throw an exception upon failure and then the user CAN change that to one of your tester-doer or try methods for performance. Pit of success is maintained for safety and the user OPTS INTO the more dangerous but more performant method.
Microsoft DOES say to NOT use return codes TWICE, here:
❌ DO NOT return error codes.
Exceptions are the primary means of reporting errors in frameworks.
✔️ DO report execution failures by throwing exceptions.
and here:
❌ DO NOT use error codes because of concerns that exceptions might
affect performance negatively.
To improve performance, it is possible to use either the Tester-Doer
Pattern or the Try-Parse Pattern, described in the next two sections.
If you're not using exceptions you're probably breaking this other rule of returning return codes or booleans from a non-tester/non-try implementation.
Again, TryParse does not replace Parse. It is provided in addition to Parse
MAIN REASON: Return codes fail the "Pit of Success" test for me almost every time.
It is far too easy to forget to check a return code and then have a red-herring error later on.
var success = Save()? How much performance is worth someone forgetting an if check here?
var success = TrySave()? Better, but are we going to abuse everything with the TryX pattern? Did you still provide a Save method?
Return codes don't have any of the great debugging information on them like call stack, inner exceptions.
Return codes do not propagate which, along with the point above, tends to drive excessive and interwoven diagnostic logging instead of logging in one centralized place (application and thread level exception handlers).
Return codes tend to drive messy code in the form of nested 'if' blocks
Developer time spent debugging an unknown issue that would otherwise have been an obvious exception (pit of success) IS expensive.
If the team behind C# didn't intend for exceptions to govern control flow, execeptions wouldn't be typed, there would be no "when" filter on catch statements, and there would be no need for the parameter-less 'throw' statement.
Regarding Performance:
Exceptions may be computationally expensive RELATIVE to not throwing at all, but they're called EXCEPTIONS for a reason. Speed comparisons always manage to assume a 100% exception rate which should never be the case. Even if an exception is 100x slower, how much does that really matter if it only happens 1% of the time?
Context is everything. For example, A Tester-Doer or Try option to avoid a unique key violation is likely to waste more time and resources on average (checking for existance when a collision is rare) than just assuming a successful entry and catching that rare violation.
Unless we're talking floating point arithmetic for graphics applications or something similar, CPU cycles are cheap compared to developer time.
Cost from a time perspective carries the same argument. Relative to database queries or web service calls or file loads, normal application time will dwarf exception time. Exceptions were nearly sub-MICROsecond in 2006
I dare anybody that works in .net, to set your debugger to break on all exceptions and disable just my code and see how many exceptions are already happening that you don't even know about.
Jon Skeet says "[Exceptions are] not slow enough to make it worth avoiding them in normal use". The linked response also contains two articles from Jon on the subject. His generalized theme is that exceptions are fine and if you're experiencing them as a performance problem, there's likely a larger design issue.
In Java, I use (in the following order):
Design-by-contract (ensuring preconditions are met before trying anything that might fail). This catches most things and I return an error code for this.
Returning error codes whilst processing work (and performing rollback if needed).
Exceptions, but these are used only for unexpected things.
I dislike return codes because they cause the following pattern to mushroom throughout your code
CRetType obReturn = CODE_SUCCESS;
obReturn = CallMyFunctionWhichReturnsCodes();
if (obReturn == CODE_BLOW_UP)
{
// bail out
goto FunctionExit;
}
Soon a method call consisting of 4 function calls bloats up with 12 lines of error handling.. Some of which will never happen. If and switch cases abound.
Exceptions are cleaner if you use them well... to signal exceptional events .. after which the execution path cannot continue. They are often more descriptive and informational than error codes.
If you have multiple states after a method call that should be handled differently (and are not exceptional cases), use error codes or out params. Although Personaly I've found this to be rare..
I've hunted a bit about the 'performance penalty' counterargument.. more in the C++ / COM world but in the newer languages, I think the difference isn't that much. In any case, when something blows up, performance concerns are relegated to the backburner :)
I wrote a blog post about this a while ago.
The performance overhead of throwing an exception should not play any role in your decision. If you're doing it right, after all, an exception is exceptional.
A great piece of advice I got from The Pragmatic Programmer was something along the lines of "your program should be able to perform all its main functionality without using exceptions at all".
I have a simple set of rules:
1) Use return codes for things you expect your immediate caller to react to.
2) Use exceptions for errors that are broader in scope, and may reasonable be expected to be handled by something many levels above the caller so that awareness of the error does not have to percolate up through many layers, making code more complex.
In Java I only ever used unchecked exceptions, checked exceptions end up just being another form of return code and in my experience the duality of what might be "returned" by a method call was generally more of a hinderance than a help.
I use Exceptions in python in both Exceptional, and non-Exceptional circumstances.
It is often nice to be able to use an Exception to indicate the "request could not be performed", as opposed to returning an Error value. It means that you /always/ know that the return value is the right type, instead of arbitarily None or NotFoundSingleton or something. Here is a good example of where I prefer to use an exception handler instead of a conditional on the return value.
try:
dataobj = datastore.fetch(obj_id)
except LookupError:
# could not find object, create it.
dataobj = datastore.create(....)
The side effect is that when a datastore.fetch(obj_id) is run, you never have to check if its return value is None, you get that error immediately for free. This is counter to the argument, "your program should be able to perform all its main functionality without using exceptions at all".
Here is another example of where exceptions are 'exceptionally' useful, in order to write code for dealing with the filesystem that isn't subject to race conditions.
# wrong way:
if os.path.exists(directory_to_remove):
# race condition is here.
os.path.rmdir(directory_to_remove)
# right way:
try:
os.path.rmdir(directory_to_remove)
except OSError:
# directory didn't exist, good.
pass
One system call instead of two, no race condition. This is a poor example because obviously this will fail with an OSError in more circumstances than the directory doesn't exist, but it's a 'good enough' solution for many tightly controlled situations.
I believe the return codes adds to code noise. For example, I always hated the look of COM/ATL code due to return codes. There had to be an HRESULT check for every line of code. I consider the error return code is one of the bad decisions made by architects of COM. It makes it difficult to do logical grouping of the code, thus code review becomes difficult.
I am not sure about the performance comparison when there is an explicit check for the return code every line.
Exceptions are not for error handling, IMO. Exceptions are just that; exceptional events that you did not expect. Use with caution I say.
Error codes can be OK, but returning 404 or 200 from a method is bad, IMO. Use enums (.Net) instead, that makes the code more readable and easier to use for other developers. Also you don't have to maintain a table over numbers and descriptions.
Also; the try-catch-finally pattern is an anti-pattern in my book. Try-finally can be good, try-catch can also be good but try-catch-finally is never good. try-finally can often times be replaced by a "using" statement (IDispose pattern), which is better IMO. And Try-catch where you actually catch an exception you're able to handle is good, or if you do this:
try{
db.UpdateAll(somevalue);
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
So as long as you let the exception continue to bubble it's OK. Another example is this:
try{
dbHasBeenUpdated = db.UpdateAll(somevalue); // true/false
}
catch (ConnectionException ex) {
logger.Exception(ex, "Connection failed");
dbHasBeenUpdated = false;
}
Here I actually handle the exception; what I do outside of the try-catch when the update method fails is another story, but I think my point has been made. :)
Why is then try-catch-finally an anti-pattern? Here's why:
try{
db.UpdateAll(somevalue);
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
finally {
db.Close();
}
What happens if the db object has already been closed? A new exception is thrown and it has to be handled! This is better:
try{
using(IDatabase db = DatabaseFactory.CreateDatabase()) {
db.UpdateAll(somevalue);
}
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
Or, if the db object does not implement IDisposable do this:
try{
try {
IDatabase db = DatabaseFactory.CreateDatabase();
db.UpdateAll(somevalue);
}
finally{
db.Close();
}
}
catch (DatabaseAlreadyClosedException dbClosedEx) {
logger.Exception(dbClosedEx, "Database connection was closed already.");
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
That's my 2 cents anyway! :)
I generally prefer return codes because they let the caller decide whether the failure is exceptional.
This approach is typical in the Elixir language.
# I care whether this succeeds. If it doesn't return :ok, raise an exception.
:ok = File.write(path, content)
# I don't care whether this succeeds. Don't check the return value.
File.write(path, content)
# This had better not succeed - the path should be read-only to me.
# If I get anything other than this error, raise an exception.
{:error, :erofs} = File.write(path, content)
# I want this to succeed but I can handle its failure
case File.write(path, content) do
:ok => handle_success()
error => handle_error(error)
end
People mentioned that return codes can cause you to have a lot of nested if statements, but that can be handled with better syntax. In Elixir, the with statement lets us easily separate a series of happy-path return value from any failures.
with {:ok, content} <- get_content(),
:ok <- File.write(path, content) do
IO.puts "everything worked, happy path code goes here"
else
# Here we can use a single catch-all failure clause
# or match every kind of failure individually
# or match subsets of them however we like
_some_error => IO.puts "one of those steps failed"
_other_error => IO.puts "one of those steps failed"
end
Elixir still has functions that raise exceptions. Going back to my first example, I could do either of these to raise an exception if the file can't be written.
# Raises a generic MatchError because the return value isn't :ok
:ok = File.write(path, content)
# Raises a File.Error with a descriptive error message - eg, saying
# that the file is read-only
File.write!(path, content)
If I, as the caller, know that I want to raise an error if the write fails, I can choose to call File.write! instead of File.write.
Or I can choose to call File.write and handle each of the possible reasons for failure differently.
Of course it's always possible to rescue an exception if we want to. But compared to handling an informative return value, it seems awkward to me. If I know that a function call can fail or even should fail, its failure isn't an exceptional case.
With any decent compiler or runtime environment exceptions do not incur a significant penalty. It's more or less like a GOTO statement that jumps to the exception handler. Also, having exceptions caught by a runtime environment (like the JVM) helps isolating and fixing a bug a lot easier. I'll take a NullPointerException in Java over a segfault in C any day.
I prefer to use exceptions for error handling and return values (or parameters) as the normal result of a function. This gives an easy and consistent error-handling scheme and if done correctly it makes for much cleaner looking code.
One of the big differences is that exceptions force you to handle an error, whereas error return codes can go unchecked.
Error return codes, if used heavily, can also cause very ugly code with lots of if tests similar to this form:
if(function(call) != ERROR_CODE) {
do_right_thing();
}
else {
handle_error();
}
Personally I prefer to use exceptions for errors that SHOULD or MUST be acted upon by the calling code, and only use error codes for "expected failings" where returning something is actually valid and possible.
There is many reason to prefer Exceptions over return code:
Usually, for readibility, people try to minimize the number of return statement in a method. Doing so, exceptions prevent to do some extra work while in a incoorect state, and thus prevent to potentially damage more data.
Exception are generally more verbose arn more easilly extensible than return value. Assume that a method return natural number and that you use negative numbers as return code when an error occurs, if the scope of you method change and now return integers, you'll have to modify all the method calls instead of just tweaking a little bit the exception.
Exceptions allows more easilly to separate error handling of normal behaviour. They allows to ensure that some operations performs somehow as an atomic operation.
I only use exceptions, no return codes. I'm talking about Java here.
The general rule I follow is if I have a method called doFoo() then it follows that if it doesn't "do foo", as it were, then something exceptional has happened and an Exception should be thrown.
One thing I fear about exceptions is that throwing an exception will screw up code flow. For example if you do
void foo()
{
MyPointer* p = NULL;
try{
p = new PointedStuff();
//I'm a module user and I'm doing stuff that might throw or not
}
catch(...)
{
//should I delete the pointer?
}
}
Or even worse what if I deleted something I shouldn't have, but got thrown to catch before I did the rest of the cleanup. Throwing put a lot of weight on the poor user IMHO.
My general rule in the exception vs. return code argument:
Use errorcodes when you need localization/internationalization -- in .NET, you could use these errorcodes to reference a resource file which will then display the error in the appropriate language. Otherwise, use exceptions
Use exceptions only for errors that are really exceptional. If it's something that happens fairly often, either use a boolean or an enum errorcode.
I don't find return codes to be less ugly than exceptions. With the exception, you have the try{} catch() {} finally {} where as with return codes you have if(){}. I used to fear exceptions for the reasons given in the post; you don't know if the pointer needs to be cleared, what have you. But I think you have the same problems when it comes to the return codes. You don't know the state of the parameters unless you know some details about the function/method in question.
Regardless, you have to handle the error if possible. You can just as easily let an exception propagate to the top level as ignore a return code and let the program segfault.
I do like the idea of returning a value (enumeration?) for results and an exception for an exceptional case.
For a language like Java, I would go with Exception because the compiler gives compile time error if exceptions are not handled.This forces the calling function to handle/throw the exceptions.
For Python, I am more conflicted. There is no compiler so it's possible that caller does not handle the exception thrown by the function leading to runtime exceptions. If you use return codes you might have unexpected behavior if not handled properly and if you use exceptions you might get runtime exceptions.
There are some important aspects that remain unmentioned in this - very interesting - discussion so far.
First, it is important to note that exceptions don't apply to distributed computing, but error codes still do. Imagine communicating services distributed over multiple servers. Some communication might even be asynchronous. And the services might even use different technology stacks. Cleary, an error-handling concept is crucial here. And clearly, exceptions can't be used in this most general case, since errors have to be serialized things sent "through the cable", perhaps even in a language-neutral way. From that angle, error codes (really, error messages) are more universal than exceptions. One needs good error-message Kung Fu once one assumes a system-architect view and things need to scale.
The second point is a very different, it is about if or how a language represents discriminated unions. The question was strictly speaking about "error codes". And so were some the answers, mentioning that error codes cannot transport information as nicely as exceptions. This is true if an error code is a number. But for a fairer contrasting with exceptions, one should probably consider error values of discriminated union type. So, the return value of the callee would be of discriminated union type, and it would either be the desired happy-path value or the payload the exception would otherwise have. How often this approach is elegant enough to be preferable depends on the programming language. For example, F# has super elegant discriminated unions and the according pattern matching. In such a language it would be more seductive to avoid exceptions than in, say, C++.
The third and final point is about functional programming and pure functions. Exceptions are (in a practical way and in a theoretical-computer-science way) "side effects". In other words, functions or methods that deal with exceptions are not pure. (One practical consequence is that with exceptions one must pay attention to evaluation order.) By contrast, error values are pure, because the are just ordinary return values, with no side effects involved. Therefore, functional programmers may more likely frown upon exceptions than object-oriented programmers. (In particular if the language also has an elegant representation of the aforementioned discriminated unions.)
I prefer exceptions over return codes.
Consider a scenario when I call a function foo and forget to handle potential errors (exceptions).
If errors in foo are passed via return codes (error codes),
at compile time, I won't be alerted
if I run the code
if the error doesn't happen, I don't notice my mistake
if the error happens but doesn't affect the code after calling foo, I don't notice my mistake
if the error happens and affects the code after calling foo, I notice my mistake, but it may be hard to locate the problem
If errors in foo are passed via exceptions that are thrown,
at compile time, I won't be alerted
if I run the code
if the error doesn't happen, I don't notice my mistake
if the error happens, I'm assured to notice my mistake
From the comparison above, my conclusion is that exceptions are better than error codes.
However, exceptions are not perfect. There are at least two critical problems:
As discussed above, if I forget to handle a potential exception, I won't be alerted until I run the code and the exception is actually thrown.
It's hard to determine all the exceptions foo may throw, especially when foo calls other functions (which may also throw exceptions).
A feature in Java, “checked exceptions”, solves both problems.
In Java, when defining a function foo, I'm required to explicitly specify what exceptions it may throw using the throws keyword. Example:
private static void foo() throws FileNotFoundException {
File file = new File("not_existing_file.txt");
FileInputStream stream = new FileInputStream(file);
}
If I call foo and forget to handle the potential FileNotFoundException, the compiler produces an error. I get alerted at compile time (problem 1 solved). And all possible exceptions are listed explicitly (problem 2 solved).
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?
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.
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.
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.
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").
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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;
}
}
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 .
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
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.
I have three type of conditions that I catch.
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.
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.
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
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."
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.
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.
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.
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.
Some useful things to think about when deciding whether an exception is appropriate:
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.)
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.
"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.
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.