异常分析和防止异常

本文关键字:异常 | 更新日期: 2023-09-27 18:21:46

我们被要求查看一个客户端应用程序的代码,该代码涉及大约150万行代码。该应用程序具有很大的稳定性,并且经常发生崩溃,我们被指派通过手动静态代码审查来查找此类问题的根本原因。目标是防止出现异常。一旦它们发生,我们的目标不是更好地处理它们。

下面我有两个例子来说明防御编程以防止异常:在非强制性逻辑和强制性逻辑的情况下。

第一个示例(非强制性逻辑):防御性编码(块2中的"if"条件)先于"obj"的使用。如果"obj"为null,那么"If"条件将跳过原本会导致异常的逻辑。我们可能在代码中有不存在"if"条件的实例,应该添加它以防止出现异常。我们想知道我们应该在多大程度上增加这种防御逻辑。

第二个示例(强制逻辑):在第二个例子中,"if"条件检查null(块3),跳过该逻辑是无效的,因为该逻辑是强制性的。在这种情况下,"if"条件必须引发异常。这种防御逻辑不会提高稳定性:无论是由于null引用异常还是由于抛出异常的"if"条件,都会引发异常。

我们被要求在代码中查找导致抛出异常的模式,即为什么没有设置对象——问题出在块1中的逻辑中。(在本例中:因为只有当SomeCondition不为false时才会设置它)。

bool someCondition = false;
DataSet obj = null;

/*** Begin block 1 ***/
if(someCondition)
{
    obj = new DataSet();
    //Fill the obj with data
    Populate(obj);
}
/*** End block 1 ***/

/*** Begin block 2 ***/
//Perform some non-mandatory logic
//defensive coding
if(obj != null && obj.Tables["Employee"] != null && obj.Tables["Employee"].Rows[5] != null)
{
    DataRow row1 = obj.Tables["Employee"].Rows[5];
    row1["FirstName"] = "Bob";
}
/*** End block 2 ***/

/*** Begin block 3 ***/
//Perform  mandatory logic
//defensive coding
if (obj == null && obj.Tables["Employee"] == null && obj.Tables["Employee"].Rows[5] == null)
    throw new Exception("Object obj cannot be null");
 DataRow row2 = obj.Tables["Employee"].Rows[5];
 row2["Role"] = "Manager";
/*** End block 3 ***/

我们正在对代码进行手动审查,但它是一个巨大的ASP.NET MVC应用程序,可以与后端WCF服务进行对话,我们正在努力寻找模式。除了手动之外,还能做其他事情吗?有什么工具可以帮助我们找到这样的模式吗。

异常分析和防止异常

故障->错误->故障

我将重点介绍Hanmer,Robert(2013-07-12),容错软件模式(Wiley软件模式系列)(第3-4页)中的定义。威利。Kindle版。

术语故障错误失败具有非常具体的含义。

当所提供的服务不再符合规范时,就会发生系统故障,后者是对系统预期功能和/或服务的约定描述。错误是系统状态中容易导致后续故障的部分;影响服务的错误是故障发生或已经发生的指示。错误的判定或假设原因是故障。[Lap91,第4页]

你选择接受的使命:

目标是防止出现异常。一旦它们发生,我们的目标不是更好地处理它们。

因此,我们谈论的是故障预防,其中错误error的来源或原因(这是例外)。

在您的示例中,如果我追溯到问题的,则在块1中的someCondition中,它在某个时刻具有错误值,导致obj未初始化。很可能是另一个故障导致了这种情况的错误。它就像一条链子。

若你们想防止异常,那个么为什么不修复那个些故障源呢?防御代码(在Hanmer的书中也有解释)是好的,因为事情会发生,它有助于检测故障。但你给出的例子似乎无效,因为你只是在避免错误(而不是消除错误)。

此外,尽管块2方法可以防止立即出现异常,但您关于代码是"非强制性"的假设最好是正确的。否则,在代码的其他地方,该逻辑块所做的工作(您跳过该逻辑块只是为了防止异常)可能会在系统中创建另一个错误

除了手动之外,还能做其他事情吗?有什么工具可以帮助我们找到这样的模式吗。

根据这个答案,有一个ReSharper的推荐(但我从未使用过)。但是,您可以尝试找到一些与ASP.NET的lint等效的东西。

我知道你的项目是用C#编写的,但SEICERT Oracle Java编码标准中有很多建议可以(从概念上)应用。如果应用程序使用线程,那么有几个规则在C#中可能很有用。

稳定性问题,IMO,不可能这么容易"解决"。

如果您使用的是最新版本的Visual Studio,您可以编写自己的分析器,也可以使用像Code Cracker这样的开源分析器来识别(并且经常更正)异常处理(以及其他编码方面)中的模式。

https://code-cracker.github.io/diagnostics.html

例如,CodeCracker有两个分析器,我曾将它们用于类似的代码评估目的,用于检测空捕获块,这是另一种常见的异常处理反模式。还要注意如何记录异常,以及是否使用描述性错误消息(此链接还列出了异常管理的最佳实践和参考资料):http://deviq.com/descriptive-error-messages/