UnreachableCodeExecuted

Since v1.2016052101

Description

UnreachableCodeExecuted is an exception. Throw this exception whenever your switch statements or if / else statements have branches that should never be executed.

Public Interface

UnreachableCodeExecuted has the following public interface:

// UnreachableCodeExecuted lives in this namespace
namespace GanbaroDigital\Defensive\V1\Exceptions;

// our base classes and interfaces
use GanbaroDigital\ExceptionHelpers\V1\BaseExceptions\ParameterisedException;
use GanbaroDigital\ExceptionHelpers\V1\Callers\Filters\FilterCodeCaller;
use GanbaroDigital\HttpStatus\Interfaces\HttpRuntimeErrorException;
use GanbaroDigital\HttpStatus\StatusProviders\RuntimeError\UnexpectedErrorStatusProvider;

// our return type(s)
use GanbaroDigital\HttpStatus\StatusValues\RuntimeError\UnexpectedErrorStatus;

class UnreachableCodeExecuted
  extends ParameterisedException
  implements DefensiveException, HttpRuntimeErrorException
{
    // we map onto HTTP 500
    use UnexpectedErrorStatusProvider;

    /**
     * creates a new exception about unreachable code that has, in fact,
     * been executed
     *
     * @return UnreachableCodeExecuted
     */
    public static function newAlert();

    /**
     * what was the data that we used to create the printable message?
     *
     * @return array
     */
    public function getMessageData();

    /**
     * what was the format string we used to create the printable message?
     *
     * @return string
     */
    public function getMessageFormat();

    /**
     * which HTTP status code do we map onto?
     *
     * @return UnexpectedErrorStatus
     */
    public function getHttpStatus();
}

How To Use

Alerting About Unreachable Code

Use UnreachableCodeExecuted to detect when a switch statement is missing one or more case clauses:

use GanbaroDigital\Defensive\V1\Exceptions\UnreachableCodeExecuted;

switch($state) {
    case DirectDebit::STATE_CREATED:
        // ...
        break;
    case DirectDebit::STATE_SUBMITTED:
        // ...
        break;
    default:
        // if we get here, our direct debit is in a state that we have
        // no support for
        throw UnreachableCodeExecuted::newAlert();
}

or when an if / else statement reaches a branch that should never happen:

use GanbaroDigital\Defensive\V1\Exceptions\UnreachableCodeExecuted;

if ($state === DirectDebit::STATE_CREATED) {
    // ...
}
else if ($state === DirectDebit::STATE_SUBMITTED) {
    // ...
}
else {
    // if we get here, our direct debit is in an unsupported state
    throw UnreachableCodeExecuted::newAlert();
}

You should use UnreachableCodeExecuted as a placeholder. When you have the time, go back and define an explicit exception for each error where you've used UnreachableCodeExecuted. This will make your code even easier to support.

Catching The Exception

UnreachableCodeExecuted implements a rich set of classes and interfaces. You can use any of these to catch this exception.

// example 1: we catch only UnreachableCodeExecuted exceptions
use GanbaroDigital\Defensive\V1\Exceptions\UnreachableCodeExecuted;

try {
    throw UnreachableCodeExecuted::newAlert();
}
catch(BadRequirements $e) {
    // ...
}
// example 2: catch all exceptions thrown by the Defensive Library
use GanbaroDigital\Defensive\V1\Exceptions\UnreachableCodeExecuted;
use GanbaroDigital\Defensive\V1\Exceptions\DefensiveException;

try {
    throw UnreachableCodeExecuted::newAlert();
}
catch(DefensiveException $e) {
    // ...
}
// example 3: catch all exceptions where there was an unexpected problem
// at runtime
use GanbaroDigital\Defensive\V1\Exceptions\UnreachableCodeExecuted;
use GanbaroDigital\HttpStatus\Interfaces\HttpRuntimeErrorException;

try {
    throw UnreachableCodeExecuted::newAlert();
}
catch(HttpRuntimeErrorException $e) {
    $httpStatus = $e->getHttpStatus();
    // ...
}
// example 4: catch all exceptions that map onto a HTTP status
use GanbaroDigital\Defensive\V1\Exceptions\UnreachableCodeExecuted;
use GanbaroDigital\HttpStatus\Interfaces\HttpException;

try {
    throw UnreachableCodeExecuted::newAlert();
}
catch(HttpException $e) {
    $httpStatus = $e->getHttpStatus();
    // ...
}
// example 5: catch all runtime exceptions
use GanbaroDigital\Defensive\V1\Exceptions\UnreachableCodeExecuted;
use RuntimeException;

try {
    throw UnreachableCodeExecuted::newAlert();
}
catch(RuntimeException $e) {
    // ...
}

Class Contract

Here is the contract for this class:

GanbaroDigital\Defensive\Exceptions\UnreachableCodeExecuted
 [x] Can instantiate
 [x] Is defensive exception
 [x] is ParameterisedException
 [x] is HttpRuntimeErrorException
 [x] maps to HTTP 500 UnexpectedError
 [x] Is runtime exception
 [x] Can raise new alert
 [x] New alert message includes caller details
 [x] New alert data includes caller details

Class contracts are built from this class's unit tests.

Future releases of this class will not break this contract.

Future releases of this class may add to this contract. New additions may include:

  • clarifying existing behaviour (e.g. stricter contract around input or return types)
  • add new behaviours (e.g. extra class methods)

When you use this class, you can only rely on the behaviours documented by this contract.

If you:

  • find other ways to use this class,
  • or depend on behaviours that are not covered by a unit test,
  • or depend on undocumented internal states of this class,

... your code may not work in the future.

Notes

None at this time.

See Also