我们应该如何防御?


11

我们已经在一些代码上运行了Pex,并且一直在显示一些好东西(好东西,但是要在生产之前显示它们!)。

但是,Pex的优点之一是它不一定会停止尝试查找问题。

我们发现的一个方面是,在传递字符串时,我们没有检查空字符串。

所以我们改变了:

if (inputString == null)

if (string.IsNullOrEmpty(inputString)) // ***

这解决了最初的问题。但是,当我们再次运行Pex时,它决定:

inputString = "\0";

造成了问题。然后

inputString = "\u0001";

我们已经决定,如果遇到默认情况,可以使用默认值// ***,并且很高兴看到由任何其他奇数输入引起的异常(并对其进行处理)。

够了吗?


您是否检查过是否可以关闭某些警告?我知道JTest也可以这样做,但是它也是关闭某些建议的一种选择。调整设置花费了一些时间,以获得我们喜欢的代码测试配置文件。
FrustratedWithFormsDesigner

@Frustrated:是的,我们可以做和正在做的个人资料肯定有一些调整。顺便说一下,Pex是一个很棒的工具。它显示的结果只是提示了这个问题。
Peter K.

我没有适合您的答案,但我想感谢您与Pex相关的链接;如果它是我认为的样子,它将看起来很整洁,并将自动(?)为现有代码创建单元测试。我正在处理的代码非常庞大,没有测试,而且代码紧密耦合,因此无法重构任何内容。
韦恩·莫利纳

@WayneM:是的,这很好,尽管我需要通过一些例子来了解它的作用。对于旧代码,这很棒。对于新代码甚至更好!
Peter K.

Answers:


9

三个问题可以帮助您确定编码的防御力。

首先-输入错误会带来什么后果?如果这是您的开发人员PC上的错误消息,则防御起来可能并不那么重要。会导致客户的财务中断,IE会计信息中断吗?这是一个生命受到威胁的实时系统吗?在生死攸关的情况下,可能应该有比实际功能代码更多的验证和错误处理代码。

其次,有多少人将重用此功能或一段代码?只有你?你的部门?你的公司?您的顾客?该代码的使用范围越广,防御性就越高。

第三-我正在验证输入的来源是什么?如果它是从用户或公共网站输入的,那我将是超级防御。如果输入始终来自您的代码,请采取一些防御措施,但不要花费过多时间进行检查。

始终可以在系统中添加更多错误检查和验证。关键是编写和维护该代码的成本将超过由代码错误引起的问题的成本。


6

用户是邪恶的,应严格检查用户输入的任何内容。

无需用户输入或从预先消毒的数据中产生的任何内容,都无需在同一级别进行检查。这里的问题是当您忘记并在不良数据上使用这些方法时,因为您已经忘记了代码没有得到加强。

您应该经常检查的一件事是可能导致溢出或崩溃的任何事情。不管该方法被埋入多深,以及您如何确定该条件永远不会发生,都无所谓。无论如何,您都需要为此编程,以安抚墨菲。


2

我会像你需要的那样防御。我想有点模棱两可,但我会尽力解释。

正确使用方法时,如果该方法具有输入参数,则必须确定这些参数的期望值。在应用程序中的情况和位置,这将有所不同。例如,如果某个方法或一段代码正在接受来自用户输入的数据,那么您将希望覆盖所有代码基础并相应地处理任何输入,无论是通过错误消息还是通过某种不错的方式来显示不可接受的数据。

如果该方法是公开的API同上。您无法控制即将发生的事情,因此您应该期望尝试涵盖所有方面并据此进行编程。

对于在项目核心引擎中生成的方法,您可以在这里做出决定。我是否假定要对到达的数据进行预筛选和验证,然后再进行必要的检查。我猜这取决于方法的概念水平,是否可以接受检查。所以我可能要考虑的是:

1)这是我唯一需要做此检查的地方吗?是否需要为此条件在许多不同位置检查此变量。如果可以的话,我可以在连锁店的更高处进行一次检查,然后再确认

2)是否期望系统的其他组件能够与我编写的方法和接口一起使用。如果是这样,您可以通过调试断言语句,调试异常,方法注释和常规系统体系结构来控制所需的结果,或者是否需要对数据进行检查。

3)代码目前的失败结果是什么。会导致整个事情失败吗?是否会在其他地方发现任何错误,并且至少会发现该错误。

4)在这里进行检查是否有意义?有时检查一些可能损坏的数据,尽管此时可以帮助解决问题,而不会出错,则可能会掩盖它。此时,您可能需要花费数小时来追踪另一个问题,而只是发现实际问题是由于对事件链中的数据回溯进行了有效检查,这些事件级联到报告了用户/开发人员的事件上。

总的来说,我是一名防御性程序员,但是我也相信,通过全面的TDD和适当的单元测试,您可以按要求的级别对代码进行检查,并确信一旦进入任何较低级别的部分,它都可以正常工作。


1

我已经花了数周的时间解决可能需要5分钟的额外工作才能发现的错误。在我看来,这项前期工作总是值得的。您最终将修复该错误。唯一的问题是需要多长时间。

这些分析工具经常发现的一件事是,不一定是错误,而是不良的编程习惯,使错误更容易发生。这样的习惯之一就是变量初始化。有时,空字符串是变量的完全有效值。在这种情况下,您想要配置工具以不认为该特定实例中存在错误。但是,空字符串通常不是变量的有效值,但人们还是在设置它,因为编译器会抱怨那里是否没有东西,或者您的语言会自动初始化为空字符串,不管它是否有效。

这使人们感到沮丧,因为它似乎没有有效的解决方案,就像一个陷阱22,但是解决方案是重构代码,因此不需要在变量中放入有效值之前就初始化变量。这需要预先进行一些思考,但是会使您的代码更健壮,并且从长远来看实际上更容易编写和维护。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.