One can argue with me, that code contract is a part of unit testing and might be included as a part of.NET test projects, but according to me, it is not restricted only for testing frameworks, you could use it more likely for your own libraries so that you could have better code handling and also some way of separation between the validation logic for which the library is built in and how you would react with the outside world. Now let us discuss, how to use it in your program, and later on I will build an application to use it.
The Basis
As an application developer, it is our duty to validate any input to a program from external agent. Most of us spend a lot of time while developing custom validation blocks which might look for a condition and throw an exception with a custom message. But does it actually worth. Putting this kind of unnecessary validation blocks for every method literally makes it look ugly and hard to maintain. Say for instance, I want to write a custom method which might input two parameters from external agent and process it. :
public void OfferMeValues(string arg1, string arg2) { if (arg1 == null) throw new ArgumentNullException("Argument cannot be null, Parameter Name: arg1"); if (arg2 == null) throw new ArgumentNullException("Argument cannot be null, Parameter Name: arg2"); if (arg1.Trim().Length == 0 || arg2.Trim().Length == 0) throw new ArgumentException("No argument cannot be empty or whitespace"); if (arg1.Equals(arg2)) throw new ArgumentOutOfRangeException("Cannot work on identical parameters, Parameter : arg1, arg2"); //here goes your actual logic Console.WriteLine("We ensure objects are not null, not empty and not equal"); }
This looks horrible, right. Even though the entire method has only one single line of code with Console.WriteLine, the entire validation block resides just above it. Yes it is possible to move it to somewhere, may be you can build one utility kind of class which takes care of these validation, but yet each method will have its own kind of validation. Hence you need to create your own library and call it from every method. Well, .NET code contracts addresses the issue. It writes the code for you during runtime, not even giving a standard library to handle these, but also makes your validation instructions available before any code. One of the major advantage of Code contract is your assembly will hold each of these validation entries internally within the block if not it calls the Code Contract library and also allows you to write static checking on these during compilation.
Installation
Code contract library actually reside directly into BCL with .NET 4.0. The compiler is also updated to write these adjustments for you. Installation is only needed to have static type checking from your Visual Studio. To have that, please download the installer from DevLabs Link and install it to your machine. Once you successfully install, create a new project on your Visual studio, and you will get a new Tab in properties section to configure your code contract with MsBuild.
You can also go to Microsoft research site on Code Contract to know more about it.
.NET code contract follows design principle of Design By Contract. This principle have 3 tenets which code contract also takes care of :
1. Precondition : Refers to the things it expect to do.
2. Postcondition : Refer to things that it guarantees to do.
3. Invariant : Refer to things it maintains.
Well, the tenets are fine for Design by Contract and .NET code contract follows each of the tenets properly. We will examine each of them in this article.
Precondition
The example that I gave just above holds the strong base on preconditions. Precondition means the things you need to satisfy before running the code. Hence if precondition is failed, no other line inside the method gets executed.
Contract.Requires allows you to pass a condition and a message so that it throws an exception whenever the condition fails to satisfy. As Requires ensures that exception occur beforehand, it is treated as Precondition. Let me rewrite the code that I specified above with Requires.
public void OfferMeValues(string arg1, string arg2) { Contract.Requires<ArgumentNullException>(arg1 != null, "Argument cannot be null, Parameter Name: arg1"); Contract.Requires<ArgumentNullException>(arg2 != null, "Argument cannot be null, Parameter Name: arg2"); Contract.Requires<ArgumentException>(arg1.Trim().Length > 0 && arg2.Trim().Length > 0, "No argument can be empty"); Contract.Requires<ArgumentOutOfRangeException>(!arg1.Equals(arg2), "Cannot work on identical parameters, Parameter : arg1, arg2"); //here goes your actual logic Console.WriteLine("We ensure objects are not null, not empty and not equal"); }
Hmm, doesn’t it looks good on me? Yes, using code contract method makes it much more cleaner and easy to read. Hence when arg1!=null it throws ArgumentNullException with the custom message provided.
Now if you try to run your application with
ContractInvoker invoker = new ContractInvoker(); invoker.OfferMeValues(null, null);
where CotractInvoker is our class, you will get something like this :
This is weird. Now after I read the documentation, I found that PreCondition with exception can only be used when runtime checking is enabled. It says “If you are using scenario 2 (Requires (Exn)) and you make your source code available to other developers, you might want to alert them that they need to use the tools to build your source”. Hence it puts the messagebox or rather a Debug.Asset statement to make sure the project is built only using runtime checks turned on.
Hence, if I change the AssemblyMode to standard, which eventually rewrite the IL instructions during compilation, you will get through the exception.
Now if I rerun the application, it throws the exception correctly.
If you try to see what happened inside the assembly after the tool builds it, you will find exactly what you are looking for. The method looks like :
The __ContractRuntime is a class that is automatically added to the assembly that takes care of your calls.
Hmm, the Requires eventually calls upon ContractHelper.RaiseContractFailedEvent, but later on throws the exception which we have wanted
The exception message comes after the string Precondition failed :arg1!=null.
PostCondition
Postcondition runs your code and throws the exception after it successfully executes it. Contract.Ensures lets you define a Postcondition for your application. The Code contract tool adds up your required code to deal with the post condition. If I change the code a little bit it will look like
public void OfferMeValues(string arg1, string arg2) { Contract.Requires<ArgumentNullException>(arg1 != null, "arg1 cannot be null"); Contract.Requires<ArgumentNullException>(arg2 != null, "arg2 cannot be null"); Contract.Ensures(arg1.Trim().Length > 0 && arg2.Trim().Length > 0, "No argument can be empty"); Contract.Ensures(!arg1.Equals(arg2), "Cannot work on identical parameters, Parameter : arg1, arg2"); //here goes your actual logic Console.WriteLine("We ensure objects are not null, not empty and not equal"); }
Now as static checker is turned on, I generate the exception at runtime just by changing the code a little :
ContractInvoker invoker = new ContractInvoker(); string x = Console.ReadLine(); string y = Console.ReadLine(); invoker.OfferMeValues(x, y);
Now if I put same string for both the input, it will throw you the exception as supposed.
First of all I should notify in this, that Contact.Old(arg1) is just a string variable. So beware of this while you see the internal code. So first it calls the Preconditions that I applied in the same way as demonstrated earlier. It loads them to the string variable. Notice, every assignment is put inside try/catch block (may be this is because it doesn’t know if cast is valid or not). But I doubt if these try/catch is required, may be it could automatically throw the exception if cast is invalid. What do you think ?
Finally it calls upon __ContractRuntime.Ensures to run your post conditions.
The __ContractRuntime.Ensures looks like :
So it’s the same code.
Invariants
Well, so far as we understand, Precondition and PostCondition works only when there is a caller for the program. Invariant works little differently. Invariants are special conditions which should evaluate to true before and after the execution of the code. Hence it ensures that the object will follow the conditions even if you have subtypes of it, you have overridden methods, for every method block like properties, events, methods etc. Hence Invariants ensures that there will never be a situation for the entire object where the condition fails.
To work with invariants you need to create a method which infers the conditions. Lets create one :
[ContractInvariantMethod] private void ContractInvariant() { Contract.Invariant(!this.Argument1.Equals(this.Argument2), "Cannot work on identical parameters, Parameter : arg1, arg2"); }
Here you should note ContractInvariantMethod is a special attribute that designate the method to be holding Invariant conditions. You are not allowed to write anything other than Contract.Invariant sequence in this method. If you do, you will be shown an error message :
Now if you put a breakpoint on the Invariance method, you will see that the method will be called as soon as you are about to create the object. Now let me check the Reflector to see what it writes for us.
Hence you can see, for every call to any method inside the block the contract ensures that the Invariant condition is satisfied. The invariant method sets #evaluatingInvariant$ to false only if the object contract fails. Similar to others, __ContractsRuntime.Invariant will report you the failure.
Static Checker
Well, as far as we have discussed, Code contract ensures that your condition is satisfied before running the code. Now you might be thinking, you can do this even with some static utility methods. What makes it so different?
The difference lies in the static checker. Visual studio builds a special assertion statement that ensures each contracts are true even before running the actual code. So even though you are not evaluation the actual code, you can get warnings on where the exceptions might occur while you build the application.
Static Checker ensures that every possible ways of calling the code satisfies the conditions. Let me show you how you can enable static checker. Go to properties panel of the project and check Perform Static Contract Checking checkbox.
Once you enable the static checker, the MSBuild will invoke the contract assertions before building the project. You can see the warnings put in the warning pane which lets you detect which contracts might be failed during the process.
You can see a number of warnings placed on the pane which is provided by the static checker.
Some other Methods
We have already understood about Ensures, Requires and Invariant methods. Now let me try few other methods available with Code contract.
1. Contract.Assume : It gives you a chance to make an assumption to the static checker that the condition is satisfied. Contract.Assume can be used anywhere in the code in comparison to Requires or Ensures that might be used only to the beginning of the block. Contract.Assume checks at an intermediate point of the code before calling a method that explicitly defines the Contract.
string x = Console.ReadLine(); string y = Console.ReadLine(); Contract.Assume(x != null); Contract.Assume(y != null); invoker.OfferMeValues(x, y);
This will ensure that the invoker.OfferMeValues will never be null to the static checker even though the values are coming from a method which never uses a contract.
2. Contract.Exists / ForAll : Expresses constraint for a collection.
3. OldValue / Result: Gets you the OldValue or ReturnValue before the code gets executed.
public int CurrentValue {get;set;} public void IncrementBy(int value) { Contract.Ensures(this.CurrentValue == Contract.OldValue<int>(this.CurrentValue) + value); this.CurrentValue += value; }
Here the oldValue can be retrieved from Contract.OldValue, so that it ensures that the value is always valid for the block.
There is also a few other methods which are used very rarely.
Contracts for Interfaces
Well, you are not restricted to write contracts only for a well defined class. Many of us like me, who writes libraries can use interface and add Contract to that interface beforehand for the library. Lets see how you can do this :
[ContractClass(typeof(HumanContract))] public interface IHuman { //Lets make Name a mandatory string Name { get; set; } int Age { get; set; } void GreetMe(); } [ContractClassFor(typeof(IHuman))] public abstract class HumanContract : IHuman { #region IHuman Members public abstract string Name { get; set; } public abstract int Age { get; set; } public void GreetMe() { Contract.Ensures(!string.IsNullOrEmpty(this.Name)); Contract.Ensures(this.Age > 0); Contract.Ensures(this.Age < 100); } #endregion }
Here we want our interface IHuman to ensure a contract that Name cannot be null or empty and Age should be between 1 to 99. We use an abstract implementation of the interface to define the Contract. ContractClass lets you define the type of the Contract class and ContractClassFor defines the type of the interface.
Hence when we create a concrete type from IHuman, the method will automatically get the contract from the buddy class.
Now if you try to see what happens through Reflector, you will see there is no existence of HumanContract type rather the class which implements the interface IHuman automatically gets the contracts from HumanContract.
public class People : IHuman { public People(string name, int age) { this.Name = name; this.Age = age; } #region IHuman Members public string Name { get; set; } public int Age { get; set; } public void GreetMe() { Console.WriteLine("Hi {0}, Your age is {1}", this.Name, this.Age); } #endregion }
Now the People class will look like :
The contract will be automatically put from the Contract we define in HumanContract abstract class.
When it comes in terms of performance ?
This might come to your mind, that even though we have a concrete Code Contract feature, can we turn off the feature when it is ported at runtime. Well, I must not recommend you to disable runtime checking, but if you are using an application for end user (not a library) and ensure that everything is ok, you can turn off Runtime Checking before releasing the code. This will help you performance gain, even though you can still get warnings from Static Checker. To turn off the Runtime checking, go to Properties again and uncheck “Perform Runtime Checking” checkbox.
This will ensure that the assembly will not hold any runtime Contracts.
FAQ on Code contracts
Conclusion
Code contract is one of the major improvement to the .NET library. In spite of normal exception handling and validation of code, it enables you to put your logic way above the abstraction level. It lets you define your own code contract and ensure that the contract satisfied even before the actual exception occurs. The Static Checker helps to assert conditions before the actual execution of code thereby preventing you to have any runtime exception.
You can download the sample code from :
Download CodeContract Sample - 44KB
I hope most of you will use this lovely feature.
Thanks for reading.
I read a lot about code contracts and even tried using VS 2010. I saw it never work. Also I feel this concept is difficult to implement that general if-else code validation and checking.
ReplyDelete@gaurav
ReplyDeleteI think you need to install http://msdn.microsoft.com/en-us/devlabs/dd491992 extension for Static Checker.
Static checker doesn't work in VS2010 professional edition
ReplyDelete@Anonymous
ReplyDeleteI am using Professional version, but it works in it.
@Abhishek
ReplyDeleteYou must be mistaken about the version of Visual Studio you are running. The static checker is not available in VS 2010 Professional. I've already tried and it gives an error when you try to install it under Professional.
Quotes From the link you provided on 2-20-11:
>"Static Checking. Our static checker can decide if there are any contract violations without even running the program! It checks for implicit contracts, such as null dereferences and array bounds, as well as the explicit contracts. (Premium Edition only.)"
>"Code Contracts Premium Edition: This version installs only if you have one of the following: Visual Studio 2008 Team System, Visual Studio 2010 Premium Edition, or Visual Studio 2010 Ultimate Edition. It includes the static checker in addition to all of the features in the Code Contracts Standard Edition."
Notice that the Professional version is not included.
I have tried it and as far as I know static checker is available only in VS Premium and ultimate edition though you can make runtime validations happening using contracts by downloading the libraries from devlabs. You may need to double check your version of VS.
ReplyDeletenevertheless article is good, keep it up.
@Abhishek
ReplyDeleteYes. Sorry its my bad. My version is Ultimate.
Thanks for your info.