0

我已经看到一些关于这个主题的问题,但我认为除了最基本的示例之外,我更根本地缺乏如何最好地使用 try/catch 块。

在这个特定的案例中,我有一系列的技术来解决一个问题,从简单到相当复杂,我的想法是这样的:

if ($zombie_killer -> board_with_nail == 'failed') {
    if ($zombie_killer -> machette == 'failed') {
       if ($zombie_killer -> shotgun == 'failed') {
           $this -> panic;
       }
    }
}

但相反,我认为使用 try/catch 块可能是一种更好的方法,以便有更多空间添加自定义子流程,例如记录该技术为何不起作用,更新 UI 以反映“a比平时更长的保持时间”,或者其他什么。所以我想它会是这样的:

try {
    $zombie_killer -> board_with_nail;
}
catch(Exception $e) {
    try {
        $zombie_killer -> machette;
    }
}

但这感觉并没有好多少,鉴于其他人对“if/else vs try/catch”的所有反响,我很清楚,至少,有很大的差异和使用它们的理由. 这就是为什么我要询问这个用例的原因,因为我觉得最好通过 try/catch 来处理它,但不知道它是否感觉不对,因为我没有真正使用它们或者因为我没有正确地接近这个。

4

3 回答 3

0

The philosophy of try/catch isn't the one you described. The good way to use it is to catch different exceptions depending of what error happened. For example:

try {
    $value = readDatabase();
    writeDatabase($++value);
} catch (ReadErrorException $e) {
    // do something
} catch (WriteErrorException $e) {
    // do something
}

If you want to achieve what you're looking for, you can do as simple as using and, if you don't need more code. If you do, just use elseif.

For example, your code could become:

if (
    $zombie_killer -> board_with_nail == 'failed'
    && $zombie_killer -> machette == 'failed'
    && $zombie_killer -> shotgun == 'failed'
) {
    $this -> panic;
}

Also, the good way would be, using booleans as attributes:

if (
    !$zombie_killer -> board_with_nail
    && !$zombie_killer -> machette
    && !$zombie_killer -> shotgun
) {
    $this -> panic;
}

EDIT: After reading your comments on other answers

I propose you an alternative solution, based on what you said. Understanding that $zombie_killer is a class, you could create a public method named, for example, kill(). This method can access the public, private and protected attributes of the class.

I will write an example without exceptions first.

Inside the class:

public function kill()
{
    if ($zombie_killer -> board_with_nail != 'failed') return true;
    if ($zombie_killer -> machette != 'failed') return true;
    if ($zombie_killer -> shotgun != 'failed') return true;

    return false;
}

In the other file, the one we were talking about:

if (!$zombie_killer->kill()) {
   $this->panic;
}

As you can see, the code is more clean, and the default behaviour of the function is suppose that the zombie won't be killed, and the exceptional cases would be if one of the methods used to kill the zombie succeeds. It's the opposite as how we would normally think: we would suppose we could kill the zombie, and the exceptional case would be if everything failed. But it's just a philosophical issue, you can reverse the code and it would still work.

Let's see the same with exceptions.

Class file:

public function kill()
{
    if (
        $zombie_killer -> board_with_nail == 'failed' 
        && $zombie_killer -> machette == 'failed'
        && $zombie_killer -> shotgun == 'failed'
    ) {
        throw new NotKilledException();
    }
}

Other file:

try {
    $zombie_killer->kill();
} catch (Exception $e) {
    $this->panic;
}

So, you see? The exception version isn't of much help in this case, because you still must do the nested if, because the condition must accomplish three different types of kills failed. The exception is to not kill the zombie. Because you want the exceptional code $this->panic to be executed.

Now, you must choose what kind of implementation fits you more. The both are correct, and developers will see it right both. I would choose though, the first one, cause with a simple copy paste you could add more killing types to your zombie_killer, and it's cleaner to read.

于 2012-08-07T10:04:12.150 回答
0

As a personnal point of view, I think that, unlike if/else, try/catch are there to handle exceptions, not use cases, so they are better used for that, not for handling what you want to do depending on a situation.

于 2012-08-07T10:05:33.597 回答
0

异常不是表示条件语句的替代方法。例外是,好吧,特殊情况,比如试图用枕头杀死僵尸:

function kill_zombie($weapon) {
    if (!$weapon instanceof FireArm && !$weapon instanceof HeavyObject)
        throw new Exception("Zombies can only be killed with firearms and heavy objects");
    // ...
}
于 2012-08-07T10:13:54.357 回答