What is 'exceptional'? [closed] - oop

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 12 years ago.
I'm looking for a definition of 'exceptional' in terms of unit testing or OOP principles. Several times on SO when talking about exception throwing, I've seen comments like, "Well, I wouldn't consider getting Foo from Bar to be exceptional." (Is there a trollface emoticon?)
I did some googling and an answer wasn't immediately forthcoming. Are there any good definitions, rules of thumb, or guidelines that are more objective than opinion or preference? If one person says "this is exceptional" and another says "no, it isn't", how does one resolve this dispute?
Edit: Wow, so there are a number of answers already, with comments that disagree, and they all seem to be the opinion of the answerers :P Nobody's referenced a wikipedia page or an article a snippet from a greybeard. The 'meta-answer' I'm taking from this is there is no agreed-upon rule of thumb for when to use exceptions. I feel more confident employing my own, personal, idiosyncratic rules when choosing to throw exceptions.

I disagree with the other answers about something needing to be "exceptional" to warrant an "exception". I say "exceptional" is any time you want to break the normal flow of control in the way you can by throwing an upward-propagating object.
Exceptions are a language feature. They're a means to an end. They aren't magical. Like any other feature, when you use them should be guided by when you need what they can provide, not by what they are called.

It's exceptional if:
It is a failure condition. AND
It happens infrequently and
unexpectedly. AND
There is no better mechanism for
reporting it.
edit
Stealing blatantly from Dan Weinreb's blog entry, which Ken posted about here, I'd like to offer the following summary of what exceptions are about.
The method's contract defines how
(and whether) unusual conditions
(ie. failures) are signaled. If the
method says something is an
exception, it just is. Of course,
this leaves open the question of how
we should design the contract.
Exceptions have the benefit of not
requiring any checking by the
caller, as well as naturally
bubbling up until they are caught by
something able to handle them. They
can also contain significant detail,
user-readable text and stack traces.
These features make them ideal for
failure cases that prevent further
processing but are not predictable
or common, or where explicit
error-handling would be disruptive
to code flow. They are especially
good for errors that "should never
happen" but are catastrophic in
effect (such as a stack overflow).
Flags, error codes, magic values
(NULL, nil, INVALID_HANDLE, etc.)
and other return-based mechanisms do
not commandeer flow, and are
therefore better suited for cases
that are common and best handled
locally, especially those where the
failure can be worked around. As
they operate by convention and not
fiat, you cannot count on them to be
detected and handled, except that an
invalid value may be designed to
cause an exception if actually used
(such as an INVALID_HANDLE being
used to read).
When using exceptions in robust
code, each method should catch
unexpected exceptions and wrap them
inside an exception from the
contract. In other words, if your
method does not promise to throw
NullReferenceException, you need to
catch it and rethrow it inside
something more general or specific.
They're called exceptions, not
surprises!

The general rule of thumb is:
Use exceptions for errors that you anticipate, and that could happen.
Use assertions to deal with errors that could never happen.

IMHO, an exception should be thrown, if the further execution of program would result in fatal error or unpredictable behaviour.

Personally, I think that this kind of discussion is a pure waste of time and that "what is exceptional" is the wrong question to ask.
Exceptions are just another flow control mechanism with certain advantages (flow of control can pass multiple levels up the call stack) and disadvantages (somewhat verbose, behaviour is less localized).
Whether it's the right choice should not be determined by its name. Would we have these discussions if exceptions were simply called "bubbleups" instead?

When someone rips out the power chord, that is exceptional, most of the other situations are expected.

Well, Exceptional programming case is one which deviates the program flow from normal stream and it might be due to:
::A h/w of s/w fault that programmer cannot handle in given situation. Programmer may be not sure what to do in those case and he left it to the user or tool/library which invokes this code.
::Even programmer might not be sure the exact environment in which his code will be used and hence it is better to leave the error handling to the one who uses the code.
So exceptional case with a program might be is to use it uncommon environment or with uncommon interactions.
Again uncommon interactions and unknown environments refers to the designers point of view.
So deviation from Normal is exceptional and again it is based on the point of view and context of the programmer.
Is it too round and round?:D

Exceptions are useful when something has gone wrong that's outside the immediate scope of the problem. They should almost never be caught close to where thrown, since if they can be satisfactorily handled there they can be satisfactorily handled without throwing anything.
One example is C++'s containers, which can throw bad_alloc if they can't get the memory they need. The people who wrote the container have no idea what should happen if the container can't get memory. Perhaps this is an expected thing, and the calling code has alternatives. Perhaps this is recoverable. Perhaps this is fatal, but how should it be logged?
Yes, it's possible to pass back error codes, but will they be used? I see lots of C memory allocations without tests for NULL, and printfs that just discard the return value. Moreover, lots of functions don't have a distinguishable error code, like negative for printf and NULL for memory allocation. Where any return value can be valid, it's necessary to find a way to return an error indication, and that leads to more complication than most programmers are willing to deal with. An exception cannot be ignored, and doesn't require lots of defensive code.

The best discussion of this that I've seen is in Dan Weinreb's blog: What Conditions (Exceptions) are Really About.
It's ostensibly about Common Lisp, whose condition system is like a more flexible form of exceptions, but there's almost no Lisp code and you don't need to be a Common Lisp programmer to follow the concepts.

And another good rule of thumb - never use exceptions to catch conditions that you can catch in code.
For example if you have a method divides 2 variables, don't use an exception to catch divide by zero errors, instead do the necessary checks beforehand.
Bad code example:
float x;
try {
x = a / b;
{
catch (System.DivideByZeoException) {
x = 0;
}
Good code example:
if (b == 0)
return 0;
Exceptions are generally expensive.

I'm not going to get into the holy war of whether exceptions ought to be used as flow control or not, but rather I'm going to focus on what an exceptional event is...
Oracle, in the context of Java, defines an exceptional event this way:
An exception is an event, which occurs
during the execution of a program,
that disrupts the normal flow of the
program's instructions.
Of course, this definition applies to exceptions in general, not just in Java.
The key here is "disrupts the normal flow". In other words, the program fails in such a way that it can't complete its instructions.
A program has a defined range of functionality. When all your program's functionality is accounted for (including handling of invalid input), anything that is left over is an exception and likely a bug.
I believe there are two kinds of exceptions:
Bugs, which are introduced into the program by the programmer.
Uncontrollable situations, like someone else said, pulling the power plug. Of course, the program wouldn't get to throw an exception in this case, but if it could, it would. Other exceptions might be some sort of failure within the OS or network that the program relies on.
For instance: A program ought to handle invalid input from users as part of its normal flow, because users will of course give you invalid input at some point. This isn't a disruption because the program's functionality should be able to parse input and see if it's valid.
However, if a programmer somehow allows null to be passed to a method that isn't supposed to accept null, then that's an exception. The method's behavior is undefined for values of null. While it's a gray area, the reason I don't necessarily consider this invalid input like the above example is because the method has a certain spec, and by coding something into the program that passes a value violating that spec, it's a bug.

Exception should be used for things you can't control within your program. Most of time, this means you are working with external files or an internet/database connection.
For user input, YOU should control it before you compute anything with it.
Of course there is a limit to what you can expect and you should stop before reaching the "armless person exception". We came up with this term when we were programming something with movement detector and one of our friend was over-protecting his code. So we told him: "Yeah so, did you control what happens if an armless person put his hand in front of the detector?". We got a good laugh with it :)

Two main cases:
When calling code has asked you to do something unreasonable.
When outside dependencies have left you with nothing reasonable to do.
In the first case consider a method int IntegerDivide(int dividend, int divisor). Now, we all know we should catch conditions like dividing by zero ourselves. However, if the calling code has asked this method to divide by zero, it's too late - it's not our code that is deciding to divide by zero, it's the calling code. The only reasonable thing to do here is to throw an exception.
In the second case, consider a component that reads a file and returns some sort of computed result, and what it should do when it fails to open the file. If we had access to the user interface, then we should catch this failure and present a useful and informative message to the user. However we don't, as we're writing a component for use by other code closer to the UI. Again, the only thing we can do is throw an exception (and hope that the calling code does the right thing when it comes to informing the user).

Related

Kotlin Arrow EffectScope.shift() implementation throws exception?

When looking at arrows documentation about functional error handling one of the reason listed to avoid throwing exceptions is performance cost (referencing The hidden performance costs of instantiating Throwables)
So it is suggested to model errors/failures as an Effect.
When building an Effect to interrupt a computation the shift() method should be used (and under the hood it is also what is used to "unwrap" the effects through the bind() method).
Looking at the shift() method implementation seems that its magic is done...throwing an exception, meaning that not only exceptions are created when we want to signal an error, but also to "unwrap" any missing Option, Left instance of an Either and all the other effect types exposed by the library.
What I'm not getting is if there's some optimization done to avoid the issues with "the hidden performance costs of instantiating Throwables", or in the end they are not a real problem?
What I'm not getting is if there's some optimisation done to avoid the issues with "the hidden performance costs of instantiating Throwables", or in the end they are not a real problem?
The argumentation that this is the biggest reason for using typed errors on the JVM is probably an overstatement, there are better reason for using typed errors. Exceptions are not typed, so they are not tracked by the compiler. This is what we want to avoid if you care about type-safety, or purity. This will be better reflected in the documentation or 2.x.x.
Avoiding the performance penalty can be a benefit in hot-loops, but in general application programming it can probably be neglected.
However to answer your question on how this is dealt with in Kotlin, and Arrow:
In Kotlin cancellation of Coroutines works through CancellationException, so it's required to use this mechanism to correctly work in the Kotlin language. You can find more details in the Arrow 2.x.x Raise design document.
It's possible to remove the performance penalty of exceptions. Which is also what Arrow is doing. (Except a small regression in a single version, this was be fixed in the next release).
An example of this can also be found in the official KotlinX Coroutines which applies the same technique for disabled stack traces for JobCancellationException.

When and how to use Result in Kotlin?

I love the idea of Result.
I love having encapsulated try/catch.
But I’m a little confused about how and when to use Result.
I currently use it like this:
My adapters and services return a Result. Failures and stacktraces are logged but do nothing else
runCatching{
.... // do something cool
}.onFailure {
logger.error("Something bad happened ", it)
}
My Resource classes fold and handle the Result
return service.method().fold(
onFailure = {
Response.serverError().entity("Oops").build()
},
onSuccess = {
Response.ok().entity(doSomethingWith(it)).build()
}
)
Is this really the correct way to use a Result? Or is there a more idiomatic way to code in Kotlin?
TL;DR: never in business code (prefer custom sealed classes), but you can consider Result if you build a framework that must relay all kinds of errors through a different way than the exception mechanism (e.g. kotlin coroutines).
First, there is actually a list of use cases for the motivation of the initial introduction of Result, if you find it interesting. Also in the same document:
The Result class is designed to capture generic failures of Kotlin functions for their latter processing and should be used in general-purpose API like futures, etc, that deal with invocation of Kotlin code blocks and must be able to represent both a successful and a failed result of execution. The Result class is not designed to represent domain-specific error conditions.
Also, here is a very nice article by the lead Kotlin designer about exceptions in Kotlin and more specifically when to use the type system instead of exceptions.
Most of what follows is my personal opinion. It's built from facts, but is still just an opinion, so take it with a grain of salt.
Do not use runCatching or catch Throwable in business code
Note that runCatching catches all sorts of Throwable, including JVM Errors like NoClassDefFoundError, ThreadDeath, OutOfMemoryError, or StackOverflowError. There is usually almost nothing you can do with such JVM errors (even reporting them might be impossible, for instance in case of OOME).
According to the Java documentation, the Error class "indicates serious problems that a reasonable application should not try to catch". There are some very special cases where you might want to try to recover from error, but that is quite exceptional (pun intended).
Catch-all mechanisms like this (even catch(Exception)) are usually not recommended unless you're implementing some kind of framework that needs to attempt to report errors in some way.
So, if we don't catch errors (and instead let them bubble up naturally), Result isn't part of the picture here.
Do not catch programming exceptions in business code
Apart from JVM errors, I believe exceptions due to programming errors shouldn't really be handled in a way that bloats the business code either. Using error(), check(), require() in the right places will make use of exceptions to detect bugs that cannot be caught by the compiler (IllegalStateException, IllegalArgumentException). It often doesn't make sense to catch these exceptions in business code, because they appear when the programmer made a mistake and the logic of the code is broken. You should instead fix the code's logic.
Sometimes it might still be useful to catch all exceptions (including these ones) around an area of code, and recover with a high level replacement for the whole failed operation (usually in framework code, but sometimes in business code too). This will probably be done with some try-catch(Exception), though, but Result will not be involved here because the point of such code would be to delimit with try-catch the high-level operation that can be replaced. Low-level code will not return Result because it doesn't know whether there are higher level operations that can be replaced with something in case of programming errors, or if it should just bubble up.
Modeling business errors
That leaves business errors for result-like types. By business errors, I mean things like missing entities, unknown values from external systems, bad user input, etc. However, I usually find better ways to model them than using kotlin.Result (it's not meant for this, as the design document stipulates). Modelling the absence of value is usually easy enough with a nullable type fun find(username: String): User?. Modelling a set of outcomes can be done with a custom sealed class that cover different cases, like a result type but with specific error subtypes (and more interesting business data about the error than just Throwable).
So in short, in the end, I never use kotlin.Result myself in business code (I could consider it for generic framework code that needs to report all errors).
My adapters and services return a Result. Failures and stacktraces are logged but do nothing else
A side note on that. As you can see, you're logging errors in the service itself, but it's unclear from the service consumer's perspective. The consumer receives a Result, so who's reponsible with dealing with the error here? If it's a recoverable error then it may or may not be appropriate to log it as an error, and maybe it's better as a warning or not at all. Maybe the consumer knows better the severity of the problem than the service. Also, the service makes no difference between JVM errors, programming errors (IAE, ISE, etc.), and business errors in the way it logs them.

is there a proper way to handle multiple errors/exceptions?

in OO programming, is there some conceptual pattern, ideas, about handling multiple errors?
for example, i have a method that performs some checks and should return an error message for each error found
['name is too short', 'name contains invalid unicode sequences', 'name is too long']
now, should i use an array of exceptions (not thrown exceptions)?
or something like this is better:
class MyExceptionList extends Exception{
public Void addException(Exception e){}
public Array getExceptions(){}
}
any theory behind this argument will be appreciated!
(this isn't a request about a specific programming language, but a pure theoretical one)
thank you in advance
Unfortunately, many languages and frameworks (including C++, Java, and .net) use an exception-handling mechanism which requires the type of an an exception object to simultaneously answer many questions, including:
What happened
What actions need to be taken beyond stack unwinding
At what point should the system be considered to be in a "known" state, at least with regard to the problems indicated by the exception.
Unfortunately, while the answers to those questions are somewhat related, they are in reality far from 100% correlated. Unfortunately, the assumption that the type of an exception will be sufficient to answer all of those questions makes it difficult to deal sensibly with many situations.
If you have control over all the exceptions that can be thrown, it may be helpful to use an exception-handling paradigm where the exception-handling object includes a virtual IsResolved property or method along with a ShouldCatchAs<T> property or method that returns a T if the exception needs to be handled as a T. Such a paradigm would be able to smoothly handle situations where an exception occurs while unwinding the stack from an earlier exception (the existing exception and new one would be wrapped into a composite exception object, whose ShouldCatchAs property would combine those of the original exceptions, and whose IsResolved property should only return true when both of the original exceptions' IsResolved properties do likewise).
I don't know any way to integrate such behavior into the existing frameworks unless one catches and wraps all exceptions that don't fit the paradigm, but perhaps future frameworks can facilitate such things.
From my years of experience, dealing with errors is best done via logging them at all levels, and return true/false from functions, indicating success/fail.
Logging is implementation dependant. It could be to a file, to memory, and you can log messages, unique numbers, whatever, as long as the log will enable you to pinpoint the exact place of the error.
I sometimes use exceptions, in cases where I perform many operations, each one depending on the success of its predecessor. This makes the code cleaner, with no ifs for error checking. Nevertheless, this is not the main thing to care about. The main thing is log the errors, and return success/fail. Success/fail is needed so that you can decide whether to continue the normal way or not (such as not doing the indended operation because the read size may overrun the memory).
Two more important notes:
1) You must construct a super easy API to report (log) your messages, otherwise you will find yourself postponing this crucial thing, eventually not doing it.
2) It's essential for the log or report to be easily viewed and inform you about the problems as they accure. Otherwise you might find yourself not using the error report mechansim at all.
This is a very important subject to me, and I believe it to be one of the most important issues in software engineering. You can read more about it on my website
You shouldn't be throwing Exceptions then.
An Exception is meant for an exceptional case. Errors found on a validation method isn't considered "Exceptional", it's rather obvious that validation errors would occur.
An exceptional situation is when your attempt to connect to a database failed, for example.
You should log all validation errors to an array, and then format it and display it as you like.
Exceptions are not intended for validation, they are intended to be created when something that is different from what was expected happens during the execution. This is why you can't create many exceptions at once, but exceptions can be caused because some other exception happened, this is why they can have a parent exception named case.

Alternative to (or refinement for) State Pattern suffering from LSP violation

I'm having trouble wrapping my head around state-based functionality for an invoicing system we are currently building. The system will support calculation, manual approval, printing, and archiving of invoices.
At first I thought we should use the State Pattern to model this. An invoice would be the context, which delegates printing, archiving, etc. to its currently assigned state.
But this is obviously a bad idea, because the different states (created, approved, printed, archived) should not support the same operations. E.g., you shouldn't be able to print an invoice, which hasn't been approved before. Throwing exceptions for unsupported operations would be a violation of LSP. I found a general description of this problem here.
Does anybody have an idea, how to implement this appropriately?
PS: I'm aware that this might sound like some lame-ass homework assignment, but it's not; I need this for a real world system.
You're basically creating a workflow of application states, where at each state the available operations on an invoice change. The state pattern doesn't seem appropriate, but you can still use it if you also create some operations like boolean canPrint() that would have to be used before calling print(). print() would have a contract that allows throwing exceptions if canPrint() returns false. This way, subclasses wouldn't break that contract. Another option is to have a boolean tryPrint(), that will only print if it can, and return whether it printed.
But, if the states support mostly non-overlapping operations, then maybe the state pattern is not the solution. Take a step back and look for better ways, without trying to fit a specific pattern to your problem. One way is to create a separate class with the necessary operations for each "state": like CreatedInvoice, ApprovedInvoice, etc. These classes would only have the operations they support.
Chain of Responsibility Pattern might help you here.
Adding the how part and fixing the link.
There can be Calculator, Approver, Printer and Archiver classes which are handler classes. These can have processRequest() overridden from a parent abstract class. Invoice can be a class which is passed to each handler's processRequest() method. The advantage with using the pattern here is newer handlers can be added dynamically and chain links with sequence of handlers can be changed easily.
Whether the State Pattern is really appropriate to your situation is not certain, but if it's not, Liskov is not the reason. Throwing some sort of "invalid operation in current state" exception can be defined as possible and valid in the state interface, and then subclasses doing this do not violate LSP.
The classic example used for the State Pattern in the GoF Design Patterns book is a TCPConnection, which definitely has operations not supported or sensible in all states. You can't transmit on a closed connection, for example.

Exceptions or not? If "yes" - checked or not?

I suppose this scratches a vast topic, but what is the best approach in handling program work-flow other than the ideal variant when everything gets done the best way.
Let's be a bit more specific:
a class has a method, that method operates on its parameters and returns result.
e.g.:
public Map<Object,OurObject> doTheWork(OtherObject oo);
One possible outcome that I ruled out was returning null if something went other way, but the ideal.
Is there a correct way ("silver bullet", or so called "best practice") of handling that situation?
I see three other outcomes:
1 - the method returns EMPTY_MAP;
2 - the method has checked exceptions;
3 - throwing a RuntimeException;
If there is no generally correct answer to that question - what are the conditions that should be considered?
Regarding the principles of design by contract (in brief, the method's responsibility is to take care of the output, assuming input parameters are correct) - is it correct for the method to throw any exception or it is better to return empty result, though correct in structure (e.g. not null)
Returning null is like setting a trap for someone. (In cases like HashMaps we've been trained to look out for nulls, so going along with precedent is ok.) The user has to know to look out for the null, and they have to code an alternative path to handle that case (which sounds a lot like handling an exception), or risk an NPE (in which case an exception gets thrown anyway, just a less informative one, at a distance from the place where the original problem occurred, so information about what went wrong will be missing).
Returning an empty map makes it unclear whether anything went wrong or not. It isn't hurtful like returning null, but it is totally ambiguous. If somehow returning the map data is purely a best-effort thing and the user doesn't really need to know, this could be ok. (But this is pretty rare.)
If there is anything you expect the user to be able to do about the exception, throwing a checked exception may be appropriate.
If there is nothing the user can do about the exception, or if the exception would only occur due to a programming error, or due to something that should be caught during testing, then an argument can be made for using an unchecked exception. There is a lot of room for disagreement about what should be checked and what should be unchecked.
Which option would be most beneficial to the callee? If all you need to know is an empty map or null is returned, then that is fine. If you need more information, then an exception would be a better choice.
As for what type of exception, if the callee really needs to do something in order to recover, then a checked exception is appropriate. However, an unchecked exception is likely cleaner.
As for returning null or an empty map, it depends on what the callee is going to do with it. If you expect the callee to take that map and pass it around elsewhere, then an empty map is a better choice.
If something in you method breaks because of erroneous input the user needs to know. Therefore, an exception is the best way to go. Returning empty or null data could potentially make the user think that nothing is wrong and that is definitely not what you want.
I'll bet that there's plenty of good answers for this in stackoverflow. Before I search for them:
Exceptions are thrown in exceptional situations only - they are not used for normal control flow.
Checked exceptions are thrown when the caller should be able to recover from the exception
Unchecked exceptions are thrown when the caller probably should not recover from the exception e.g. exceptions thrown due to programming errors.
An empty collection should be returned if it is a normal state. Especially when the result is a collection, the return value should not be null. If the the return value is null, then it should be clearly documented. If there's need for more complicated analysis of the return state, you might be better of with a appropriately modeled result class.
It all depends on how big of a problem it is if doTheWork.
If the problem is so large that the application might need to shutdown then throw a RuntimeException.
If the callee might be able to recover from the problem then a CheckedException is common.
If an empty Map has no meaning then it can be used as a return, but you have to be careful that an empty Map is not a valid value to return in a successful case.
If you do return just a null, I would suggest making a note in the Javadoc about the return value.
The best pattern in many cases is the try/do pattern, where many routines have two variations, e.g. TryGetValue() and GetValue(). They are designed to handle three scenarios:
The object was obtained successfully
The value couldn't be obtained, for a reason the caller might reasonably anticipate, and the system state is what the caller would expect given such a failure.
The value couldn't be obtained, for some reason the caller probably isn't anticipating, or else the system state is corrupted in a way the caller won't expect.
The idea behind the try/do pattern is that there are times when a caller will be prepared to handle a failure, but there are other times where the only thing the caller could do in case of failure would be to throw an exception. In the latter case, it would be better for the method which failed to throw the exception rather than requiring the caller to do it.