Should You Start Using Contracts? - part 2
Facts and Fallacies
Now, let’s move from philosophy to business. Code Contracts have a number of features, some of which are consequences of certain architectural decisions, and others are imposed by the principles of contract programming. But not all of the myths about this tool are true, IMHO.
They are slooooow (in terms of compilation)!
This is correct. A ccrewrite will make the build three times slower, and it will stop working in a solution with a thousand projects. The problem is that you need to get a full transitive closure of all the dependencies for obtaining contracts of the caller. The task is difficult, and actual implementation is not linear.
Static analyzer does not work.
This is also true. Cccheck gives a lot of false warnings and an extensive tuning of the code may be required to tell the analyzer that everything is fine and that he is the fool. As a result, in actual large projects cccheck is rarely used or is run selectively for code analysis once every couple of months.
Tooling is poor.
True again. There is Code Contracts Editor Extensions, but this thing never really worked for me. So I chose the plug-in for Resharper, but this thing is very limited.
The resulting code runs more slowly.
This is not entirely true. In my current project, people are just crazy about effectiveness - custom serializers, hundreds of structures and a man-year of optimization. But contracts are still there. The main problem with contracts was related to recursion check which is inserted by a rewriter when a member of the current class is used in a precondition. Disabling this check gave a 15% increase in productivity in a heavy end-to-end scenario, and a complete shutdown of contracts after that gave another 5-6%.
Generation of internal ContractException is a horrible implementation bug.
Well, this is by design. If you want to handle an exception, you can use Contract.Requires (predicate), but in most cases a violation of pre-condition or post-condition should fly to the top of the stack and there either crash an application or issue an internal error message for a user.
Why contracts? It could be done by if-throws.
Well, following this logic, you can code in assembler. I do not agree with this statement. Thinking in terms of contracts is very helpful, and for me personally using a tool is stimulating. Plus the opportunity to shut down contracts totally or subscribe to breach of contract can be very helpful.
Transition to contracts is difficult. You need to change everything!!
This is not quite right, or rather not true at all. There are some simple steps for painless adaptation of this tool. The easiest way to start is to decorate existing classes, like Guard.NotNull, with an attribute ContractArgumentValidatorAttribute, or by adding Contract.EndContractBlock after a normal if-throw. In this case, even if the Code Contracts library will not be installed on the developer’s machine, the behavior during the execution will be the same, and you will have some new advantages (such as post-conditions, invariants, generation of documentation, or even static verifier).
The Future
The future is quite complicated.
Code Contracts library moved to public access and is developed by the community. After the release of support for VS2015 this community became quite active – there are new bugs, and more importantly, new fixes. I am planning to finish normal post-conditions for asynchronous methods. There are also plans to refine tooling.
In the near future the repository will move to a dotnet organization on github-e, which will simplify some organizational issues. As for the official development by Microsoft, it is likely finished.
But in addition to Code Contracts, there are theoretical plans to add contracts to the new edition of C# language (here is the github discussion). But so far it is not clear what will happen, what functionality the new contracts will have, when they will appear, or will they appear at all.
So Should We Use It or Not?
I always try to separate the tool from development practices. It is clear that in some cases the lack of tool makes the practice useless, but this is not the case.
The sense is not so much in Code Contracts as a library, as in the Design by Contracts as a way of sharing responsibilities between software components. Take a new class. Ask yourself a question: “what is its contract?” “What are the pre-conditions, post-conditions, are its invariants simple and obvious?” If you can not answer these questions, then the tool will not be very helpful. The design has to be changed!
Well, if you still want to try the tool (which is a good thing!), then you can start to use it to the full extent in your home projects (how come you don’t have any?!?!?) or use a careful path, as described above, using annotations of Guard.NotNull or Contract.EndContractBlock. Then, if over time the benefits will become obvious, it will be possible to switch to the full use of the tool, and if not, then you will not have to delete anything, because Contract.EndContractBlock does not require anything.
Yes, by the way, this is my personal opinion; the official opinion of Microsoft might be the same, not the same, or whatever.
Sergey Teplyakov
Expert in .Net, С++ and Application Architecture