当前位置:  开发笔记 > 编程语言 > 正文

Debug.Assert vs Exceptions

如何解决《Debug.AssertvsExceptions》经验,为你挑选了3个好方法。

令人惊讶的我才能够找到SO关于这个主题的一个先前的问题,我只是想获得社会"信任投票"(或不!)我的做法.

我这样看是这样的:

Debug.Assert你的处置将是真实的状态的事情.当我们完全控制我们的环境时,例如在验证某些前后条件的方法中,将使用此方法.

在出现特殊情况时使用例外情况.处理外部资源,即文件,数据库,网络等是很容易的.但...

在以下场景中它有点模糊.请注意,这是一个仅供参考的示例!

假设我们有MyClass类,它有一个公共属性MyMode和一个方法GetSomeValueForCurrentMode().将MyClass视为一个打算在库中发布(发布版本)以供其他开发人员使用的版本.

我们希望MyMode可以由此类的外部用户更新.现在,GetSomeValueForCurrentMode()有以下逻辑:

switch(MyMode)
{
case Mode.ModeA:
return val1;
case Mode.ModeB:
return val2;
default:
//Uh-uh this should never happen

}

我在这里得到的是MyClass的用户将其置于无效状态.那我们该怎么办?

在默认情况下,我们应该Debug.Assertthrow new InvalidOperationException(或其他)?

有一句咒语说我们不应该信任我们班级的用户.如果我们选择Debug.Assert并将MyClass构建为发布版本(从而删除Debug Asserts),则该类的用户将无法获得他们将其置于无效状态的有用信息.但这与其他咒语相反,后者只表示在完全无法控制的事情发生时抛出异常.

我发现我围绕着这个问题 - 其中一个编程辩论似乎没有明确的'正确'答案.那么让我们投票吧!

编辑:我在相关的SO问题(使用断言或例外的合同设计?)中注意到了这个响应:

经验法则是,在尝试捕获自己的错误时应使用断言,在尝试捕获其他人的错误时应使用异常.换句话说,您应该使用异常来检查公共API函数的前提条件,以及何时获得系统外部的任何数据.您应该将断言用于系统内部的函数或数据.

对我而言,这是有道理的,并且可以与下面概述的'Assert then throw'技术结合使用.

欢迎思考!



1> Daniel Daran..:

首先,MyClass有效当然应该由MyClass的不变量表示.

其次,你说"我们期望MyMode由这个类的外部用户更新" - 当然这个模式的setter应该具有典型的按合同设计形式(如任何公共函数):

  void Setter(mode m)
  {
    // INVARIANT ASSERT (1)
    // PRECONDITION ASSERTS (uses "m") (2)

    // BODY (3)

    // POSTCONDITION ASSERTS (if any) (4)
    // INVARIANT ASSERT (5)
  }

在(5)中,你会因为不变量不成立的尖叫断言而失败.但是在(2)中你会失败,因为传递的模式m是无效的.这将向用户发送明确的消息,从而解决您的问题.

请不要告诉我模式字段是公共的,用户在没有任何控制的情况下进行更改.

编辑:关于断言和释放模式,另请参阅:

断言总是坏的吗?

什么时候断言应该留在生产代码中?

使用断言或例外通过合同设计?



2> Carl Selebor..:

我基本上你自己的问题的结论一致:如果一个虱子的代码检测到错误一个虱子做,这是一个案例一个 ssert(和断言应在生产代码留下,除非性能另有规定).如果Alice的代码检测到E ve 代码中的错误,那么就是E xceptions 的情况,假设Alice和Eve位于错误跟踪软件的两侧.

现在这是一般的经验法则.断言,略有修改的形式,也可以用作"单挑,开发人员!"机制(然后它们不应被称为"ASSERT",而是"HEADS_UP"或类似的东西).如果您的公司开发客户端/服务器产品,并且服务器向客户端发送无效数据,该怎么办?如果您是客户端程序员,您会觉得将其视为外部数据(这是Eve的数据是kaputt)并且您想要抛出异常.但是,一个"更软"的断言,使Visual Studio的调试器停在那里,可以很早地检测到这些问题并将其报告给服务器团队.在一个真正的装置中,很可能是Mallory使用Eve和Alice之间的数据进行调整,但大部分时间它都是你的同事之一的错误,并且你想在它发生的时候看到它 - 这就是我称它们为什么的原因"单挑"断言:他们'不'



3> ChrisV..:

我同意这里的大多数人并遵循"按合同设计".您应该尝试区分已部署代码(合同)中的要求和设计期间的预期状态(调试断言).

您应该始终将合同断言作为例外(因为它们应该始终是例外).大多数框架都内置了用于捕获调试断言的机制.但在运行时,您应该总是抛出异常.

我使用自定义库来帮助解决这个问题(在C#/ VB.NET中).我最近在Codeplex(http://www.contractdriven.com/)上提出了它,如果你对它在实践中是如何工作感兴趣的话.

这样做的另一个好处是,当您开始更频繁地使用DbC时,您很少需要使用调试断言,因为已经有明确的保证写入您的代码,因此实际上很难进入无效状态.

所以你原来的帖子中的问题......"我在这里得到的是MyClass的用户将其置于无效状态.那么我们该怎么办?"......永远不应该出现.

您可能永远不需要再次调试任何东西!;-)


克里斯,抛出"合同破坏"异常(只能指示一个错误)不是"快速失败",它是"快速失败":大量的堆栈展开必须首先发生.在那里中止,然后当你发现违约时,将是真正的"快速失败".
推荐阅读
mobiledu2402851373
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有