Is "throwing stack-less exceptions" a known/common pattern? - exception

Is this a known/common pattern? (example in Java)
class BadInput extends Exception {
BadInput INSTANCE = new BadInput();
private BadInput() { }
}
Whenever INSTANCE is thrown, it won't have a sensible stack trace but that's OK as it doesn't signify a coding error/resource issue/security issue/etc. (at a low level) but an input error (at a high level). Also, it won't explain why some input is bad. That's OK as well if no specifics are needed.
Here's a use case about (exact) integer division (it could just as well be about e.g. rationals or polynomials)
class ExactDivision extends BinaryOperator {
int compute(int arg1, int arg2) throws BadInput
{
if (arg2 == 0 || arg1 % arg2 != 0) throw BadInput.INSTANCE;
return arg1 / arg2;
}
}
It may be involved in a (possibly complex) computation of some expression. If the exception is thrown, no cost is incurred in building a stack trace. All intermediate levels don't have the burden of having to check the validity of intermediate results since the exception simply propagates upwards (no checks as in if (!equalsErrorSentinel(subresult)) … are needed, which avoids both performance-penalties as well as coding errors (such checks are bound to be forgotten sometimes). At the end (at the top level), a caught BadInput exception simply means that the input makes the evaluation undefined. Absence of the exception means that the computed result is correct.
It seems to be a great pattern (only to be used when the two OK's above are really OK of course). Why have I never come across it?

I've seen this sort of thing done for performance reasons in a few cases.
The usual way to do it, though, seems to be to override fillInStackTrace() The new implementation should just return this.
Both ways work, and you could even do both at the same time to avoid having a completely irrelevant stack trace in your BadInput instance. You should probably make the constructor public though, so people can still use the normal throwing code for your exception if they want to.
Also, if you're going to throw constants, I suggest having multiple constants like DIVIDE_BY_ZERO with appropriate messages built-in.

Related

Turning an exception into an IObservable exception

I have the following code:
var s = Observable
.StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
.SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
.Select(ParseToMD);
The ParseToMD is pretty simple:
private static IDocumentMetadata ParseToMD(string marc21XML)
{
return MARC21Parser.ParseForMetadata(marc21XML);
}
Unfortunately, it is quite legal for the ParseForMetadata to throw an exception. I'd very much like to be able to use the normal Rx techniques to deal with the exception. For example:
var goodOrEmpty = s.Catch(Observable.Empty<Tuple<PaperStub, PaperFullInfo>>());
How can I properly protect that Select call so exceptions are correctly turned into IObservable On Error? I'm also going to need to do it for the others (StartAsync).
A pattern I follow is a little different from the standard way of dealing with exceptions. Just because a select throws an exception doesn't necessarily mean the subscription is bad. The next event might be fine.
Note that in RX, when OnError is triggered it means the subscription must be terminated.
What I do is wrap my selects in a monadic Exceptional type to do the following
Exceptional<IDocumentMetadata> s = Observable
.StartAsync(tnk => CERNWebAccess.GetWebResponse(reqUri))
.SelectMany(resp => Observable.StartAsync(tkn => resp.Content.ReadAsStringAsync()))
.SelectExceptional(ParseToMD);
If you just want to skip the bad ones
s.SelectMany(s=>s)
or you can project it like
var Exceptional<ProcessedDocumentType> =
s.Select(document => ProcessDocument(document))
If you need to extract the exception from the Exceptional type you can do this with properties
bool HasException
Exception Exception
To get the value you can access the property
T Value
However you should use Select and SelectMany if you are just operating on the good values and don't need the exceptions.
My implementation was based on
Exception or Either monad in C#
From your comments, I have to wonder if you are seeing the effect of using StartAsync rather than FromAsync. These methods differ in one important detail; the former runs once as soon as it is evaluated - i.e. it runs exactly once regardless of and before any number of subscribers. If there are no subscribers and it throws you will have an unobserved exception. Contrast with FromAsync which is called per subscriber on subscription.

Are exceptions fundamental, or can they be replaced with conditions?

I am attempting to understand from where exception conditions derive. My question is at the end, but I will present an example that might make it clearer.
Take this Java code, for example. It has the path to a file and set-up a File object. If the path is null, an exception is thrown.
String path = getPathName();
try {
File file = new File(path);
} catch (NullPointerException e) {
// ...
}
This is hardly an exceptional circumstance, though, and if we could modify it in such a way that this might be preferrable:
String path = getPathName();
if (path == null) {
path = DEFAULT_PATH;
}
File file = new File(path); # we've removed the need for an exception
But moving further, we run into a new exception when we try and make the File readable.
try {
file.setReadable(true);
} catch (SecurityException e) {
// ...
}
We can skirt around this issue by checking two conditions:
SecurityManager sm = System.getSecurityManager();
if (sm != null && sm.checkWrite(path)) {
// modify the SecurityManager
} else {
file.setReadable(true);
}
With this example in mind, on to my question...
If we move down the stack, going from Java to the OS, etc., is it possible to replace all exception handling code with if-else branches? Or is there some root cause of exceptions (hardware?) that means they are "baked" into programming?
If we move down the stack, going from Java to the OS, etc., is it possible to replace all exception handling code with if-else branches?
Yes. This is how it used to be done, and still is in languages without exceptions. Exceptions are used because they are easier in a number of senses. The primary advantages are that cases not anticipated by the programmer can be aggregated in a general handler; and that information about the exceptional condition does not need to be explicitly preserved in every single function until it is properly handled.
Or is there some root cause of exceptions (hardware?) that means they are "baked" into programming?
Also yes. In general, unexpected hardware conditions need to be handled in some way, unless you are comfortable with undefined behaviour in such cases.
If all the methods in a program returned a pointer/reference to some kind of "exception" object (for other return values, pass in a pointer or reference to a caller-allocated storage location), and if every call to every method which might directly or indirectly want to throw an exception were bracketed with something like:
ret = callFunction( ...parameters...);
if (ret != NULL)
return AddToExceptionStacktrace(ret, ...info about this call site... );
then there would be no need for any other form of exception handling (note that if the type supports scoped variables, the "return" statement would have to insert code to clean them up before it actually returns to the caller).
Unfortunately, that's a lot of extra code. This approach would be workable in a language which had only "checked" exceptions (meaning a method can neither throw exceptions nor pass them through unless it is declared as doing so), but adding that overhead to every function which might directly or indirectly call a function which throws an exception would be very expensive. Exception-handling mechanisms generally eliminate 99% of the extra overhead in the no-exceptions case, and the expense of increasing the overhead in the "exception" case.

Is it good practice to throw an exception sooner than later?

Today I encountered the following situation: ("pseudo code")
class MyClass {
public void workOnArray(Object[] data) {
for (Object item : data) {
workOnItem(item);
}
}
public void workOnItem(Object item) {
if (item == null) throw new NullPointerException();
}
}
Now if the caller calls workOnArray with an array containing null items, the caller would get a NullPointerException because of workOnItem.
But I could insert an additional check in workOnArray, in other words, the problem can be detected sooner.
(Please note that this is a trivial example, in a real life application this can be much less obvious).
On the pro side I'd say an additional check could offer more high-level diagnostic information. Also failing early is always a good thing.
On the contra side I'd ask myself "If I do that, shouldn't I also validate each and every parameter passed into the core API of my programming language and throw the exact same exceptions?"
Is there some rule of thumb when to throw exceptions early and when to just let the callee throw it?
In the case of a loop processing items like that, there's one thing that would definitely make me want to pre-validate the whole array of items first; If it would be bad for some of the items to be processed before an exception was thrown, leaving any remaining items un-processed.
Barring some sort of transaction mechanism wrapping the code, I would usually want to have some assurance that the items in the collection were valid before beginning to process them.
In this example, the workOnItem method is the one that cares whether or not item is null. The workOnArray method doesn't care whether or not items are null and so IMO shouldn't validate whether or not any items are null. The workOnItem method does care and so should perform the check.
I would also consider throwing a more appropriate exception type from workOnItem. A NullPointerException (or in C#, NullReferenceException) often indicates some unexpected flaw in the operation of a method. In C#, I would be more inclined to throw an ArgumentNullException that includes the name of the null parameter. This more clearly indicates that workOnItem can't continue because it cannot handle receiving a null argument.

Is using an if() coupled with an immediate return an accepted practise?

Is using an if coupled with an immediate return like in the example below an acceptable practise instead of having a if with a block of code inside {} ? Are these equivalent in practise or is there a disadvantage to one of the approaches ?
An example in Java:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
ServletContext sc = this.getServletContext();
// Throw exception for fatal error (Servlet not defined in web.xml ?)
if( sc == null )
return; // old-style programming
// Careful with silent bugs ! Correct way of handling this is:
// throw new RuntimeException( "BookDetail: ServletContext is null" );
BookList bookList = WebUtil.getBookList( sc );
Martin Fowler would favour the early return, and calls the idea a Guard Clause.
Personally, I don't like it in Java, as I prefer one return per method. However this is subjective and I may be in the minority.
I've blogged about this for and against.
That is not a return, it's an exception. The code is perfectly ok tho.
Even if you'd replace that throw with a "return something", it would still be ok.
I think it comes down to readability. The code should function the same either way.
I use stuff like this all the time
Function Blah() As Boolean
If expr Then
Return False
End If
Do Other work...
Return result
End Function
For error conditions, generally it's best to throw an exception - exception handling was invented to get rid of the manual return code style error checking in C that comprises about 30% of a C program.
However, early returns are fine - they are far more readable than adding an extra scope with curly braces.
if (!_cache.has_key(key))
return null;
return _cache[key]
Is better than:
if (_cache_has_key(key))
{
return _cache[key]
}
else
return null;
And it only gets more obvious the more early returns that you add, 5 early returns beats the hell out of 5 nested if statements.
Note that I didn't return null on an error condition, it's expected that often the key won't be in the cache - but it still means the caller has to write code to check the result. In .NET there's a better pattern of returning a boolean, and setting the result via an out parameter. The methods beginning with Try usually follow this pattern:
Foo foo;
if (!TryGetCachedFoo("myfoo", foo))
{
foo = new Foo(...);
AddToCache("myfoo", foo);
}
// do something with foo
As long as you're using them for conditional escapes as the first thing in the routine. I think the fact that they are obvious in that location, and avoid at least one level of indentation outweighs the negative of having a multiple returns.
In the example you give, I'd favor throwing an exception because a null ServletContext is usually a sign that something has gone wrong. However, there are times when checking whether a parameter is null and returning immediately from the method is both useful and valid.
For instance, if you are gathering contact information about a user and the user has the option of providing a phone number. In that case, you may have a method that validates that the phone number contains all numbers, has the correct number of digits, etc, but which would immediately return if the phone number was empty or null.
public void validatePhone(String phoneNumber) throws ValidationException {
if (phoneNumber == null || phoneNumber.equals("")) {
return;
}
//do validation stuff, throwing exception if not valid
In your example, there is no return after the if statement; you are throwing an exception. (edit: I see you have changed the code since I posted this answer).
There are purists who think that you should have only one return statement in a method (at the end of the method). There's some merit to that idea - it makes the code more clear, it makes it easier to see what can be returned for the method, and especially when you need to cleanup resources (especially in a language without garbage collection; or in Java where you need to close for example an InputStream) it's more clear and easier if you have just one return at the bottom, and do the cleanup code just before the return.
I would not have any objection against the code in your example, however.
I have a few (subjective, or not) remarks:
I always use accolades with a if even the block contains only one line
I don't like to have many return on one method
I don't think that this null check is necessary. If getServletContext() returns null, then you have a much bigger problem with your webapp that should definitely be fixed. In that case, having a NullPointerException later in the code is an exceptional error so I wouldn't bother handling it.

Exception handling: Contract vs Exceptional approach

I know two approaches to Exception handling, lets have a look at them.
Contract approach.
When a method does not do what it says it will do in the method header, it will throw an exception. Thus the method "promises" that it will do the operation, and if it fails for some reason, it will throw an exception.
Exceptional approach.
Only throw exceptions when something truly weird happens. You should not use exceptions when you can resolve the situation with normal control flow (If statements). You don't use Exceptions for control flow, as you might in the contract approach.
Lets use both approaches in different cases:
We have a Customer class that has a method called OrderProduct.
contract approach:
class Customer
{
public void OrderProduct(Product product)
{
if((m_credit - product.Price) < 0)
throw new NoCreditException("Not enough credit!");
// do stuff
}
}
exceptional approach:
class Customer
{
public bool OrderProduct(Product product)
{
if((m_credit - product.Price) < 0)
return false;
// do stuff
return true;
}
}
if !(customer.OrderProduct(product))
Console.WriteLine("Not enough credit!");
else
// go on with your life
Here I prefer the exceptional approach, as it is not truly Exceptional that a customer has no money assuming he did not win the lottery.
But here is a situation I err on the contract style.
Exceptional:
class CarController
{
// returns null if car creation failed.
public Car CreateCar(string model)
{
// something went wrong, wrong model
return null;
}
}
When I call a method called CreateCar, I damn wel expect a Car instance instead of some lousy null pointer, which can ravage my running code a dozen lines later. Thus I prefer contract to this one:
class CarController
{
public Car CreateCar(string model)
{
// something went wrong, wrong model
throw new CarModelNotKnownException("Model unkown");
return new Car();
}
}
Which do style do you use? What do you think is best general approach to Exceptions?
I favor what you call the "contract" approach. Returning nulls or other special values to indicate errors isn't necessary in a language that supports exceptions. I find it much easier to understand code when it doesn't have a bunch of "if (result == NULL)" or "if (result == -1)" clauses mixed in with what could be very simple, straightforward logic.
My usual approach is to use contract to handle any kind of error due to "client" invocation, that is, due to an external error (i.e ArgumentNullException).
Every error on the arguments is not handled. An exception is raised and the "client" is in charge of handling it. On the other hand, for internal errors always try to correct them (as if you can't get a database connection for some reason) and only if you can't handle it reraise the exception.
It's important to keep in mind that most unhandled exception at such level will not be able to be handled by the client anyway so they will just probably go up to the most general exception handler, so if such an exception occurs you are probably FUBAR anyway.
I believe that if you are building a class which will be used by an external program (or will be reused by other programs) then you should use the contract approach. A good example of this is an API of any kind.
If you are actually interested in exceptions and want to think about how to use them to construct robust systems, consider reading Making reliable distributed systems in the presence of software errors.
Both approaches are right. What that means is that a contract should be written in such a way as to specify for all cases that are not truly exceptional a behavior that does not require throwing an exception.
Note that some situations may or may not be exceptional based upon what the caller of the code is expecting. If the caller is expecting that a dictionary will contain a certain item, and absence of that item would indicate a severe problem, then failure to find the item is an exceptional condition and should cause an exception to be thrown. If, however, the caller doesn't really know if an item exists, and is equally prepared to handle its presence or its absence, then absence of the item would be an expected condition and should not cause an exception. The best way to handle such variations in caller expectation is to have a contract specify two methods: a DoSomething method and a TryDoSomething method, e.g.
TValue GetValue(TKey Key);
bool TryGetValue(TKey Key, ref TValue value);
Note that, while the standard 'try' pattern is as illustrated above, some alternatives may also be helpful if one is designing an interface which produces items:
// In case of failure, set ok false and return default<TValue>.
TValue TryGetResult(ref bool ok, TParam param);
// In case of failure, indicate particular problem in GetKeyErrorInfo
// and return default<TValue>.
TValue TryGetResult(ref GetKeyErrorInfo errorInfo, ref TParam param);
Note that using something like the normal TryGetResult pattern within an interface will make the interface invariant with respect to the result type; using one of the patterns above will allow the interface to be covariant with respect to the result type. Also, it will allow the result to be used in a 'var' declaration:
var myThingResult = myThing.TryGetSomeValue(ref ok, whatever);
if (ok) { do_whatever }
Not quite the standard approach, but in some cases the advantages may justify it.