Google+

Replace Error Code with Exception

Problem

A method returns a special value that indicates an error?

Solution

Throw an exception instead.

Before
int withdraw(int amount) {
  if (amount > _balance) {
    return -1;
  }
  else {
    balance -= amount;
    return 0;
  }
}
After
void withdraw(int amount) throws BalanceException {
  if (amount > _balance) {
    throw new BalanceException();
  }
  balance -= amount;
}
Before
int Withdraw(int amount) 
{
  if (amount > _balance) 
  {
    return -1;
  }
  else 
  {
    balance -= amount;
    return 0;
  }
}
After
///<exception cref="BalanceException">Thrown when amount > _balance</exception>
void Withdraw(int amount)
{
  if (amount > _balance) 
  {
    throw new BalanceException();
  }
  balance -= amount;
}
Before
function withdraw($amount) {
  if ($amount > $this->balance)
    return -1;
  else {
    $this->balance -= $amount;
    return 0;
  }
}
After
/**
 * (Here you put some real function documentation.
 *  Note: the line below indicates that function
 *  can throw an exception of given type.)
 * @throws BalanceException
 */
function withdraw($amount) {
  if ($amount > $this->balance) {
    throw new BalanceException();
  }
  $this->balance -= $amount;
}
Before
def withdraw(self, amount):
    if amount > self.balance:
        return -1
    else:
        self.balance -= amount
    return 0
After
def withdraw(self, amount):
    if amount > self.balance:
        raize BalanceException()
    self.balance -= amount

Why Refactor

Returning error codes is an obsolete holdover from procedural programming. In modern programming, error handling is performed by special classes, which are named exceptions. If a problem occurs, you "throw" an error, which is then "caught" by one of the exception handlers. Special error-handling code, which is ignored in normal conditions, is activated to respond.

Benefits

  • Frees code from a large number of conditionals for checking various error codes. Exception handlers are a much more succinct way to differentiate normal execution paths from abnormal ones.

  • Exception classes can implement their own methods, thus containing part of the error handling functionality (such as for sending error messages).

  • Unlike exceptions, error codes cannot be used in a constructor, since a constructor must return only a new object.

Drawbacks

  • An exception handler can turn into a goto-like crutch. Avoid this! Do not use exceptions to manage code execution. Exceptions should be thrown only to inform of an error or critical situation.

How to Refactor

Try to perform these refactoring steps for only one error code at a time. This will make it easier to keep all the important information in your head and avoid errors.

  1. Find all calls to a method that returns error codes and, instead of checking for an error code, wrap it in try/catch blocks.

  2. Inside the method, instead of returning an error code, throw an exception.

  3. Change the method signature so that it contains information about the exception being thrown (@throws section).