Exception handling: Contract vs Exceptional approach我知道两种处理异常的方法,让我们来看看它们。 合同方式。 当某个方法不执行其在方法标头中将要执行的操作时,它将引发异常。因此,该方法"承诺"它将执行该操作,并且如果由于某种原因而失败,则将引发异常。 出色的方法。 仅当发生真正奇怪的事情时才抛出异常。当您可以使用常规控制流(If语句)解决问题时,不应使用异常。您不会像在合同方法中那样将异常用于控制流。 让我们在不同情况下使用两种方法: 我们有一个Customer类,该类具有一种称为OrderProduct的方法。 合同方式:
特殊方法:
在这里,我更喜欢采用特殊的方法,因为如果客户没有赢得彩票,他就没有钱并不是真正的例外。 但是,我在合同风格上存在这种情况。 极好:
当我调用一个名为CreateCar的方法时,我该期望一个Car实例而不是一些糟糕的null指针,后者可能会在十行之后破坏我正在运行的代码。因此我更喜欢合同:
您使用哪种风格?您认为对异常的最佳通用方法是什么? 我赞成您所说的"合同"方法。在支持异常的语言中,无需返回null或其他特殊值以指示错误。当代码中没有很多" if(result == NULL)"或" if(result == -1)"子句以及非常简单,直接的逻辑时,我发现代码更容易理解。 我通常的方法是使用合同来处理由于"客户端"调用(即由于外部错误(即ArgumentNullException))引起的任何类型的错误。 参数上的每个错误都不会处理。引发异常,由"客户端"负责处理。另一方面,对于内部错误,请始终尝试更正它们(就像由于某种原因而无法获得数据库连接一样),并且只有在您无法处理它时才引发异常。 重要的是要记住,客户端始终无法处理此类级别的大多数未处理的异常,因此它们很可能会由最通用的异常处理程序处理,因此,如果发生此类异常,则无论如何您都可能是FUBAR。 两种方法都是正确的。这就是说,应该以这样一种方式来写合同:对于并非真正例外的所有情况,都指定不需要抛出异常的行为。 请注意,根据代码调用者的期望,某些情况可能会或可能不会例外。如果呼叫者期望字典中将包含某个项目,而没有该项目则表示存在严重问题,则找不到该项目是一种特殊情况,并且应引发异常。但是,如果调用者实际上不知道某个项目是否存在,并且同样准备处理该项目的存在或不存在,则该项目的缺失将是预期的情况,并且不会引起异常。处理呼叫者期望中的此类变化的最佳方法是让合同指定两种方法:DoSomething方法和TryDoSomething方法,例如
请注意,尽管标准的"尝试"模式如上所述,但是如果有人正在设计一个生成项目的接口,则某些替代方法也可能会有所帮助:
注意,在接口中使用类似普通的TryGetResult模式的东西会使接口相对于结果类型不变。使用上述模式之一将允许接口相对于结果类型协变。同样,它将允许在'var'声明中使用结果:
并不是完全标准的方法,但是在某些情况下,其优势可能是合理的。 如果您实际上对异常感兴趣,并想考虑如何使用它们来构建健壮的系统,请考虑阅读存在软件错误时制作可靠的分布式系统。 我相信,如果您要构建一个将由外部程序使用(或将由其他程序重用)的类,则应使用合同方法。一个很好的例子是任何一种API。 |