13

For the last few months I've been developing a side project for my company, but the higher-ups have now decided it would be a good fit in an existing product.

I've been developing the side project using Microsoft's Code Contracts for static type checking (partly because I hadn't used them before and was eager to learn).

My problem is that if I check in my code to the code base with Contracts in place, will every other developer need the Code Contracts tools installed to be able to continue developing? I know for a fact that none of them have it installed, and I'm the junior here so I doubt I could convince them all to take it up.

I'm using .Net 4.5, so the Code Contract libraries are included, but I'm wondering if Visual Studio will complain that they're not building with CONTRACTS_FULL specified in the build options every time they go to build, or, if I leave CONTRACTS_FULL in the build options, what will happen when another developer tries to build? Additionally I'm wondering how the end-product will act when a Contract fails, but the code has not been built with the Code Contracts Rewriter.

I created a new solution with just one project. Created a simple function that fired a code contract violation, with code contracts uninstalled and CONTRACTS_FULL not specified. Built and ran it and received the following error:

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

I think the error message needs rewriting, as CONTRACTS_FULL is most definitely not specified.

Thanks to Matías Fidemraizer, we've worked out that this happens when using Contract.Requires<TException>() and not on Contract.Requires().

Ideally, I'd like to modify this behaviour so that the Contract fires the provided exception as if it were a normal guard statement instead of complaining about the rewriter.

Here's a fiddle demonstrating the problem: https://dotnetfiddle.net/cxrAPe

leppie
  • 115,091
  • 17
  • 196
  • 297
Nick Udell
  • 2,420
  • 5
  • 44
  • 83
  • I don't understand the issue at all. Such developers without CC installed won't compile the whole solution *with* contracts. Contracts will be ignored and the built result won't have contracts. – Matías Fidemraizer Sep 09 '14 at 15:49
  • I'm getting an error `Code contracts rewriter has not been run on this project, but it specifies CONTRACTS_FULL...` complaining the contracts were not rewritten by the contract rewriter when I fail a contract if it was built without the tools installed. Instead I would rather it threw the exception specified in my `Contract.Requires` calls. I can only assume the rest of my team will notice this, and it will have to be built by me for final release. – Nick Udell Sep 09 '14 at 15:55
  • CC won't compile if you don't have CC VS extension. `Contract` class in included in .NET Framework since 4.0, but they're bypassed without CC installed. – Matías Fidemraizer Sep 09 '14 at 17:26
  • Is there a way to get it to not compile the contracts and to instead just throw the exception when the contract fails instead of the above rewriter error? Perhaps using a Contract subclass? – Nick Udell Sep 09 '14 at 19:14
  • No, if CC compiler isn't executed, contracts aren't compiled thus they won't hit during execution :\ – Matías Fidemraizer Sep 09 '14 at 20:10
  • In my test project it's definitely hitting them without the tools installed, and I get that rewrite error above. This is in an empty solution made with the tools uninstalled, with one contract on a form's onload handler guaranteed. When the form loads, I get the error message. – Nick Udell Sep 10 '14 at 10:46
  • I don't know what's going on in your enviro, check this fiddle: https://dotnetfiddle.net/zcneYF. It compiles and `Contract.Requires` does nothing (it's not compiled). – Matías Fidemraizer Sep 10 '14 at 13:08
  • It seems to be caused when you use Contract.Requires instead of Contract.Requires. See my modified fiddle: https://dotnetfiddle.net/cxrAPe – Nick Udell Sep 10 '14 at 13:12
  • Uhm, I believe that this isn't the expected behavior! – Matías Fidemraizer Sep 10 '14 at 13:19
  • It seems that it's an expected behavior... http://stackoverflow.com/questions/14991647/throwing-an-exception-vs-contract-requirest see the accepted answer – Matías Fidemraizer Sep 10 '14 at 13:21
  • Ah yes, MSDN backs it up that `Contract.RequiresTException>` needs the rewriter, but `Contract.Requires` doesn't. Damn. Maybe I'll be able find some way to build my own. – Nick Udell Sep 10 '14 at 13:24
  • Do you need to get contracts work even if CC compiler isn't installed? – Matías Fidemraizer Sep 10 '14 at 13:29
  • Preferably I'd have it test the condition and then throw an exception as if it was a normal guard statement. I think I have a semi-reasonable solution, which I am writing up as an answer. – Nick Udell Sep 10 '14 at 13:33

3 Answers3

4

Unfortunately it's difficult to keep a library that is not installed via nuget up to date without forcing your coworkers to maintain their personal environment. Code contracts does not appear to have an official Microsoft-blessed package out there for use.

fourpastmidnight's post below has a recently updated answer to my original concern above, but the bottom half I think remains relevant even now. Get your buy-in, people!

In my (admittedly subjective) experience, tools like this come to be reviled if buy-in is not established among coworkers in advance. You might try broaching the subject slowly to see if they would be receptive to using it.

C Bauer
  • 5,003
  • 4
  • 33
  • 62
  • 3
    +1 for suggesting to stick with it. "and I'm the junior here so I doubt I could convince them": OP should not base the outcome of his suggestions on his seniority. Make the case, and discuss the pros and cons of using the library. Programmers tend to agree to take the best path forward if they are included in the decision, presented all the facts, and adequately deliberated it. – Guillaume CR Sep 09 '14 at 14:58
4

The short answer is: Yes. If you check in the code with Code Contracts, then all developers that might build that code must also have Code Contracts installed in order to build the code.

In contradiction to what @CBauer wrote in his answer, there is a "blessed" package for Code Contracts. No, it's not a NuGet package—it's an MSI installer based installation.

Finally, if you are in a Continuous Integration environment for debug builds (e.g. Development, QA/QC and/or Testing), then those build servers will also need to have Code Contracts installed.

When you use Code Contracts, Debug builds always require the use of Code Contracts. Please note that this is not necessarily the case for Release builds. It depends on what form of contract checking you're using and the options specified in the Project Properties.

The Code Contracts manual has all the details. It's quite good and I highly recommend taking the time to read and understand it.

It should be noted that if you use the Contract.Requires<TException>(bool condition) form of preconditions, you must have Code Contracts enabled for Release builds (see Section 5: Usage Guidelines, specifically, page 20, Usage 2 scenario).

Since you are integrating this code into an existing codebase that has not been developed with Code Contracts, you should consider revising your Code Contracts Project Property settings to conform to Usage Scenario 3 outlined on page 20 of the Code Contracts manual, and reformulate your contracts using the "legacy" if-then-throw pattern. This will enable your team to best tranisition the code base to using Code Contracts everywhere, allowing you to eventually replace "legacy" if-then-throw precondition checks with actual Code Contracts Contract.Requires(bool condition) checks, and if you like, Contract.Requires<TException>(bool condition) checks.

UPDATE: There Will Soon Be A NuGet Package For Code Contracts I was at the new GitHub repository for Code Contracts today. For those of you who don't know, Microsoft has open-sourced this and it is now a community-driven effort.

They recently (back in January) announced v1.10.xxxx.RC1 release. You can find information about it here on their GitHub repository.

fourpastmidnight
  • 4,032
  • 1
  • 35
  • 48
0

Contract.Requires<TException>() will fail if the code contracts rewriter is not installed, regardless of setting CONTRACTS_FULL or not.

One solution is to build a separate class FailableContract which tests the preprocessor condition CONTRACTS_FULL, which is set by Code Contracts.

Then all you have to do is remember to remove CONTRACTS_FULL from your build parameters before committing your code to the code base. You still get code contracts, everybody else gets guard statements.

A small portion of FailableContract (which I'm still writing):

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
    }
}

Then a simple Find, Replace Contract. to FailableContract.should get most issues.

Nick Udell
  • 2,420
  • 5
  • 44
  • 83
  • No, I thought about *not* throwing exceptions or contract exceptions. No CC rewriter == less checking. If deploys are done using continous integration and deployed compilation has CC compiled, each developer will decide what's easier: use more time and get more issues (thus, less productive) or just install the ##€#€#2@~~@ CC extension (2 minutes...) and go – Matías Fidemraizer Sep 10 '14 at 13:46