2011-11-11 58 views
7

当引入新的异常类型时,我总是不确定如何正确执行此操作。有一个共同的约定吗?你怎么做呢?你如何命名和组织你的例外?

我感兴趣的范围,你组织他们(让他们在他们的?使用的单位有一个单元组件级别?包级别?应用程序?)

这也影响了命名。你包含多少上下文?让它们非常具体(比如EPersonIDNotFoundError)还是试图让它们可重用(比如ENotFoundError)更好?

那么后缀“错误” - 什么时候应该添加它,什么时候离开它?我看不到逻辑例如在Classes.pas

EWriteError = class(EFilerError); 
    EClassNotFound = class(EFilerError); 
    EResNotFound = class(Exception); 
+0

我认为按严重程度和每个包来组织异常是很好的做法。按严重程度例如。从数据加载/保存错误中分离验证异常。例外情况可以包含更多关于发生情况的具体细节。 – too

+1

这不是一个问题......一次出现太多问题,有一些潜在的争议(拖延?)。恕我直言,这不适合SO目的。 –

+0

@Arnaud好吧,让我试着回答这个问题。因为我非常欣赏这个输入。 –

回答

6

我所知道的唯一真正的约定,是E前缀他们。 我过去并没有真正考虑过它,但现在我想起来,在我看来,ErrorException通常被用作后缀。如果你把它们混合在一起,我会说Exception涉及意想不到的错误,比如断开的连接,或者文件变得不可读,而错误更多地与错误的输入有关,例如一个数字是预计,但有人键入文字。

的VCL似乎遵循一定的约定过,但它似乎增加一个后缀,只有当它不会是明确和错误,没有它,例如

EConvertError,EMathError,EVariantError

VS

EAccessViolation,EInvalidPointer,EZeroDivide

后者描述错误本身,其中所述第一列表需要后缀来指示在特定过程或实体错误。

这些例子可以在SysUtils中找到,也许你可以看看那里,因为它包含了许多异常类以及更多的异常的基类。在Exception中很少有这样的结果,除了一些非常特殊的错误,你确实希望永远不会遇到,比如EHeapException和ESafecallException。

+0

当错误消息本身非常好地传输故障条件时,跳过“错误”的好处。你是否混合了“Exception”和“Error”? –

+1

我很少使用“错误”,尽管我可能从现在开始,因为这个问题让我想到了它。但我通常不会引入大量的异常类型。我倾向于创建一些基础应用程序级别的例外,并且我(重新)使用了很多现有的例外。如果我无法转换某个值,我很高兴为它使用EConvertError,并且我自己的列表/数组/集合实现可以轻松地重用它所调用的EListIndexError。我当然不会为每个未找到的字段创建单独的例外。 – GolezTrol

1

创建一个新的异常时,我把它变成了应用程序范围。我从最详细的错误开始到最一般的错误,比如类(Exception),并且我相应地命名它们。

因此,在您的示例中,我会使用EPersonIDNotFoundError,ENotFoundError,Exception。

这真的取决于你从你的错误消息多少细节要和你包括你的日志(如果连续记录错误)

1

通常为简单的应用程序,你可以用Exception.Create脱身( '错误信息')。如果异常变得强大,就可以通过查看课程来检测所需的响应类型。 Delphi已经通过Abort过程来完成这个操作,这会引发EAbort。 EAbort是'特殊的',因为它不会触发'错误',因为它是一种'沉默'异常。您可以使用此特定于类的操作来检查异常并执行其他操作。您可以创建一个EMyWarning,EMyVeryNastyError等等,每个都来自基本的Exception类型。此外,您可以定义一个新的异常类,以将更多信息输出到异常被捕获的位置。例如与代码(未选中):

EMyException = class(Exception) 
    constructor Create(const AErrorMessage : string; AErrorCode : integer); reintroduce; 
PUBLIC 
    ErrorCode : integer 
end; 

constructor EMyException.Create(const AErrorMessage : string; AErrorCode : integer); 
begin 
    inherited Create(AErrorMessage); 
    ErrorCode := AErrorCode; 
end; 

你现在有当你抛出异常设置“错误代码”的可能性,你拥有了它提供的异常被捕获时。例外非常强大。

+0

不是真正的问题答案,而是首先为什么要从Exception继承的好例子。我喜欢EAbort。 :)你可以放弃这么多事情。例如,通过在OnBeforePost中创建一个EAbort以及许多类似的中断来中止发布记录。我也用它来放弃复杂的操作。 – GolezTrol

1

在哪个范围内组织它们?

使用一个单位的整个应用程序,你试图适应最普遍的例外。其他一切都进入抛出异常的单位。如果您在其他单元中需要这些例外,请将它们移动到您正在使用的子系统使用的公共单元。

如何命名?

尝试使一个或两个“一般”例外级别,如ENotFoundError。将这些放在应用程序全局文件中。不要过于努力地推广,因为你不知道什么异常会在以后要求你改变一切。在全球范围内创建单元级别的特殊异常。

怎么样“错误”后缀?

别再想它了。 Add it.除非它听起来很愚蠢。

+2

如果代码使用接口很多,我会在声明接口的单元中声明异常,而不是在引发它们的实现代码中声明 – mjn

+1

@mjn绝对如此。否则,接口的用户不能对异常类进行特定的检查而不会依赖于实现者... –