代码契约 .NET - 替代方案

4

最近,我开始使用.net代码合约。在我看来,代码合约的思想本身很棒,但实现起来非常不愉快。

我不喜欢它的主要原因是:

  • 我只能在我的程序中使用像Contract.Require()这样的方法。 ContractAbbreviator有很多限制(例如,我不能将它们放在单独的程序集中,也不能使用参数),这使它们不太可用。没有属性和扩展方法,所以我的代码变得非常冗长。例如,如果我只想检查我的返回类型为Dictionary<string,string>的返回值不为空,我需要添加一个怪物,如Contract.Ensure(Contract.Result<Dictionary<string,string>>!= null)。它甚至不可读。
  • 静态分析器发出了许多错误警报,我花费的时间比修复实际问题还要多。
  • 它非常慢。即使它有一些缓存,但分析一个小项目仍需要几分钟,这使其对增量修复无用。它只需要太长时间。
  • ccrewriter中存在漏洞-它无法处理一半的程序集,并且无法在.net 4.5运行时中生存.net 4.0程序集。
  • 存在运行时/静态检查器二元性。当我刚开始时,我认为它就像Debug.Assert-您只需在感觉需要的地方添加它们即可。但事实证明,我需要向静态检查器证明所有内容,这肯定是先进的,但有时检查器很愚蠢,无法解决许多明显的代码结构(例如while)。而且没有工具可以告诉分析器“我知道自己在做什么,请忽略此合同违规行为”。
  • 您无法关联条件。例如,无法向静态分析器解释如果我检查string.NotNullOrEmpty,则包括string!= null。或者,如果我有自己的大型过程来检查文件路径,我无法向分析器解释它肯定不为空且不为空。 ContractAbbreviator属性有点帮助,但所有这些冗长的内容都在那里,看起来仍然很糟糕和愚蠢。
  • 代码合同的开发非常缓慢,即使现在它是开源的,据我所知,代码库也处于糟糕状态。
有没有比代码合约更先进且缺陷更少的替代方案?
1个回答

14

我不知道是否有其他的替代方案,但是我可以解决你提出的几个问题。我所在的团队在所有代码中都使用合同(约束条件),包括大约1000个模块,并在每次提交时运行静态分析,以及在VS中进行分析。

  • 代码丑陋。我们为(几乎)每个接口都单独创建了接口,还有实现这些接口的抽象类,由ContractClass和ContractClassFor属性连接。约束条件位于抽象的ContractClassFor类中,这使得实际的实现代码几乎没有受到代码合同的影响。

  • 静态分析器速度慢通常是由于缺少足够的合同,这迫使分析器要更多地工作才能找出是否存在违反合同的情况。

  • 静态检查器误报。我遇到过一些,但并没有成为问题。同样,如果您的合同太少,则静态检查器可能无法及时完成分析。

  • 可以通过这些MSBuild选项调试静态分析器速度,它将显示哪些方法需要最长时间进行分析。

    msbuild myproject.sln /p:CodeContractsExtraAnalysisOptions="-show progress -stats=!! -stats slowMethods"

  • 如果您确信某个条件总是成立,则可以使用Contract.Assume(condition)指示静态检查器假定这是事实。例如:

    Contract.Assume(mystring != null && mystring != "") 或者只需使用 Contract.Assume(!string.IsNullOrEmpty(mystring))

  • 关于使用Debug.Assert,我认为相对于应用程序在客户端崩溃而言,拥有静态检查的优势非常大。这样,我可以在发布产品之前消除应用程序崩溃的风险。也许我误解了你的意思,但我真的不认为你的比较有意义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接