Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is returning an exception an anti-pattern?

Tags:

I have two simple methods:

public void proceedWhenError() {    Throwable exception = serviceUp();     if (exception == null) {       // do stuff    } else {       logger.debug("Exception happened, but it's alright.", exception)       // do stuff    } }  public void doNotProceedWhenError() {    Throwable exception = serviceUp();     if (exception == null) {       // do stuff    } else {       // do stuff       throw new IllegalStateException("Oh, we cannot proceed. The service is not up.", exception)    } } 

The third method is a private helper method:

private Throwable serviceUp() {     try {         service.connect();         return null;     catch(Exception e) {        return e;     } } 

We had a small talk with a colleague of mine about the pattern used here:

returning an Exception (or Throwable) object from the serviceUp() method.

The first opinion:

It is an anti-pattern to use Exceptions to control the workflow and we should only return boolean from serviceUp() and never the Exception object itself. The argument is that using Exceptions to control the workflow is an anti-pattern.

The second opinion:

It is alright, as we need to deal with the object afterwards in the two first methods differently and whether returning Exception object or boolean does not change the workflow at all

Do you think 1) or 2) is correct and especially, why? Note, that the question is ONLY about the method serviceUp() and its return type - boolean vs Exception object.

Note: I am not questioning whether to use Throwable or Exception objects.

like image 595
Martin Linha Avatar asked Apr 12 '18 12:04

Martin Linha


People also ask

Are exceptions an anti pattern?

According to many references like here and here, using Exceptions to control application flow is an anti-pattern that is not recommended. (Because of performance issues, Less readable and etc).

Can exceptions be returned?

Use exceptions to report and handle error conditions. Exceptions shouldn't be returned as a return value or parameter instead of being thrown. Don't throw System. Exception, System.

Can you throw an exception and return something?

It's not possible to both throw an exception and return a value from a single function call.

Does throwing an exception return false?

Since it returns a boolean value, there would be no need of throwing an exception, simply return false.


Video Answer


1 Answers

It is an anti-pattern to use exceptions to direct the flow only when the exception is thrown in a non-exceptional situation*. For example, ending a loop by throwing an exception when you reach the end of a collection is an anti-pattern.

Controlling the flow with actual exceptions, on the other hand, is a good application of exceptions. If your method encounters an exceptional situation that it cannot handle, it should throw an exception, thus re-directing the flow in the caller to the exception handler block.

Returning a "naked" Exception object from a method, rather than throwing it, is certainly counter-intuitive. If you need to communicate the results of an operation to the caller, a better approach is to use a status object that wraps all the relevant information, including the exception:

public class CallStatus {     private final Exception serviceException;     private final boolean isSuccess;     public static final CallStatus SUCCESS = new CallStatus(null, true);     private CallStatus(Exception e, boolean s) {         serviceException = e;         isSuccess = s;     }     public boolean isSuccess() { return isSuccess; }     public Exception getServiceException() { return serviceException; }     public static CallStatus error(Exception e) {         return new CallStatus(e, false);     } } 

Now the caller would receive CallStatus from serviceUp:

CallStatus status = serviceUp(); if (status.isSuccess()) {     ... // Do something } else {     ... // Do something else     Exception ex = status.getException(); } 

Note that the constructor is private, so serviceUp would either return CallStatus.SUCCESS or call CallStatus.error(myException).

* What is exceptional and what is not exceptional depends a great deal on the context. For example, non-numeric data causes an exception in Scanner's nextInt, because it considers such data invalid. However, the same exact data does not cause an exception in hasNextInt method, because it is perfectly valid.

like image 149
Sergey Kalinichenko Avatar answered Oct 01 '22 18:10

Sergey Kalinichenko