Search code examples
phperror-handlingseparation-of-concerns

Errors - Do they belong in the logic, or the presentation layer?


Regarding function calls, is it better to give the caller the responsibility of checking if a function worked or failed, or should the error be announced by the function itself?

The reason I'm asking is because I don't like mixing presentation with logic, however if the caller has to error-check, it can be inaccurate and cumbersome eg.

if(!login($username, $password)
{
    echo 'Login failed. Please try again.';
}

The caller has no idea why it failed. Was the username/password combo wrong, or was it a database connection failure? Or some other unexpected reason?

This would not be a problem if we can error check/throw exceptions inside the functions, because then we would have specific errors at specific points of code eg database connection failures...but that would be mixing presentation and logic. What is the best practice here?

Thank you.


Solution

  • I would personally give the caller the responsibility by throwing an exception in the business logic (model) layer. Then, the exception can be caught in the controller (and the error assigned a variable in the view). Some people even like to catch exceptions directly in the presentation layer, but this does not apply well in the case of web development. As long as the exception is only used for presentation purposes in the view, I don't consider it much of a problem, though.

    So, I would not do as you did in your simple example, because the caller may not always want an error to be displayed. By handling the responsibility to the caller, he or she has a choice. Also, I don't like echoing content in the business logic (I prefer to throw exceptions and keep the models clean from presentation), but your code was most likely just an oversimplified example.

    Edit: You could do something like this:

    Model:

    function login($username, $password) {
        if (login failed) {
            throw new Login_Exception();
        }
    
        else {
            // Set session
            return true;
        }
    }
    

    Controller:

    try {
        $model->login($username, $password);
    }
    
    catch (Login_Exception $e) {
        $view->loginError = 'There was an error logging in.';
    }
    

    You can then throw different exceptions to indicate exactly what went wrong (e.g. Wrong_Username_Exception) and handle it accordingly. Alternatively you could even provide a user friendly reason in the exception's constructor, but in my opinion that would be coupling presentation and logic a little too much.