Code Contracts 进展缓慢

阅读数:636 2009 年 12 月 14 日

话题:.NET语言 & 开发架构文化 & 方法

从目前的开发进度来看,Code Contracts距离产品阶段还遥遥无期。尽管仍旧坚守着最初的承诺,但只要运行该程序不久就会发现众多的问题,这一切使得当前的 Code Contracts 还无法投入到真正的使用当中。

Code Contracts 一个最基本同时也是最重要的特性就是对空引用的检测。编译期对空引用异常的检测能力对于广大开发者来说是个天大的福音。但遗憾的是,目前 Code Contracts 还没有实现该功能。

Code Contracts 最大的问题在于无法探知字段的 readonly 修饰符。众多开发者从.NET 1.0 开始就在 C# 和 VB 中使用该修饰符来表明无法在构造方法外修改字段。通常它总是伴随着一个内联的初始化器,这样就保证了字段不会变成 null。然而遗憾的是 Code Contracts 中的静态检测器既不支持 readonly 修饰符,也不会检查对字段的赋值情况,这就导致了大量错误的警告信息的出现。

对于 Visual Basic 开发者来说,一个头疼的问题是 Code Contracts 中的静态检测器无法理解“If (aString = "")”语法。从语义上来说,这与新式的“String.IsNullOrEmpty”函数功能是一样的,而通常的 VB 代码都是用这种方式进行空字符串的检测。由于静态检测器会忽略掉含有类似语法的代码行,因此 VB 开发者总是会收到大量错误的警告信息。根据微软的 Francesco Logozzo 所述,Code Contracts 的下一版将会彻底解决该问题。

Code Contracts 的另一个问题是缺少对某些常见场景的属性支持,而该项工作的进展又不明朗。比如,大多数返回对象的函数都想要保证结果不为 null。通常我们都使用如下乏味的代码完成这一检查。

Contract.Ensures(Contract.Result(OfSomeType)() IsNot Nothing)

Contract.Ensures(Contract.Result<SomeType>() !=null);

长久以来开发者想要的只是一个简单的属性而已。

<NotNull()>PublicFunctionFoo() As SomeType

[NotNull] SomeType Foo()

由于 Code Contracts 包含了一个 assembly rewriter,因此增加一些可以转换成其他常见场景的属性(如给定的参数是否接受空值)是一件非常简单的事情。甚至还能自动生成正确的代码以抛出 ArgumentNull 或是 ArgumentOutOfRange 这样的异常。

但遗憾的是,Code Contracts 团队从一开始就不赞成让 Code Contracts 支持那些不使用它的客户端。比如说,他们想使用断言而非异常来处理错误(后者会抛出 ArguementException 异常)。当然了,以这作为失败断言是万万不能接受的,因为它会导致整个程序崩溃而没法采取任何恢复措施。

从那时起,情况就变得越来越糟。实际上,开启运行时检测会将写在”If check Then Throw“中的参数检测禁用掉。

Code Contracts 团队所面临的一个巨大问题就是.NET 框架的体积。除了要解决静态检测器和处理非 Code Contracts 代码方式上的严重问题外,他们还不得不回过头来定义那数不清的类的契约。到目前为止,连那些基本的契约如”For all ICollection<T>, calling Add will increment Count by 1.“还没搞定呢。

值得注意的是,只要有足够的时间和资源,以上这些问题都是可以解决的。Code Contracts 还是一项非常有前途的技术,随着时间的推移,它必定能够为那些花费大把时间和精力学习这些强大但却复杂工具的人们减少甚至彻底消除各类错误。

查看英文原文:Code Contracts are Making Slow Progress