mercredi 7 octobre 2015

How to design code without repetitions to catch errors in mvc framework?

Let's suppose there is model that performs some logic on saving object. This logic consists of db-transactions, some external services calls.

class ExampleModel {
  //some field
  //constructor and getters with setters

  public function save() {
    $db->beginTransaction();
    $db->somequery();
    $db->anotherone();
    $object->externalApiCall();
    $object->saveToCache();
  }


}

My question is what is the best way to catch errors and make rollbacks?

Solution#1 Catch everything in the model, rollback there, log some information and re-throw error to a controller. Will look something like this:

class ExampleModel {
  //some field
  //constructor and getters with setters

  public function save() {
    try {
     $db->beginTransaction();
     $db->somequery();
     $db->anotherone();
     $object->externalApiCall();
     $object->saveToCache();
    } catch (DbException $e) {
      $db->rollback();
      $logger->log($e->getMessage());
      throw $e
    }
     catch (ApiExcetpion $e) {
       somelogic();
       throw $e;
     }
  }


}

My main concern with this approach is that there is a lot of redundancy in writing try/catch blocks. For every composite method there will be try catch block.

Solution #2 Throw errors in a Model, and handle rollbacks/logging etc in a controller. This one I don't like because it breaks MVC pattern, and a controller becomes fat.

Solution #3 Binding error-listeners to an app instance so that they will handle exceptions according to their logic. Example:

class ExampleModel {
  //some field
  //constructor and getters with setters

  public function save() {
    $db->beginTransaction();
    $db->somequery();
    $db->anotherone();
    $object->externalApiCall();
    $object->saveToCache();
  }


}

$app->bind_error_handler("DbTransactionException", function () {
     rollback();
     log();
     return View::render("some error");
});

I overall like this approach because there are no numerous try/catch blocks. Controller is skinny and error logic is de-coupled from everything else. My concern with last approach is whether or not it is considered best practice. Also is this approach flexible and will it give me flexibility of a first approach?

Overall question: What is considered best practice in handling errors (transactional and other) in MVC world? And which solution from what I have provided is the best one?

Aucun commentaire:

Enregistrer un commentaire