代码合同 .net - 备选方案
Code contracts .net - alternatives
最近开始使用Code contracts for .net。代码契约本身的想法在我看来很棒,但实现起来却很不愉快。
我不喜欢它的主要原因是:
- 我只能在程序中使用像
Contract.Require()
这样的方法。 ContractAbbreviator
s 有太多限制(比如,我不能将它们放在单独的程序集中,我不能使用参数),这使得它们不太可用。没有属性,也没有扩展方法,所以我的代码变得非常冗长。比如我只是想检查我的Dictionary<string, string>
类型的return值不为null,就需要加一个怪物如Contract.Ensure(Contract.Result<Dictionary<string, string>> != null)
。它甚至不可读。
- 静态分析器发出如此多的误报,以至于我花在关闭它上的时间比解决实际问题的时间还多。
- 速度极慢。尽管它有一些缓存,但即使是一个小项目也需要几分钟的时间来分析,这使得它无法用于增量修复。就是时间太长了。
ccrewriter
中存在错误——它无法咀嚼一半的程序集,并且无法在 .net 4.5 运行时中生存 .net 4.0 程序集。
- 存在 runtime/static 棋盘二元论。当我刚开始时,我认为它就像
Debug.Assert
一样简单——您只需将它们添加到您认为需要的任何地方。但事实证明,我需要向静态检查器证明一切,这肯定是先进的,但检查器有时很愚蠢,无法解析许多明显的代码结构(如 while
)。而且没有仪器只能对分析器说 "I know what I'm doing, just ignore this contract violation".
- 您不能关联条件。例如,没有办法向静态分析器解释如果我检查
string.NotNullOrEmpty
这包括 string != null
。或者,如果我有自己的大程序检查文件路径,我无法向分析器解释它肯定不是 null 也不是空的。 ContractAbbreviator
属性有点帮助,但是所有这些冗长的东西都在那里,它看起来仍然肮脏和愚蠢。
- 代码合约的开发非常缓慢,尽管它现在是开源的,但据我所知,代码库处于糟糕的状态。
有没有缺陷更少的代码契约的高级替代品?
我不知道有什么替代方案,但我也许可以解决您的一些问题。我在一个团队中工作,该团队在我们所有的代码(~1000 个模块)中使用合同,并且 运行 对每次签入以及在 VS 中进行静态分析。
代码丑陋。我们对(几乎)所有事物都有单独的接口,以及实现这些接口的抽象 类,由 ContractClass 和 ContractClassFor 属性连接。合同是抽象的ContractClassFor-classes,这使得实际的实现代码几乎没有代码合同。
静态分析器速度慢通常是由于没有足够的契约,这迫使分析器做更多的工作来找出是否可以破坏契约。
静态检查器错误警报。我有过一些,但还没有到成为问题的程度。同样,如果你的合约太少,静态检查器可能无法及时完成分析。
可以使用这些 MSBuild 选项调试静态分析器运行缓慢,这将显示哪些方法花费最多的时间进行分析。
msbuild myproject.sln /p:CodeContractsExtraAnalysisOptions="-show progress -stats=!! -stats slowMethods"
如果您确定某些条件始终成立,那么您可以使用 Contract.Assume(条件) 指示静态检查器假定情况就是如此。例如
Contract.Assume(mystring != null && mystring != "")
或者只是 Contract.Assume(!string.IsNullOrEmpty(mystring))
关于 Debug.Assert 的使用,我认为进行静态检查而不是仅仅让我的应用程序在客户站点崩溃是一个巨大的优势。这样,我就可以在发布产品之前消除应用程序崩溃的风险。可能我理解错了,但我真的觉得你的比较没有意义。
最近开始使用Code contracts for .net。代码契约本身的想法在我看来很棒,但实现起来却很不愉快。
我不喜欢它的主要原因是:
- 我只能在程序中使用像
Contract.Require()
这样的方法。ContractAbbreviator
s 有太多限制(比如,我不能将它们放在单独的程序集中,我不能使用参数),这使得它们不太可用。没有属性,也没有扩展方法,所以我的代码变得非常冗长。比如我只是想检查我的Dictionary<string, string>
类型的return值不为null,就需要加一个怪物如Contract.Ensure(Contract.Result<Dictionary<string, string>> != null)
。它甚至不可读。 - 静态分析器发出如此多的误报,以至于我花在关闭它上的时间比解决实际问题的时间还多。
- 速度极慢。尽管它有一些缓存,但即使是一个小项目也需要几分钟的时间来分析,这使得它无法用于增量修复。就是时间太长了。
ccrewriter
中存在错误——它无法咀嚼一半的程序集,并且无法在 .net 4.5 运行时中生存 .net 4.0 程序集。- 存在 runtime/static 棋盘二元论。当我刚开始时,我认为它就像
Debug.Assert
一样简单——您只需将它们添加到您认为需要的任何地方。但事实证明,我需要向静态检查器证明一切,这肯定是先进的,但检查器有时很愚蠢,无法解析许多明显的代码结构(如while
)。而且没有仪器只能对分析器说 "I know what I'm doing, just ignore this contract violation". - 您不能关联条件。例如,没有办法向静态分析器解释如果我检查
string.NotNullOrEmpty
这包括string != null
。或者,如果我有自己的大程序检查文件路径,我无法向分析器解释它肯定不是 null 也不是空的。ContractAbbreviator
属性有点帮助,但是所有这些冗长的东西都在那里,它看起来仍然肮脏和愚蠢。 - 代码合约的开发非常缓慢,尽管它现在是开源的,但据我所知,代码库处于糟糕的状态。
有没有缺陷更少的代码契约的高级替代品?
我不知道有什么替代方案,但我也许可以解决您的一些问题。我在一个团队中工作,该团队在我们所有的代码(~1000 个模块)中使用合同,并且 运行 对每次签入以及在 VS 中进行静态分析。
代码丑陋。我们对(几乎)所有事物都有单独的接口,以及实现这些接口的抽象 类,由 ContractClass 和 ContractClassFor 属性连接。合同是抽象的ContractClassFor-classes,这使得实际的实现代码几乎没有代码合同。
静态分析器速度慢通常是由于没有足够的契约,这迫使分析器做更多的工作来找出是否可以破坏契约。
静态检查器错误警报。我有过一些,但还没有到成为问题的程度。同样,如果你的合约太少,静态检查器可能无法及时完成分析。
可以使用这些 MSBuild 选项调试静态分析器运行缓慢,这将显示哪些方法花费最多的时间进行分析。
msbuild myproject.sln /p:CodeContractsExtraAnalysisOptions="-show progress -stats=!! -stats slowMethods"
如果您确定某些条件始终成立,那么您可以使用 Contract.Assume(条件) 指示静态检查器假定情况就是如此。例如
Contract.Assume(mystring != null && mystring != "")
或者只是Contract.Assume(!string.IsNullOrEmpty(mystring))
关于 Debug.Assert 的使用,我认为进行静态检查而不是仅仅让我的应用程序在客户站点崩溃是一个巨大的优势。这样,我就可以在发布产品之前消除应用程序崩溃的风险。可能我理解错了,但我真的觉得你的比较没有意义。