Why do many languages treat Exception-objects as first-class citizens? - oop

When we get an objects that is actually are exceptions, we can do with them anything that we can do with ordinar objects in our language. We can pass them as an argument, we can store them in some collection and, what is the worst, we can return them as a result from the methods!
So there is a possibility for someone to write smelly code like this:
public Exception doSomethingCritical()
{
Exception error = null;
try
{
...
}
catch (Exception e)
{
// maybe at least here is the logging of the error if we are lucky
error = e;
}
return error;
}
So the question is why is the concept of an Exception-object is a first-class citizen in many OO languages? Maybe it is better if we have only limited constructions in the language that is allowed for exception-objects (like throw).

The problem with treating exceptions as a special case, and allowing only limited functionality with exceptions is that ultimately somewhere every good program needs to do something with exceptions, whether it be a global error-handler or a limited item that appropriately deals with the exception. By making exceptions first class citizens, there are many benefits, such as:
Allowing subclassing of exceptions. This is invaluable for exception handling as code dealing with exceptions can narrow their scope and deal only with exceptions they know how to deal with. I'd go so far as to say that any non-global exception handling routine that is catching just "Exception" is probably doing it wrong.
Passing data along with exceptions. Exceptions aren't very useful if the only thing you know in your catch logic is that an exception occurred. Stack traces, messages and even custom data for certain exception types are invaluable in identifying and resolving the problem that caused the exception.
Creating error handling routines that use OOP themselves. If exceptions couldn't be passed as objects, you couldn't for instance have a library that deals with exceptions - well, at least not a well written one.
Besides all of that, there's no way to guard against bad exception handling like you posted above. Even if an exception wasn't a first class citizen, there's no way to stop a developer from eating any and all exceptions and carrying on their merry way (at least, without fundamentally breaking how we think of exceptions)

My opinion.
I think you are confusing two different things: the Exception and the Exception throwing.
The exception throwing is an out-of-band process that allows you to throw an object through a preferential, lateral channel. This object can be intercepted and handled through the Exception catching mechanism.
The Exception is just one object that you can (preferentially) throw via the Exception throwing out-of-band channel. Of course, this channel can have requisites for the interface of the object being thrown, requisites that are satisfied by the Exception class interface.
You are looking at the issue the other way around. Indeed you can do horrors, but there's nothing special about the Exception object, apart of being the preferred object that is thrown in the out-of-band channel.

I've never actually seen that example you've used. And I can't see how not allowing people to return exceptions will make a big difference to conceptually poor code - compare
public int doSomethingCritical()
{
int error = 0;
try
{
...
}
catch (Exception e)
{
// maybe at least here is the logging of the error if we are lucky
error = E_SOMETHINGBAD;
}
return error;
}
Whereas if you create a new kind of "thing" to be used for exceptions that isn't the same as an object, there is a design and learning overhead disadvantage.

How would you be able to inherit from the base exception class and derive your own exception class for your module if they were not first type citizens?

I don't see why I shouldn't be allowed to pass and return exceptions as normal method parameters. What if I were writing an Exception Handling library? What if I were writing a unit test assertion that compared exceptions?

Because life is a lot easier that way. Among other things, it means that the exception object can contain information that the program can use to correct the exceptional situation (perhaps with human intervention).
Abend is so 1960s.

I'm not sure the example you give is a strong enough case for not having exceptions as objects. After all you COULD do all kinds of "smelly" or "bad" things while programming. However thats precisely the reason we want good programmers. Just because I can do dsomething like :
def get_total
return nil
end
surely doesnt mean I should not allow nil as an instance of an object!

Related

Can a language have exceptions without a type hierarchy?

In my experience, every language which supports exceptions has a hierarchy of exception types. This allows a single catch clause to match a group of related exceptions by catching their common parent. For example, part of Python's hierarchy:
FloatingPointError < ArithmeticError < Exception < BaseException
Go, on the other hand, famously does not support exceptions and also has "no type hierarchy". Some people think exceptions should be added to Go - would it be possible to do this without adding a type hierarchy?
Are there other languages which have exceptions but no type hierarchy? Do they group related exceptions in some other way?
SuperTalk has effectively no data types, but has exceptions. Basically you throw an error code and check that. That's also how many early macOS application frameworks worked, even in C++.
So just as an object can be approximated by using a simple data structure with a type selector, exceptions can be made to work.
on doFoo
throw "myError"
end doFoo
on startUp
try
doFoo
catch tError
if tError = "myError" then
-- do something about it
else
throw tError
end if
end try
end startUp
Instead of "myError", you can throw any string or number, so you could use a formatted string, like "copyFileError,/path/to/source/file.txt,/path/to/dest/file.t‌​xt" (of course with proper escaping of dangerous characters like "," in this case) and then just compare the first item in this list to tell whether it's the error you want to handle.
If you're just going with error numbers without any additional payload, you can segment the number space to get error "classes" e.g. "fatal errors are negative, recoverable ones positive" or "1-100 are file system errors" or whatever (see HTTP status code for an example of using error code ranges to define error classes).
I'd rather post this as a comment, but the sentiment was too long to get across within the limitations of a comment. I am aware that this is primarily opinion based, and I apologize for that.
Go does not support exceptions because it does not need to. Exceptions are a crutch that developers have been lured into becoming dependent on because they don't want to handle errors properly. In Go, it is idiomatic to handle every error, on the spot, every time. If you do this, your programs run better, and you are aware of exactly when/where errors happen and you can fix them. Using catch in other languages ends up being more difficult to debug as you are not always aware of exactly where the error originally happened. By wrapping your code in try catch blocks, you essentially mask the bugs in your code. try and catch are also terribly inefficient because all of the optimizations in the binary grind to a halt as the program has to figure out what unexpectedly happened. Using errors properly in Go circumvents this because you capture errors and handle them, thereby "expecting" them as an eventuality and handling them properly.

Is overloading a method without throwing an exception an antipattern?

We are currently designing an API for storing settings and we are considering having these two types of methods:
public Object getSetting(String key) {
// return null if key does not exist
}
public Object getSettingExc(String key) {
// throw a runtime exception if key does not exist
}
Somehow I feel that this just isn't right, but I can't think of any disadvantages except for doubling the number of functions in the API and perhaps decreased code readability (if I know the setting MUST exist, I think I should throw an exception explicitly rather than relying on the get method).
What are your opinions on this?
Exceptions are for exceptional occurrences, when the code cannot continue to function according to its advertised function.
Requesting a setting that isn't set is hardly exception-worthy. If "you" (i.e. the calling code) "know" that setting "must" exist, call getSetting(), check the return value for null, and then throw an exception yourself out of the knowledge that it should have been there. Add a meaningful message about what setting in which context wasn't found. (This is something only the caller knows.)
Don't delegate the throwing of the exception to code that doesn't know the context of the query or that the setting should be there, and needs to be told explicitly (by getting called under a different name). Also, getSettingExc() will most likely be only a null-check-and-throw wrapper around getSetting() anyway, so why not do it at a point where you can make the exception message so much more helpful?
IMHO. (And this is the point where I realize I should have voted-to-close instead of writing an answer...)
This is introducing a weird kind of coupling between the object structure and the potential error conditions. Regarding your comment:
I'm just trying to gather arguments to persuade other guys in my team.
The onus should be on the proponent of this design to justify it, not on you to justify against it. Nobody else uses this in any design I've ever seen.
This does however remind me of another design that maybe is what your team intended? Consider these two methods:
public Object getSetting(String key) {
// return the setting or throw an exception
}
public Object getSettingOrDefault(String key) {
// return the setting or a pre-determined default
}
This aligns the methods more with the functionality than with the error conditions. getSetting() can advertise that it might throw an exception, whereas getSettingOrDefault() can advertise that it will default to a specific value if none can be found in the settings.
If Java has optional parameters or something akin to that, getSettingOrDefault() might even accept as an argument a default to use in the event of no such setting. That might get a little kludgy for consuming code though, just sort of thinking out loud on that one.
Either way, the API should reflect the functionality and not the error conditions. Ideally there should be only one method, but if there's a noticeable need to differentiate between a method that throws and a method that doesn't (and I could certainly see that being the case in a language with checked exceptions), those two should align with the functionality rather than with the exception.
IMHO having two methods to do precisely the same operation indicates that you as the API designer did not complete the job of 'designing' your API. Choose one way or another, publicize it via the API (javadocs) and then the consumers will be consistent in their usage (one way or the other).

Validation in setters: What approach is better?

I have dispute with my friend.
He said me that this code:
method SetBalance(balance) {
if (balance > 0) {
this.balance = balance;
return true;
}
return false;
}
is better then this:
method SetBalance(balance) {
if (balance < 0) {
throw new InvalidArgumentException("Balance couldn't be negative")
}
this.balance = balance;
}
My question is: "Which approach is better for validation?" and why?
Thank you.
Ah. Return status versus exception.
I prefer throwing exceptions, because you can't really ignore an exception. The program either crashes, or you have to explicitly catch and handle it.
You can just ignore a return status.
Besides, isn't this the reason exceptions exist in modern programming? To deal with, well... exceptions (balance <= 0, something that shouldn't happen).
In case of setters, developers will never expect the return value from those methods since they feel that this will anyway will take care of setting the value.
In case, if there is an exception, then this will help then to understand that something is really wrong and look after the code again.
Instead of runtime exception, you better define your own exception like InvalidBalanceException and specify that this method will throw this exception in the signature itself. This avoids surprises at testing phase and decide the business logic in development phase itself.
Return value is easily ignored. Here you have clear coding bug, so crash loud. I would even halt/segfault/stop program - the exception may still be caught. We live in "ideal world", but imagine our less fortunate colleagues - they might well go for gagging error signalling facility being unable to deal with the root cause (insert here more complicated error scenario). Coding gets much easier when you dont give clients ways to do things wrong way.
Besides the answers given already, returning a boolean value in a function named "setFoo" is very misleading. If you translate a boolean value you come up with yes/no. So a function that returns booleans in oop should be readable as a question that gives yes/no as an answer, e.g. isBalanceSet.
In discussion with collegues we considered the only valid return-value for a normal setter is the class itself for fluent-interfaces.
Regarding your question throwing exceptions is the better solution if the class actually validates its properties itself ;)
My personal opinion: both approaches has its uses. It depends on why the situation arose, could it be prevented, what the client could have done to prevent it.
Server:
method SetBalance(int balance)
{
// do something only if balance >= 0
}
Client:
myServer.SetBalance(balance);
Case 1:
The situation arises only because of a bug somewhere (in server or client). Throw exception. Let the responsible party fix its code.
Case 2:
A bad input is received from some external dependency. The client could easily check the precondition. Throw exception, let the client fix its code if she is unhappy with that.
if(balance>0)
myServer.SetBalance(balance);
else
//take appropriate action.
Case 3:
A bad input is received from some external dependency. The client could not easily check the precondition. Example: it would require the client to parse a string, which is the server's job. Here, it makes sense that the server should return success:
bool succeeded = myServer.SetBalance(balance);
if(!succeeded)
//take appropriate action.
After writing my answer down, I noticed it all boils down to this: The client should not have to use try-catch to call the method SetBalance. (Either it's a bug so don't catch the exception, or check the precondition yourself, or inspect the return value)
Here is a good reading on a related subject: http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx
Edit:
Jojo makes a good point. Rename the method TrySetBalance() if there is a probability that it might fail.
Exceptions handling is the method of choice to handle errors in OOP, whether it is runtime error or logic error. One of the arguments to justify exception handling is that, if error code is used a client of a function may forget to check the error code leading to a potential bug which may not be easily found. Whereas, if exception handling is used, even if it is not caught, it will propagate until it is handled. So, OOP purists always advice using exception handling.

How are try/catch blocks implemented?

If an exception occurs in a try block, how is execution transferred to the catch block? This is not a C#/Java/C++ question, I'm just wondering how it works internally.
this is not a c#/java/c++ question. How it works internally,how the line knows to go catch statement.
How this works internally makes this pretty much a c#/java/C++ question (because it will be implemented differently).
In Java, a try block installs itself into a special table (in the class file). When the JVM throws an exception, it looks at that table to see where the next catch or finally block to go to is.
When an exception occurs a special instruction is executed (usually called interrupt). This leads to executing a generic error handler that deduces which is the latest installed suitable exception handler. That handler is then executed.
There is a difference how exceptions are technically handled between natively compiled languages such as C++ and languages using byte-code being executed on a virtual machine such as Java or C#.
C++ compilers usually generate code that protocols the information needed for exception handling at runtime. A dedicated data structure is used to remember entrance/exit of try blocks and the associated exception handler. When an exception occurs, an interrupt is generated and control is passed to the OS which in turn inspects the call stack and determines which exception handler to call.
Further details are pretty well explained in the following article by Vishal Kochhar:
How a C++ compiler implements exception handling
In Java or .NET there is no need for the overhead of maintaining exception handling information as the runtime will be able to introspect the byte code to find the relevant exception handler. As a consequence, only exceptions that are actually thrown are causing an overhead.
It is basically parsing fundamentals of the language.
You can get all info at Here
it should work in all langues somewhat like this:
if (error_occured xy while doing things in try){
call_catch_part(error xy)
}
you could do the same in C even though there is no exception handling per se.
There you would use setjmp/longjmp unfortunately you then do not get the stack unwinding and have to handle all the nitty-gritty yourself.

Which Error Handling Model Is More Robust?

I'm kind of torn between these two error-handling models:
Create a boolean Error and a string ErrorMessage property for your object. Catch all exceptions internally in the object's methods and pass the messages along using conditional logic from the caller, ie:
Dim o As New MyObject
o.SomeMethod()
If Not o.Error Then
'Do stuff'
Else
Dim msg As String = o.ErrorMessage
'do something with message'
End If
Throw exceptions in your object and handle them on the outside with Try Catch logic:
Dim o As New MyObject
Try
o.SomeMethod()
'Do stuff'
Catch ex As Exception
Dim msg As String = ex.ErrorMessage
'do something with message'
End Try
To me, it seems like the same amount of code either way, except that you have property code for the Error and ErrorMessage properties. However, you also can tell when an error occurs without having to check for exceptions. Which pattern should I go with?
I have decided to go with throwing exceptions instead of using error/return codes. I just recently looked really hard into this.
The #1 reason to throw exceptions is there is a possibility you can forget to check the error code. If you don't check it, then you will continue working while the error exists. With exceptions though, if you forget to handle them, then the exception will raise to the top and stop all processing. It is better for this to happen than to continue after unknown errors have occurred.
For more info check out the Exception chapter in Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, Second Edition by Addison-Wesley.
Joel Spolsky actually prefers error/return codes over exceptions but a lot of people disagree with him. Joel's post in favor of return codes can be found here. Check out this blog post and all of the comments with some good discussion regarding this subject.
Prefer #2. For details, see this excerpt on Exception Throwing from the development of Microsoft's excellent Framework Design Guidelines, as Dennis mentioned. Note especially the section on Exceptions and Performance.
Short version:
Do not return error codes.
Do report execution failures by throwing exceptions.
Do not use exceptions for normal flow of control.
I highly recommend reading the book for a full discussion, complete with commentary from a number of the Microsoft luminaries.
Exceptions should be used when something exceptional has happened.
e.g. you are passed a null (nothing) object when you expect one.
Uncle Bob recommends Exceptions over Error codes in his book Clean code.
He says
The problem with these [error codes] approaches is that they clutter the caller. The caller must check for errors immediately after the call. Unfortunately it's easy to forget. For this reason it is better to throw an exception when you encounter an error. The calling code is cleaner. Its logic is not obscured by error handling.
The biggest issue I have with the first one is that it's passive, easily overlooked and not very standardized. How will a programmer know to check that property? Or which properties / methods can possible set an error? Or which property / method access caused the error to be set?
For example. In your first sample code if o.Error is True, it's unclear whether the initialization of the object or the call to SomeMethod caused the flag to be set.
The exception model is an unignorable way of telling your users that an error occurred. It cannot be avoided without explicit code to handle the situation.
They are both accepted forms of error handling, however the preferred choice for .NET languages is to use exceptions.
There are a few problems with using return codes (either numeric or boolean), the two biggest being:
Easily overlooked/ignored by programmers.
Can't be used in all situations. What happens if your constructor fails? It's not possible for you to return a value explicitly from a constructor.
For these reasons alone, you should use exceptions. Exceptions provide a clean, standardized way to indicate and any failure no matter where it arises.
You will also end up with less code overall as you should only catch exceptions when and where you can safely and appropriately handle that exception.
I recommend using both.
Why?
"Use the right tool for the job"
The "problem" with return codes is that people often forget to handle them. However, exceptions don't solve this problem! People still don't handle exceptions (they don't realise a certain exception needs to be handled, they assume somebody up the stack will handle it, or they use a catch() and squash all errors).
While an unhandled return code might mean the code is in an unstable state, an unhandled exception often guarantees that the program will crash. Is this better?
While a return code is easily identifiable when writing code, it is often impossible (or just tediously time-consuming) to determine what exceptions might be thrown by a method you are calling. This typically results in a lot of very poor exception handling.
Exceptions are supposed to be used for "errors". Therein lies the difficulty. If a file is not found when you try to open it, is that an "error", or an "expected situation"? Only the caller knows. Using exceptions everywhere essentially elevates every piece of status information into an error.
Ultimately, error handling is something a programmer has to work at. This problem exists in both return codes and exceptions.
Thus, I use return codes for passing status information (including "warnings"), and exceptions for "serious errors". (and yes, sometimes it's hard to judge which category something falls under)
Example case from .net:
Int32.Parse throws exceptions (even though none of its exceptions are errors - it is up to the caller to verify the results and decide for themselves if the result is valid). And it's simply a pain (and a performance hit) to have to enclose every call to it in a try/catch. And if you forget to use a try/catch, a simple blank text entry field can crash your program.
Thus, Int32.TryParse() was born. This does the same thing, but returns an error code instead of an exception, so that you can simply ignore errors (accepting a default value of 0 for any illegal inputs). In many real life situations this is much cleaner, faster, easier and safer to use than Int32.Parse().
"TryParse" uses a naming convention to make it clear to the caller that errors might occur, that should be correctly handled. Another approach (to force programmers to handle errors better) is to make the return code into an out or ref parameter, so that the caller is explicitly made aware of the need to handle returned errors.