An alternative to throwing exceptions. Rather than: try { doSomething(); } catch (S''''''omeException e) { handleException(e); } We might have: boolean success = doSomething(); if (!success) handleException(e); ''The above would need some magic to get at the exception information e. So we might have to use:'' R''''''eturnCode rc = doSomething(); if (rc != SUCCESS) handleException(rc); But see UseExceptionsInsteadOfErrorValues. ---- '''ExceptionHandlingChallenge entry 1: Use ErrorValue''''''s and ''if (success)''''' Newkirk and Martin used the following code (ExtremeProgrammingInPractice, p120): boolean success = U''''''serDatabase.add(user); if (success) { if (mailPassword(email, password)) redirect("success"); else { U''''''serDatabase.delete(email); ''//this can fail also !!!'' redirect("mailfailure"); } } else { redirect("addfailure"); } '''Pros:''' * Easy to unit test * Doesn't use exceptions, which means you don't have to put try/catch blocks everywhere. '''Cons:''' * Suffers from the ArrowAntiPattern. * if (success) puts error handling far from the erroring code. * Doesn't use exceptions, which means the compiler won't tell you what exceptional cases to expect (i.e., you can throw away the return values if you are lazy). * Asymmetrical (Changing it to ''if (UserDatabase.add(user)'' would alleviate this, but would be even harder to read). * Is verbose. ---- '''ExceptionHandlingChallenge entry 2: Use ErrorValue''''''s and ''if (!success)''''' A variation on the above: boolean successWhenAdding = U''''''serDatabase.add(user); if (!successWhenAdding) redirect("addfailure"); boolean successWhenMailing = mailPassword(email, password)); if (!successWhenMailing) { U''''''serDatabase.delete(email); ''//this can also fail !!!'' redirect("mailfailure"); } redirect("success"); '''Pros:''' * Same as above, plus: * No ArrowAntiPattern. * Errors are handled directly after failures happen, then the rest of the code goes on like normal. Kind of like the BouncerPattern. * Symmetry. '''Cons:''' * The compiler still won't help you if you want to be lazy. * Wouldn't you have to put 'return;' after each of the failure redirects? ''Giving...'' boolean successWhenAdding = U''''''serDatabase.add(user); if (!successWhenAdding) { redirect("addfailure"); return false; } boolean successWhenMailing = mailPassword(email, password)); if (!successWhenMailing) { U''''''serDatabase.delete(email); ''//this can also fail !!!'' redirect("mailfailure"); return false; } redirect("success"); return true; ''or...'' boolean success = U''''''serDatabase.add(user); if (!success) redirect("addfailure"); if (success) { success = mailPassword(email, password)); if (!success) { U''''''serDatabase.delete(email); ''//this can also fail !!!'' redirect("mailfailure"); } } if (success) redirect("success"); return success; ''or, if you want symmetry...'' boolean success = true; if (success) { U''''''serDatabase.add(user); if (!success) redirect("addfailure"); } // ''etc...'' --------------- Some suggest error values are problematic because "true" functions only return one value. Thus, errors allegedly "waste" the return value for other uses. Here are two ways to get around this. The first is to return an array/structure/object: resultArray = doSomething(...) if (!resultArray.good) ... Another is to specify the result variable as a parameter: doSomething(param1, param2, errorVar="status") if (!status) ... If the error variable is not requested, then the routine does its own error handling (such as a message and stop). This is why it is an optional parameter. This works better for some languages than others. ---- CategoryException