3

关于函数调用,是让调用者负责检查函数是否工作或失败,还是应该由函数本身宣布错误?

我问的原因是因为我不喜欢将演示文稿与逻辑混合,但是如果调用者必须进行错误检查,则它可能不准确且很麻烦,例如。

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

调用者不知道为什么失败。是用户名/密码组合错误,还是数据库连接失败?还是其他一些意想不到的原因?

如果我们可以在函数内部进行错误检查/抛出异常,这将不是问题,因为这样我们就会在特定的代码点出现特定的错误,例如数据库连接失败……但这将混合表示和逻辑。这里的最佳做法是什么?

谢谢你。

4

3 回答 3

2

我个人会通过在业务逻辑(模型)层中抛出异常来赋予调用者责任。然后,可以在控制器中捕获异常(并将错误分配给视图中的变量)。有些人甚至喜欢直接在表示层捕获异常,但这不适用于 Web 开发的情况。只要异常仅用于视图中的演示目的,我认为这不是什么大问题。

因此,我不会像您在简单示例中那样做,因为调用者可能并不总是希望显示错误。通过处理呼叫者的责任,他或她有一个选择。此外,我不喜欢在业务逻辑中回显内容(我更喜欢抛出异常并保持模型不显示),但您的代码很可能只是一个过于简单的示例。

编辑:你可以这样做:

模型:

function login($username, $password) {
    if (login failed) {
        throw new Login_Exception();
    }

    else {
        // Set session
        return true;
    }
}

控制器:

try {
    $model->login($username, $password);
}

catch (Login_Exception $e) {
    $view->loginError = 'There was an error logging in.';
}

然后,您可以抛出不同的异常来准确指出哪里出了问题(例如Wrong_Username_Exception)并相应地处理它。或者,您甚至可以在异常的构造函数中提供一个用户友好的理由,但在我看来,这会使表示和逻辑耦合得过多。

于 2012-09-03T13:00:10.180 回答
1

您的示例代码的问题:

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

...是 login() 函数没有返回足够的信息供调用者使用。无论调用者是 Web 表示层还是其他东西,这都是一个问题。

更好的 login() 函数可能会返回一个对象,以便调用者可以执行以下操作:

$response = login($username, $password);
if(! $response->isLoggedIn()) {
    echo "Login failed. " +  $response->getErrorMessage();
}

现在您的登录方法与用户界面没有紧密耦合,但您可以将登录失败的原因传递给用户。

现在,可以说 login() 方法中仍然存在“表示”,因为它返回的文本是逐字引用给用户的。如果您想更加松散耦合,您可以定义一个错误代码列表,并让您的表示层将它们转换为消息。或者您可以返回一个指向消息表的值。阅读国际化;这是相同的基本域。

于 2012-09-03T13:13:10.117 回答
0

第一个。调用者应该有错误检查的责任。如果您想知道发生了什么样的错误,您可以重写登录函数并添加第三个参数,该参数将包含对错误的引用,如下所示:

<?php
function login($user, $pass, &$error) {
    // if user or pass wrong
    $error = 'Username / pass wrong';

    // if db failed
    $error = 'unable to connect to db'
};

if(!login($user, $pass, $error)) {
    // do whatever you want with the error
}

更好的是,您可以将常量用于错误类型

更新

如果您在调用该函数后设置会话或 cookie,则您不希望显示该函数的错误。它会变薄,您会收到如下通知:“标头已发送......”

于 2012-09-03T12:58:26.173 回答