Code contracts - Is it only about argument validation?

*Updated* 3 April 2011: Update how to enable Intellisense for code contracts

 

There are more and more articles coming out about Code Contracts. Some of them talk only about input validation and miss the goal of Code Contracts. What else can we do with Code Contracts?

image
Figure: Real world validation message


Microsoft DevLabs says: Code Contracts express coding assumptions

 

question_and_answer[5] What are coding assumptions?

Assumptions are expectations on your object state that need to be fulfilled. Those expectations are expressed in the form of

  1. Pre-conditions
  2. Post-conditions and
  3. Object invariants

The tools that check these expectations are the "Runtime checker" and the "Static Checker"

 

 

What we typically see is that people use Code Contracts to verify input values, because we trust no one.

Trust No One
Figure: Trust No One. Validate input from the user

But there is more…
Before you read on, check out Kevin Hazzard blog post series about Code Contracts

 

 

Good usages of Code Contracts

#1 Express assumptions on interfaces

By expressing assumptions on interfaces, every implementer of that interface needs to fulfill that contract in order to be valid. This was not easily possible without code contracts.
Note: One way before Code Contracts could have been: Convert the interface to an abstract class and have all your expectations in there.

A nice sample of using Code Contracts on interfaces can be found on Kevin Hazzard's blog post about Code Contracts Part 5 - Abstract Types and Interfaces

 

 

#2 Guidance for test tools

Test generation tools like Pex are able to read and understand your Code Contract assumptions and generate test input data that considers those Code Contracts.

Nice video from PDC about Pex with Code Contracts

 

 

#3 Contract inheritance = Assumptions for all inheritors

A nice sample for "Contract inheritance" is the abstract class "TextReader" in System.IO with the "Peek" method

        public virtual int Peek() 
        { 
            Contract.Ensures(Contract.Result<int>() >= -1);
 
            return -1;
        }

Figure: "Peek" method in "TextReader.cs" with a Code Contract

Every inheritor, like "StringReader"and "StringReader" have to follow that contract, which means they have to make sure to return a value greater equals than "-1" in the "Peek" method.

How powerful is that!

Another nice example can be found on Code Contracts Part 4 - Object Invariants

 

 

What I love about Code Contracts

#4 The "Static Checker" spots bugs before you even run your application

The Static Checker checks your code contracts assumptions on compile time and tells you if you break some. (at least those that it can check)
This speeds up bug discovery and tightens the feedback loop.

Spot the bug
Figure: Spot the bug --> here is the solution http://www.flickr.com/photos/rockman/5316118/

 

 

#5 Code Contracts give you a standard notation for assumptions expressed in code

Code Contracts give you a standard way to express input validation, and as you know I like standards.

        public Report GetReport(int employeeId, DateTime reportDate, string usercode)
        {
            if (employeeId <= 0) { throw new ArgumentOutOfRangeException("employeeId"); }
            if (reportDate.Date >= DateTime.Now.AddDays(1).Date)
            {
                throw new ArgumentOutOfRangeException("reportDate");
            }

            if (string.IsNullOrEmpty(usercode))
            {
                employeeId = Constants.ViewerUsercode;
            }

            // TODO: Do something 
            return null;
        }
bad Bad: Validation code is all over the place and is written "inverted" (A "reportDate" greater than tomorrow is not allowed)

 

        public Report GetDailyReportCardWithContract(int employeeId, DateTime reportDate, string usercode)
        {
            Contract.Requires(employeeId > 0);
            Contract.Requires(reportDate.Date < DateTime.Now.AddDays(1).Date);
            Contract.Requires(string.IsNullOrEmpty(usercode) == false);

            // TODO: Do something 
            return null;
        }
good Good: Validation is expressed in a a code Contract and is easy to understand

 

 

#6 Intellisense shows you contracts during coding  

How cool is this: Intellisense shows coding assumptions during coding. 
What does each method require (pre) and what can I expect after the method call (post)

clip_image002 
Figure: Intellisense brings up Pre and Post conditions

 

image
Figure: In order to get Intellisense you need to "Build" the "Contract Reference Assembly" - Thanks Mike
If that doesn't work, close and reopen the solution. If that doesn't work, turn lights off, restart computer and turn lights on.

 


6 great reasons to start using Code Contracts today!
Now go ahead:

  1. Install the latest Code Contracts
  2. Install the Code Contracts Editor Extension for Visual Studio 2010
  3. Enable Code Contracts in the properties of your project pane
  4. Build your code
  5. Have fun!!!!

 

References

Code Contracts Chapter from the book C# in Depth by Jon Skeet

Code Contracts Primer blog series from Derik Whittaker

Code Contracts FAQ

 

 

BTW
Make sure to checkout http://www.pexforfun.com/
Pex for fun

 

And

Trust No One
image

5 comments:

Anonymous said...

Check out the VS gallery plugin "Code Contracts Editor Extensions". It provides you with intellisense for code contracts and also shows you contracts on libraries when you use F12.

Peter Gfader said...

@Anonymous
Thanks!

Done.
Installed the Extension but still no Intellisense showing up for *my own* contracts

Found the answer on StackOverflow
Changing
DefineConstants DEBUG;TRACE
in the csproj files to DEBUG;TRACE;CONTRACTS_FULL
shows Code contracts of my own code in Intellisense.

From
http://stackoverflow.com/questions/3461972/am-i-implementing-this-simple-contract-incorrectly/3461992#3461992

WOOHOO...Sweet!


Note: I switched from Resharper Intellisense to VS2010 Intellisense.

With Resharper Intellisense I can bring up "VS2010 Quick Info" and see the Contracts.
Ctrl+K,I

Mike Barnett said...

You might not want to define the CONTRACTS_FULl symbol directly: it is better to use the "Code Contracts" pane in your project properties page to control the tools. You should see your own contracts in Intellisense if you choose the "Build" option for the "Reference Assembly" pull-down. If not, please let us know so we can fix that!

Peter Gfader said...

@Mike
I get Intellisense only by manually defining that constant. Changing the project properties did not work.

Peter Gfader said...

Choosing the "Build" option for the "Reference Assembly" pull-down works. Thanks Mike

Post a Comment

Latest Posts

Popular Posts