【发布时间】:2010-08-22 15:39:00
【问题描述】:
在编写 Perl 模块时,在模块内部使用 croak/die 是一个好习惯吗?
毕竟,如果调用者不使用 eval 块,模块可能会使调用它的程序崩溃。
在这些情况下,最佳做法是什么?
【问题讨论】:
在编写 Perl 模块时,在模块内部使用 croak/die 是一个好习惯吗?
毕竟,如果调用者不使用 eval 块,模块可能会使调用它的程序崩溃。
在这些情况下,最佳做法是什么?
【问题讨论】:
如果您要指出某种错误,我通常更喜欢例外。否则,您必须花费更多时间在代码库的不同级别上散布错误处理代码,而不是将错误处理集中在系统的适当层中 - 除其他原因外。
您可能会发现此old thread on perlmonks 很有用。我将在下面复制我的评论 - 因为我大多同意我当时写的内容:-)
我喜欢例外的一些原因:
稳健性。我可能忘记检查返回的错误值。我不能忘记检查异常。
简洁。我更喜欢:
$o->foo->bar->fribble->ni
到
$o->foo or return(ERROR_FOO);
$o->bar or return(ERROR_BAR);
$o->fribble or return(ERROR_FRIBBLE);
$o->ni or return(ERROR_NI);
清晰。对于基于异常的代码,“正常”的控制流程更加明确,因为它不会被错误处理代码所掩盖。我认为上面两个代码示例中的第一个比第二个更直接地显示了代码的意图。
关注点分离。错误条件和错误处理程序是不同的想法。
您可能希望根据上下文以不同的方式处理错误。
您可能还不知道在错误发生时应如何处理。
您可能在编写代码时不知道应该如何处理错误。
使用 return-error-code 样式,您最终不得不:
将错误条件传播到可以决定如何处理它们的位置。
将错误处理程序传播到可能发生错误的位置
如果在错误条件和错误处理程序之间有许多级别的代码,这两个选项都会很快变得混乱。
返回值和错误条件之间没有混淆。
可能还有更多 ;-)
【讨论】:
至少在生产的早期阶段,我喜欢有很多 throw 例外(早早死掉的座右铭)。所以我可以快速发现任何错误(并为您节省大量时间,避免思考逻辑和跟踪返回码)。然后在每次发布迭代中,我可以降低将它们与 $o->debug 状态相关联的抛出的严重性。所以当你运行你的测试时,一切都死了,但是当你运行你的代码时,真正的呱呱叫到日志中,只有在不可避免的致命情况发生时才会死。在我看来,这比我过去使用的返回代码更灵活。
另外,一个简单的“死”异常有时也不是很有用,所以最好有一个 throw 函数来打印所有调用堆栈跟踪(如 Carp->confess()|cluck())。
一个好的捕捉机制也很方便。使用Try::Tiny 或TryCatch。
PD:adrianh 指出的 perlmonk 线程是经典的。
【讨论】: