2008-11-12 63 views
9

我刚刚遇到了有关初始化局部变量的this question。许多答案辩论简单/可读性健壮性。作为嵌入式(远程部署的)的系统开发人员,我总是青睐稳健性,而且往往遵循以下几个看似矛盾的规则:健壮性的最佳实践

  • 天天看错误的最好的你的方式的能力,允许该设备继续运行。

  • 设计代码失败尽快发生编程或致命错误后。

我们都接受过验证输入的训练,以防止设备因用户(或其他外部)输入而断开;始终假定数据可能无效并相应地进行测试。

还有什么其他具体您是否遵循以下方法来确保健壮性?示例很有帮助,但我也对技术感兴趣,这些技术都是通用的。

回答

2

我实现了多种方法来预防和从错误中恢复:

1)处理所有异常。正如你所说,“处理每一个错误”。如果用户单击表单上的按钮,应用程序就不可能从未处理的异常中消失(“poof”)。出于这个原因,我用一个通用的try catch来包装事件处理程序。

2)使用完整堆栈跟踪记录错误。当我重新抛出异常时,我总是创建一个新异常,并将捕获到的异常添加为内部异常。我的日志代码以递归方式展开消息,这些消息给出了比我更多的细节。

3)决定你的班是否可以重复使用。如果没有记录它。考虑在代码中实现一个接口,如IRestartableIReusable。没有实现它的任何对象在被使用一次后必须被抛弃。

4)切勿假设线程安全。我已经学会了.NET非常多线程的难题。许多事件在任意线程上处理。用.NET编写的给定应用程序可能有许多并发线程正在执行,并且没有一行代码明确创建一个。

5)尽量缩小变量范围。在使用它们的地方附近实例化对象,而不是在方法开始的大块中。您将潜在地缩短对象的寿命,并且您不会忘记位于类或方法顶部的巨大块中的不需要的或重用的变量。

5)简单,但我仍然看到它发生。避免像鼠疫这样的全局变量。我看过有数百个未使用/重用变量的代码。弄清楚和重构是一团糟。

2

尽量使用Design by contract。但是我发现在我的工作领域里很少实用。

+0

单个开发人员负责时很难执行此操作,但我们首先尝试定义接口。如果没有其他的东西,它可以很容易地编写测试用例和独立开发模块。 – 2008-11-12 06:08:08

+0

DBC也最好与本地支持它的语言一起使用,这在许多人的生产环境中并不常见。 – 2008-11-12 06:14:58

+0

不幸的是,我发现DbC只在某些情况下有用,并且发现了一些问题。现在我编程的图形用户界面和程序不能真正失败,因为输入错误然后。但是我确实发现,即使没有本地支持,DbC也适用于记录应该如何使用代码。 – Jonas 2008-11-12 06:31:59

7

我是“The Pragmatic Programmer”中描述的技术的粉丝。我也使用TDD,而不是DBC,因为我觉得它更灵活和更有效率。例如,'pragprog'中描述的一些技术包括:

  • 测试经常。尽早测试。测试自动
  • 一次且仅一次
  • 使用Sabotuers来测试你的测试
  • 使用异常的特殊问题
  • 不要生活在破碎的窗户
  • 不使用人工程序

他们似乎都喜欢常识,但惊人的速度有多快,在面临最后期限时,团队偏离这些基本原则。

+0

我正在游说采用TDD和基于证据的调度,因为它们都迫使我们与现实合作,而不是假设。感谢指针。 – 2008-11-12 06:10:17

2

我是的粉丝而不是初始化局部变量。他们应该在需要时进行设置。否则,读取代码的程序员可能会感到困惑,如"hmm why is this 0 at the beginning..."。如果你没有初始化它,很明显它还没有被使用。

+1

我会抓住这个机会 - 并通过评论缓解它 - 因为我花费了太多时间来追逐由未初始化的变量导致的“跳跳虫”错误。 – 2008-11-12 06:20:17

+0

正确测试应该可以避免初始化错误。 – 2008-11-12 06:50:45

+0

我同意。不要将变量初始化为从不使用的值。未使用的初始值是不必要的代码,这可能会导致混淆。 – 2008-11-12 07:17:18

5

听起来像你已经有这两个下来:
快速失败。 http://en.wikipedia.org/wiki/Fail-fast
失效保护。只要有可能

逃避国家:http://en.wikipedia.org/wiki/Fail-safe

这三个可能成为我比任何其他更好的。创建和使用不可变对象 - 它们更容易测试,不太可能背叛你。

不要编写不必要的代码。这个很难。查看Strunk和White编写的关于“风格的元素”的文章的最近绽放。

问自己每10分钟左右:“这是愚蠢的吗?”说实话。这一个更难。

-Jason

2

我喜欢...... 文件limit values in (java)doc。 (可以参数为空吗?为空?)

这样,当我的代码被使用(或当我使用我自己的代码)时,我知道我能期待什么。简单的建议,但很少实施;)

该文件还包括明确分开static and runtime exceptions。这样,如果程序必须尽快失败以提高健壮性,我知道它是否因为预见的异常而失败(静态,必须在编码时间通过捕获或重新抛出来处理),或者如果这是因为参数不正确(运行时异常,只在应用程序生命周期中检测到)。

如果两种类型的异常都有明确记录(尤其是限制参数值时),则整体稳健性更容易实施。

6

我喜欢第二双眼睛方法:在我编写并测试了一些关键代码之后,有时我会请同事仔细检查它,以期寻找方法来打破它。

以这种方式展现人们的创造力很有趣。:-)

2

如果可能的话,我会询问专门从事其他事情的人的意见。这常常揭示一种或多种全新的打破事物的方式。

2

偏执是程序员的生存特质。不断问自己,这怎么会失败?然后尝试弄清楚如何防止这种失败。

1

我写的系统(C语言)对性能和可靠性要求很高。设计失败很好。当涉及设计安全的事情变得更加复杂。

硬件可能总是失败,除此之外您还有无效数据从外部进入系统的问题。我在这些领域的解决方案通常会精心制作(为了安全起见而设计),而在几乎所有其他领域,通过极其简单的代码设计并且根本没有数据验证来设计失败。

所以你可以说我设计的时候风险很小,而且安全的时候风险很高。

对于调试,我有时会编写条件代码,它永远不会被输入,其中包含一个除零或一些这样的内容,以便处理进入时立即调用调试器。

我通常不会初始化本地堆栈变量,因为编译器会告诉我哪些需要初始化,哪些可以完全省略。

代码审查是伟大的,但不是傻瓜证明。我曾经花了几个小时看着一个小的(无限)循环(尴尬,不是吗?)并且看不到索引没有增加。我的同事也没有看到它。当我终于看到生成的代码清单时,我发现循环测试已经被优化为一次无条件跳转,然后才明白问题所在。