例外 - 什么是“例外”?

问题描述:

我读过的例外情况不应该用于指导应用程序的流程,但应该用于在出现“异常”情况时将应用程序恢复到稳定状态,例如,当您无法连接到数据库时。例外 - 什么是“例外”?

不应使用例外的例子是提供不正确登录的用户。这不会是一个例外,因为它预计会发生。

我不知道下面的情况是例外与否:

我目前正在设计一个简单的博客。 “职位”仅分配给一个“类别”。在我的帖子表中,我有一个带有外键约束的category_id字段。

现在,我使用Laravel,所以如果我尝试删除当前有帖子的类别,我相信它应该会因为外键约束而抛出\ Illuminate \ Database \ QueryException。所以我应该靠这个,写这样的代码:

try { 
    $category->delete(); 
} 
catch (\Illuminate\Database\QueryException $e) { 
    // Tell the user that they can't delete the category because there are posts assigned to it 
} 

或因为我知道我多么希望我的博客的工作,我应该使用:

if ($category->posts->isEmpty()) { 
    $category->delete(); 
} 
else { 
    // Tell the user they can't delete... 
} 

任何意见,将不胜感激。谢谢!

+2

我认为这主要是基于舆论,但我会选择第二个选项。为什么? 1.规则明确。 2.其他类型的数据库异常不会产生误导性的错误。 3.如果有人打开级联删除,您的逻辑仍然运行相同。 –

+1

继续@ DarkFalcon的回答,抛出异常是一个更重的操作,所以你应该只使用它,以防你真的不能发生某些事情。 –

这是非常基于意见的,所以我给你我的意见: 例外是强大的,因为你可以附加大量的信息 - 你可以发送它们“调用堆栈”而不需要使用方法检查任何呼叫的返回值并将其返回给自己的呼叫者。

这可让您轻松处理调用堆栈中所需图层的错误。

一个方法应该返回,什么是调用的结果(即使它是无效的)。如果因任何原因致电失败,应该有没有返回值。

错误不应通过返回值运输,但有例外。

想象一下执行db-queries的函数:KeyAlreadyExistsException,InvalidSyntaxExceptionNullPointerException - 很可能你想在你的代码中非常不同的部分处理这个“错误”。

(一个是一个代码错误,一个是查询错误,一种是逻辑错误)

例一,方便“处理”:

try{ 
    method1(1); 
}catch (Exception $e){ 
    //Handle all but NullpointerExceptions here. 
} 
--- 
method1($s){ 
    try{ 
    method2($s+2); 
    } catch (NullPointerException $e){ 
    //only deal with NPEs here, others bubble up the call stack. 
    } 
} 
--- 
method2($s){ 
    //Some Exception here. 
} 

例二 - 你看所需的“嵌套”,堆栈深度仅为2。

$result = method1(1); 
if ($result === 1){ 
    //all good 
}else{ 
    //Handle all but NullpointerExceptions here. 
} 
--- 
method1($s){ 
    $result = method2($s+2); 
    if ($result === 1){ 
    return $result; 
    }else{ 
    if ($result === "NullPointerException"){ 
     //do something 
    } 
} 

method2($s){ 
    //Exception here. 
} 

特别是进行维修,异常具有巨大的优势:如果您添加了新的“异常” - 最坏情况下将是一个未处理的异常,但是代码的执行将中断。

如果要添加新的“返回错误”,您需要确保,每一个来电知道这些新的错误:

function getUsername($id){ 
    // -1 = id not found 
    $name = doQuery(...); 
    if (id not found) return -1; 
    else return $name; 
} 

VS

function getUsername($id){ 
    $name = doQuery(...); 
    if (id not found) throw new IdNotFoundException(...); 
    return $name; 
} 

现在考虑在这两个处理案例:

if (getUsername(4)=== -1) { //error } else { //use it } 

VS

try{ 
    $name = getUsername(4); 
    //use it 
}catch (IdNotFoundException $e){ 
    //error 
} 

现在,您添加返回码-2:第一种方法将假设用户名为-2,直到实现错误代码。第二种方法(另一个异常)会导致执行停止,并在调用堆栈的某处出现未处理的异常。

处理错误传输的返回值(任何类型)是容易出错的,错误可能在某处消失,变成“错误的”解释结果。

使用异常是安全的:要么你必须使用一个返回值,或者(处理或未经处理的)异常,但没有“错误的价值观”由于autocasts等