【问题标题】:Can I leave contracts in code that I'm merging with a codebase used by non-code contracts developers?我可以将合同留在与非代码合同开发人员使用的代码库合并的代码中吗?
【发布时间】:2014-09-02 15:48:32
【问题描述】:

在过去的几个月里,我一直在为我的公司开发一个副项目,但现在高层认为它非常适合现有产品。

我一直在使用 Microsoft 的代码合同进行静态类型检查(部分是因为我以前没有使用过它们并且渴望学习)来开发辅助项目。

我的问题是,如果我将代码签入到带有合同的代码库中,其他开发人员是否需要安装代码合同工具才能继续开发?我知道他们都没有安装它,而且我是这里的大三学生,所以我怀疑我能否说服他们所有人都接受它。

我使用的是 .Net 4.5,因此包含了代码合同库,但我想知道 Visual Studio 是否会抱怨他们没有在每次构建时使用构建选项中指定的CONTRACTS_FULL 进行构建,或者,如果我在构建选项中留下CONTRACTS_FULL,当另一个开发人员尝试构建时会发生什么?此外,我想知道当合同失败时最终产品将如何运作,但代码尚未使用 Code Contracts Rewriter 构建。

我只用一个项目创建了一个新的解决方案。创建了一个触发代码合约违规的简单函数,其中代码合约已卸载,CONTRACTS_FULL 未指定。构建并运行它并收到以下错误:

Run-time exception (line 8): An assembly (probably "hdxticim") must be rewritten using the code contracts binary rewriter (CCRewrite) because it is calling Contract.Requires<TException> and the CONTRACTS_FULL symbol is defined.  Remove any explicit definitions of the CONTRACTS_FULL symbol from your project and rebuild.  CCRewrite can be downloaded from http://go.microsoft.com/fwlink/?LinkID=169180. 
After the rewriter is installed, it can be enabled in Visual Studio from the project's Properties page on the Code Contracts pane.  Ensure that "Perform Runtime Contract Checking" is enabled, which will define CONTRACTS_FULL

我认为错误消息需要重写,因为绝对没有指定 CONTRACTS_FULL。

感谢 Matías Fidemraizer,我们发现在使用 Contract.Requires&lt;TException&gt;() 而不是 Contract.Requires() 时会发生这种情况。

理想情况下,我想修改此行为,以便合约触发提供的异常,就好像它是正常的保护语句一样,而不是抱怨重写器。

Here's a fiddle 演示问题:https://dotnetfiddle.net/cxrAPe

【问题讨论】:

  • 我完全不明白这个问题。此类未安装 CC 的开发人员不会编译整个解决方案 with 合同。合同将被忽略,构建的结果将没有合同。
  • 我收到一个错误Code contracts rewriter has not been run on this project, but it specifies CONTRACTS_FULL...,抱怨如果合约是在没有安装工具的情况下构建的,合约没有被合约重写器重写。相反,我宁愿它抛出我的Contract.Requires&lt;ExceptionType&gt; 调用中指定的异常。我只能假设我的团队的其他成员会注意到这一点,并且它必须由我构建才能最终发布。
  • 如果您没有 CC VS 扩展,CC 将无法编译。 Contract 类自 4.0 起包含在 .NET Framework 中,但在未安装 CC 的情况下会被绕过。
  • 有没有办法让它不编译合约,而是在合约失败时抛出异常而不是上面的重写错误?也许使用 Contract 子类?
  • 不,如果不执行 CC 编译器,则不会编译合约,因此它们不会在执行期间命中:\

标签: c# .net-4.5 development-environment code-contracts


【解决方案1】:

简短的回答是:是的。如果您使用代码契约签入代码,那么所有可能构建该代码的开发人员也必须安装代码契约才能构建代码。

与@CBauer 在他的回答中写的相反,代码合同有一个“有福的”包。不,它不是 NuGet 包,而是基于 MSI 安装程序的安装。

最后,如果您处于调试构建(例如开发、QA/QC 和/或测试)的持续集成环境中,那么这些构建服务器还需要安装代码合同。

当您使用代码协定时,调试版本始终需要使用代码协定。请注意,Release 版本不一定属于这种情况。这取决于您使用的合同检查形式以及项目属性中指定的选项。

Code Contracts manual 包含所有详细信息。它非常好,我强烈建议您花时间阅读和理解它。

应该注意,如果您使用Contract.Requires&lt;TException&gt;(bool condition) 形式的前置条件,您必须发布构建启用代码协定(参见第5节:使用指南,特别是第 20 页使用 2 场景)。

由于您将此代码集成到尚未使用代码合同开发的现有代码库中,因此您应该考虑修改您的代码合同项目属性设置以符合 上概述的使用场景 3代码合同手册的第 20 页,并使用“旧的”if-then-throw 模式重新制定您的合同。这将使您的团队能够最好地将代码库转换为在任何地方使用代码合同,最终允许您用实际的代码合同Contract.Requires(bool condition) 检查替换“遗留” if-then-throw 前置条件检查,如果您愿意,还可以使用 Contract.Requires&lt;TException&gt;(bool condition) 检查.

更新:很快就会有代码合同的 NuGet 包 我今天在新的 GitHub 代码合同存储库中。对于那些不知道的人,Microsoft 已将其开源,现在是社区驱动的工作。

他们最近(早在一月份)宣布了 v1.10.xxxx.RC1 版本。您可以找到有关它的信息here on their GitHub repository

【讨论】:

    【解决方案2】:

    不幸的是,在不强迫您的同事维护他们的个人环境的情况下,很难使未通过 nuget 安装的库保持最新。代码合同似乎没有微软官方支持的软件包可供使用。

    fourpastmidnight 下面的帖子最近更新了我对上面最初关注的答案,但我认为下半部分即使现在仍然相关。得到你的支持,人们!

    在我(诚然是主观的)经验中,如果没有事先在同事之间建立认同,这样的工具就会受到谴责。您可以尝试慢慢地提出这个主题,看看他们是否愿意使用它。

    【讨论】:

    • +1 建议坚持下去。 “而且我是这里的大三学生,所以我怀疑我能说服他们”:OP 不应该将他的建议的结果建立在他的资历上。提出案例,并讨论使用该库的利弊。如果程序员在决策中包括在内、陈述所有事实并经过充分考虑,他们往往会同意采取最好的前进道路。
    【解决方案3】:

    如果没有安装代码契约重写器,Contract.Requires&lt;TException&gt;() 将失败,无论是否设置CONTRACTS_FULL

    一种解决方案是构建一个单独的类FailableContract,用于测试由代码合同设置的预处理器条件CONTRACTS_FULL

    那么您所要做的就是记住在将代码提交到代码库之前从您的构建参数中删除CONTRACTS_FULL。你仍然得到代码合同,其他人得到保护声明。

    FailableContract 的一小部分(我还在写):

    public class FailableContract
    {
    
        public static void Requires(bool condition)
        {
            #if CONTRACTS_FULL
                Contract.Requires(condition);
            #else
                if (!condition) throw new ArgumentException(); //Just go with an argument exception because we haven't been supplied with an exception type.
            #endif
        }
    
        public static void Requires<TException>(bool condition) where TException : Exception, new()
        {
            #if CONTRACTS_FULL
                Contract.Requires<TException>(condition);
            #else
                if (!condition) throw new TException();
            #endif
        }
    }
    

    然后一个简单的查找,将Contract. 替换为FailableContract. 应该会解决大多数问题。

    【讨论】:

    • 不,我想过抛出异常或合同异常。没有 CC 重写器 == 更少的检查。如果使用持续集成完成部署并且部署的编译已编译 CC,则每个开发人员将决定更容易的方法:使用更多时间并解决更多问题(因此效率较低)或仅安装 ##€#€#2@~~@ CC延长(2 分钟...),然后去
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-08
    • 2011-03-07
    • 1970-01-01
    • 2011-02-05
    相关资源
    最近更新 更多