Where should you catch an Exception?

The Idea!

Not every code deserves a catch! Design demands that exception should be caught where it can be handled! Most of the time it is controller. Sometimes there is a pseudo exception handling, where exception is suppressed only to avoid an error in a runtime and not handled.

For example consider following codes:

Any normal MVC!


interface Searchable{
    function search();
}

class User extends Model implements Searchable{
    public static function search($condition) :array{
        return User::findAll($condition);
    }
}

class UserController extends Controller{
    public function search(Request $request,Response $response){
        User::search(["where"=>[
            "paid" => true
        ]]);
    }
}


Wrong Exception Handling! – Suppressing an Exception

This is a classic example of suppressing an exception. These kinds of exceptions give no room to the end user or developer to do anything for the exception but pretend that nothing happened.
Developers here try to keep functionality intact despite there is an exception! Most often it will be only logged – that no one cares.


interface Searchable{
    function search();
}

class User extends Model implements Searchable{
    public static function search($condition) :array{
        try{
            return User::findAll($condition);
        }catch(Exception $e){
            // You are still getting back with an empty array indicating search result is empty
            Log::error($e->getMessage());
            return [];
        }
    }
}

class UserController extends Controller{
    public function search(Request $request,Response $response){
        $result = User::search(["where"=>[
            "paid" => true,
            "name" => ["like",$request->param("q")]
        ]]);
        return $response->json($result);
    }
}

Right Exception Handling!

These kinds of exceptions handling forces a user to do something about it – which is by definition an exception handling. It is clearly communicated to the end user that there is an exception and thus, input can be changed.


interface Searchable{
    function search();
}

class User extends Model implements Searchable{
    public static function search($condition) :array{
        try{
            return User::findAll($condition);
        }catch(Exception $e){
             Throw($e);
        }
    }
}

class UserController extends Controller{
    public function search(Request $request,Response $response){
        try{
            $result = User::search(["where"=>[
                "paid" => true,
                "name" => ["like",$request->param("q")]
            ]]);
            return $response->json($result);
        }catch(Exception $e){
            return $response->json([
                "status"=>"false",
                "message"=>$e->getMessage()
            ]);
        }
    }
}


Exceptions in handling Exceptions!

Certain exceptions can’t be handled in a controller, these exceptions often combines with some transactions.

Please note that – example shows that module files aren’t important (which is right). It doesn’t matter if module files are left or deleted, but database entries are important. Which is why database rollback is not considering file unlink exception. This is very likely that not all the files removed, which defeats the purpose of keeping database entry – a broken module.

In following example, controller is catching a re-thrown exception, while during a re-throw, exception is being handled by rolling back queries needed to delete a module.


class Module extends Model {
    // ...
    // ...
    private function deleteFromDb(){
        try{
            Transaction::begin();
            // ....
            // ....
            Transaction::commit();
        }catch(ModelExcepiton $e){
            //Handling the exception within a block!
            Transaction::rollback();
            throw $e;
        }

    }
    private function deleteFiles(){
        try{
            array_walk($this->files,function($file){
                unlink($file);
            });
        }catch(FileException $e){
            throw $e;
        }
    }
    public function delete(){
        try{
            $this->deleteFromDb();
            $this->deleteFiles();
        }catch(Exception $e){
            throw $e;
        }
    }
}

class ModuleController extends Controller {
    // ---
    public function delete(Request $request,Response $response){
        if(!$this->isAuthenticated()){
            $response->statusCode = 401;
            return $response;
        }
        try{
            $module = Module::find($request->param('id'));
            $module->delete();
        }catch(Exception $e){
            if($e instanceof FileException){
                //nothing serious!
            }elseif($e instanceof ModelExcepiton){
                //module is still installed!
            }
            return $response->json([
                "status"=>"false",
                "message"=>$e->getMessage()
            ]);
        }
    }
}

Where should you catch an Exception?

2 thoughts on “Where should you catch an Exception?

  1. Do we have to throw an exception if there is already an exception in the code block then it is already thrown right?

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top