【问题标题】:Exception analysis and preventing exceptions异常分析与预防异常
【发布时间】:2016-02-14 07:13:09
【问题描述】:

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

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

第一个例子(非强制性逻辑): 防御性编码(块 2 中的“if”条件)先于“obj”的使用。如果“obj”为空,则“if”条件跳过否则会导致异常的逻辑。我们可能在代码中存在“if”条件不存在的实例——应该添加它以防止异常。 我们想知道我们应该在多大程度上(努力)添加这种防御性逻辑。

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

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

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 服务通信,我们正在努力寻找模式。是否可以手动执行其他操作?是否有任何工具可以帮助我们找到这样的模式。

【问题讨论】:

  • 我投票结束这个问题,因为它属于codereview.stackexchange.com
  • 150 万行代码由并不真正知道自己在做什么的开发人员编写,这是技术债务的。确实没有解决该问题的工具或快速解决方案。静态分析工具可以通过报告他们认为可能存在问题的事情来帮助。但是像这样的代码库中的问题比几个空引用异常要更深。
  • 我会认真考虑/推荐重写。在这种特殊情况下,它的成本可能比尝试修补它并且仍然有一些不稳定的东西要少得多。当然前提是他们不使用与第一次相同的开发人员......
  • @Cᴏʀʏ 我没有要求任何人审查我的代码,这就是 codereview.stackexchange.com 的用途。我正在寻求有关如何审查代码并解决问题中描述的问题的想法

标签: c# exception design-patterns nullreferenceexception code-analysis


【解决方案1】:

如果您使用的是最新版本的 Visual Studio,您可以编写自己的分析器或使用 Code Cracker 等开源分析器来识别(通常是纠正)异常处理(和其他编码方面)中的模式。

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

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

【讨论】:

    【解决方案2】:

    错误 -> 错误 -> 失败

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

    faulterrorfailure 这三个术语具有非常具体的含义。

    系统故障发生在交付的服务不再符合规范时,后者是对系统预期功能和/或服务的约定描述。 错误是系统状态中可能导致后续故障的部分;影响服务的错误表明发生或已经发生了故障。判断或假设的错误原因是错误。 [Lap91,p。 4]

    您选择接受的使命:

    目标是防止异常。我们的目标不是在它们发生后更好地处理它们。

    所以我们说的是故障预防,其中故障错误(这是异常)的来源或原因。

    在您的示例中,如果我追溯问题的来源,则在第 1 块中的 someCondition 中,在某些时候有一个错误值,导致 obj 不是初始化。可能还有另一个故障导致该条件错误。就像一条链子。

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

    此外,尽管块 2 方法可以防止立即发生异常,但您对代码“非强制性”所做的假设最好是正确的。否则,在代码中的其他地方,由该逻辑块完成的工作(您只是为了防止异常而跳过这些工作)可能会在系统中创建另一个 fault

    除了手动之外,是否可以执行其他操作?有什么工具可以帮助我们找到这样的模式。

    从这个answer,有一个关于 ReSharper 的推荐(但我从未使用过它)。但是您可以尝试找到一些相当于 ASP.NET 的 lint

    我知道您的项目是用 C# 编写的,但SEI CERT Oracle Coding Standard for Java 有很多建议可以适用(从概念上)。如果应用程序使用线程,则有几条规则在 C# 中可能很有用。

    稳定性问题,IMO,不能这么轻易地“解决”。

    【讨论】:

      猜你喜欢
      • 2012-02-21
      • 1970-01-01
      • 2010-10-28
      • 2011-05-28
      • 2016-10-10
      • 1970-01-01
      • 1970-01-01
      • 2012-06-17
      • 1970-01-01
      相关资源
      最近更新 更多