문제

I can't get my head around WHEN to throw and catch exceptions for when I call functions from classes.

Please imagine that my QuizMaker class looks like this:

// Define exceptions for use in class
private class CreateQuizException extends Exception {}
private class InsertQuizException extends Exception {}

class QuizMaker()
{

    // Define the items in my quiz object
    $quiz_id = null;
    $quiz_name = null;

    // Function to create a quiz record in the database
    function CreateQuizInDatabase()
    {

        try
        {

            $create_quiz = // Code to insert quiz

            if (!$create_quiz)
            {
                // There was an error creating record in the database
                throw new CreateQuizException("Failed inserting record");
            }
            else
            {
                // Return true, the quiz was created successfully
                return true;
            }

        }
        catch (CreateQuizException $create_quiz_exception)
        {
            // There was an error creating the quiz in the database
            return false;
        }
    }

    function InsertQuestions()
    {
        try
        {
            $insert_quiz = // Code to insert quiz

            if (!$insert_quiz)
            {
                // There was an error creating record in the database
                throw new CreateQuizException("Failed inserting quiz in to database");
            }
            else
            {
                // Success inserting quiz, return true
                return true;
            }
        }
        catch (InsertQuizException $insert_exception)
        {
            // Error inserting question
            return false;
        }
    }
}

... and using this code, I use the class to create a new quiz in the database

    class QuizMakerException extends Exception {}

try
{
    // Create a blank new quiz maker object
    $quiz_object = new QuizMaker();

    // Set the quiz non-question variables
    $quiz_object->quiz_name = $_POST['quiz_name'];
    $quiz_object->quiz_intro = $_POST['quiz_intro'];
            //... and so on ...

    // Create the quiz record in the database if it is not already set
    $quiz_object->CreateQuizRecord();

    // Insert the quiz in to the database
    $quiz_object->InsertQuestions();

}
catch (QuizMakerException $quiz_maker_error)
{
    // I want to handle any errors from these functions here
}

For this piece of code, I want to call a QuizMakerException if any of the functions don't perform what I want them to (at the moment they return TRUE or FALSE).

What is the correct way to go about catching when any of the functions in this code does not perform what I want them to? At the moment they simply return TRUE or FALSE.

  • Do I really have to put lots of if/else statements between calling each function, I thought that was the whole point in exceptions, they simply halt the execution of further statements within the try/catch?
  • Do I throw a QuizMakerException from within the catch of my functions?

What is the right thing to do?

Help!

도움이 되었습니까?

해결책

Well typically in the function which throws the exception, say your InsertQuestions method, you don't want to catch any exceptions, you want to throw them or let ones occurring to "bubble up". Then your "controller" code can make the determination of how to handle the exception.

If your goal here is to halt if CreateQuizRecord fails I would wrap CreateQuizRecord and InsertQuestions each in their own try block.

One advantage of exceptions is they can tell you more than a simple bool pass/fail. Either extending your base exception into things like "Invalid_Parameter" and testing for specific exceptions or -less ideally- inferring from properties of the exception. You can nest your catch blocks to handle exceptions individually.

Do I throw a QuizMakerException from within the catch of my functions?

Yes. Typically your code under // Code to insert quiz would itself return an exception. Say if the Model failed to insert it might be raising a database exception. In which case you can let that database exception bubble up, or do what you sort of doing now and catch it simply to in turn throw another exception (kinda dumbs down your exceptions in a way, doing that though).

Do I really have to put lots of if/else statements between calling each function, I thought that was the whole point in exceptions, they simply halt the execution of further statements within the try/catch?

I look at it like this, each call which throws an exception and is followed by a subsequent call which depends on this one not throwing any exceptions, should be wrapped in a try block. Assuming you want to handle it gracefully, if you simply want it to error out and halt just don't handle the exception. You'll get an error and stack trace. Sometimes that is desirable.

다른 팁

You might want to change the structure a bit. Your class QuizMaker can become:

<?php

// Define exceptions for use in class
public class CreateQuizException extends Exception {}
public class InsertQuizException extends Exception {}

class QuizMaker()
{

    // Define the items in my quiz object
    $quiz_id = null;
    $quiz_name = null;

    // Function to create a quiz record in the database
    function CreateQuizInDatabase()
    {

        try
        {

            $create_quiz = // Code to insert quiz

            if (!$create_quiz)
            {
                // There was an error creating record in the database
                throw new CreateQuizException("Failed inserting record");
            }
            else
            {
                // Return true, the quiz was created successfully
                return true;
            }

        }
        catch (Exception $create_quiz_exception)
        {
            // There was an error creating the quiz in the database
            throw new CreateQuizException(
                "Failed inserting record " . 
                $create_quiz_exception->getMessage()
            );
        }
    }

    function InsertQuestions()
    {
        try
        {
            $insert_quiz = // Code to insert quiz

            if (!$insert_quiz)
            {
                // There was an error creating record in the database
                throw new InsertQuizException("Failed inserting quiz in to database");
            }
            else
            {
                // Success inserting quiz, return true
                return true;
            }
        }
        catch (Exception $insert_exception)
        {
            // Error inserting question
            throw new InsertQuizException(
                "Failed inserting quiz in to database " . 
                $create_quiz_exception->getMessage()
            );
        }
    }
}

Effectively, if you cannot insert the record correctly, you throw an Insert exception. If anything goes wrong with that block of code, you catch it and throw again an Insert exception. Same goes with the Create function (or any other ones you might have).

In the main block of code you can have:

try
{
    // Create a blank new quiz maker object
    $quiz_object = new QuizMaker();

    // Set the quiz non-question variables
    $quiz_object->quiz_name = $_POST['quiz_name'];
    $quiz_object->quiz_intro = $_POST['quiz_intro'];
            //... and so on ...

    // Create the quiz record in the database if it is not already set
    $quiz_object->CreateQuizRecord();

    // Insert the quiz in to the database
    $quiz_object->InsertQuestions();

}
catch (InsertQuizException $insert_exception)
{
    // Insert error
}
catch (CreateQuizException $create_quiz_exception)
{
    // Create error
}
catch (Exception $quiz_maker_error)
{
    // Any other error
}

If you don't want to have the multiple catch block there, just keep the catch(Exception) one and then check in it the type of each exception thrown to specify the actions taken from there.

HTH

The best thing to do is to not have to thhrow exceptions in the first place. Exceptions are thrown when the program crashes and they are not made to handle wrong output. If your function returns anything (even its the wrong thing) it doesn't need an exception.

To answer your question, if it's necessaryto use a lot of ifs/elses then you must use them.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top