【发布时间】:2009-03-16 18:31:39
【问题描述】:
我正在从 php 中的普通 mysql 切换到 PDO,我注意到测试错误的常用方法是使用 try / catch 组合而不是 if / else 组合。
该方法的优点是什么,我可以使用一个 try / catch 块而不是几个嵌套的 if / else 块来处理不同步骤(连接、准备、执行等)的所有错误吗?
【问题讨论】:
我正在从 php 中的普通 mysql 切换到 PDO,我注意到测试错误的常用方法是使用 try / catch 组合而不是 if / else 组合。
该方法的优点是什么,我可以使用一个 try / catch 块而不是几个嵌套的 if / else 块来处理不同步骤(连接、准备、执行等)的所有错误吗?
【问题讨论】:
我会使用 try/catch 块,当通过代码的正常路径应该正常运行时,除非确实有一些异常情况——比如服务器关闭、您的凭据过期或不正确。我不一定会用它来处理非异常错误——比如当前用户没有担任正确的角色。也就是说,当您可以合理地预期并处理非异常情况的错误时,我认为您应该进行检查。
在您所描述的情况下 -- 设置和执行查询,try/catch 块是处理它的好方法,因为您通常期望查询成功。另一方面,您可能希望通过控制流逻辑检查结果的内容是否符合您的预期,而不是仅仅尝试使用可能对您的目的无效的数据。
您要注意的一件事是草率地使用 try/catch。 Try/catch 不应该用来保护自己免受不良编程的影响——“我不知道如果我这样做会发生什么,所以我将把它包装在 try/catch 中并希望最好的”类型的编程。通常,您会希望将捕获的异常类型限制为与代码本身无关的异常(服务器关闭、凭据错误等),以便您可以找到并修复与代码相关的错误(空指针等) .)。
【讨论】:
一般来说,try-catch 块非常棒,因为只要发生异常,它们就会中断(移动到 catch 语句)。 if-else 块依赖于您预测错误何时发生。
编辑: 此外,catch 块不会阻止您的代码在遇到错误时停止。
【讨论】:
try/catch 和一般异常的优势更多地适用于开发库(如 PDO)的人。它们允许系统开发人员以快速简单的方式处理未定义的情况或意外结果。建立数据库连接。如果无法访问数据库,系统应该做什么。它应该停止执行吗?再试一次?发出警告并继续?系统开发人员不知道你需要它做什么,他们会抛出一个异常,你稍后会捕获并处理它。
对您来说,作为系统的使用者,您的优势是,您不会得到一些模糊的错误代码,或者一个简单的布尔值 false 表明它失败了,而是会得到一个 Exception 对象
以这样一种方式命名,以便更明显地出错(如果我没记错的话,PDO 只有一种异常类型,但其他系统包含针对不同类型错误的多种异常类型)
可能/应该包含可以帮助您找出为什么引发异常的方法和属性
无论如何,这就是理论。有很多聪明的人声称例外是要走的路。也有很多聪明人认为异常是魔鬼,是懒惰的系统开发者的拐杖。在这个问题上没有任何类似的共识。
【讨论】:
与大多数其他原始操作相比,抛出和捕获异常是一项昂贵的操作。如果这是一段需要良好执行的代码(例如,在一个紧密的循环中),您将需要查看您的用例 - 如果您希望相对频繁地抛出异常,那么使用 if 会更好/else 性能方面(除非底层代码只是为您包装了一个异常,在这种情况下根本没有任何收益)。如果仅在极少数情况下抛出异常,那么最好使用 try/catch 以避免在紧密循环中分支的开销。
【讨论】:
@Perchik:
我的错误处理的一般理念:
您应该使用 if / else 来处理您期望的所有情况。您应该不使用 try {} catch {} 来处理所有事情(在大多数情况下),因为可能会引发有用的异常,并且您可以从它。您应该在您怀疑某些事情可能/将会出错并且您不希望它导致整个系统崩溃的情况下使用 try {} catch {},例如网络超时/文件系统访问问题,文件不存在等
【讨论】:
Try/Catch 将错误处理逻辑与对象业务逻辑完全分离。
【讨论】:
这正是优点,使用一个 try/catch 而不是多个 if 语句。您还可以捕获任何未预料到的错误。
【讨论】:
其他人都有很好的答案 - 但我想我会自己回答:
【讨论】:
由于 PDO 使用对象,因此如果发生错误,它们会引发异常。旧的 mysql/mysqli 只是函数,不会抛出异常,它们只是返回错误代码。当可以从代码中抛出异常时使用 Try/catch,并且您在 catch 子句中捕获它,这是一种处理错误的面向对象的方式。您无法使用 if/else 块捕获异常 - 它们与 try/catch 不共享任何内容。
【讨论】:
在php中使用带有继承的Try Catch,我们可以从另一个类中抛出异常。
示例:- 我在 controller 并使用 Models 验证用户数据。
如果触发任何错误,我只需从 Model 方法中抛出异常。
try 中的执行会中断并被Catch 块捕获。
所以返回布尔值和检查的开销更少。
除了这个 Try Catch 在链中使用时效果很好(Try - Catch 在另一个 Try - Catch 中)。
【讨论】:
这个问题已经在十多年前提出了错误的前提。实际上,如果和尝试是无法比拟的。可悲的是,直到今天,人们灾难性地将 exceptions 与 try catch 混为一谈,认为两者密不可分。
在询问的方式中,实际上将 if {} 更改为 try {} 的含义是强制尝试包装单行代码以测试错误,这几乎没有意义。
但实际的问题是 使用 exceptions 与 if {} else {} 相比有什么优势。
它立即开始变得有意义:异常允许自动错误报告,当不需要编写 try catch 或 if else 时。
异常本质上是一种自动方式来编写if ($result == FALSE) raise_error(); 没有异常,您必须手动测试每个操作的结果。使用异常重新创建相同的行为只是愚蠢的。在大多数情况下,应该不理会抛出的异常,除非有特定的处理场景。在所有其他情况下,它必须在其他地方冒泡,因此 不需要编写 try {} catch {}。
【讨论】:
假设我们正在编写一个 a/b 除法代码,并且发生了最著名的异常情况,即 0 除法错误,您认为接下来可以做什么? 1.您可以打印一条消息并退出。 2.您可以打印一条消息并让用户重新输入值等。
在某些情况下,不同的人/供应商希望以不同的方式处理相同的异常情况。 catch 块让他们轻松地做到这一点。如果您需要更改处理某个异常情况的方式,您只需要更改 catch 块。
【讨论】:
TRY/CATCH 可以在您对错误信息知之甚少的编程环境中使用,或者您认为可能会发生诸如此类的错误。
#include <iostream>
using namespace std;
int main (){
try{
while(true){
new int[100000];
}
}
catch(bad_alloc& e){
cout << e.what() << endl;
}
}
虽然程序中没有语义或编译时错误,但可以理解的是它存在运行时错误“bad_alloc”,当您尝试连续分配内存并且程序耗尽内存时会出现.该异常定义在 bad_alloc 标准类中,它是类“Exception”的子类,因为它抛出一个隐式异常,所以这里没有隐含 throw 关键字。
你也可以使用try/catch来检查文件是否被误删除,也可以使用if/else来检查文件是否存在,两者各有优势。
【讨论】:
当函数之间有通信时,Try 和 Catch 函数很有用。在 Try 和 Catch 中,如果 TRY 块中存在异常,则控制将直接转移到 CATCH 块,该块将存储我们的异常条件。然而,这在 IF ELSE 的情况下是不可能的,在 IF 条件下,如果存在异常,无论如何控制都不能转到 ELSE 块。
int division(int a,int b){
if(b==0)
throw 101;
return a/b;
}
int main()
{
int a=10,b=0,c;
try{
c=division(a,b);
cout<<c<<endl;
}
catch(int a){
cout<<"Division not possible by 0"<<endl;
}
}
考虑以下代码: throw 和 catch 函数用于函数划分和主函数之间的通信。 请注意,当 b 为 0 时,不执行打印 c 的语句,因为在抛出值 os 后,控件直接转移到 catch 块。 然而,如果这里是 IF ELSE,这是不可能的。
【讨论】: