Quantcast
Viewing latest article 4
Browse Latest Browse All 9

Design by Contract (DbC) and .Net 4.0 Code Contracts

After spending years developing software which collaborates with many other sub-systems, I have subconsciously developed affection for Design by Contract (DbC). When various system/ sub-systems are designed to communicating over SOAP or similar protocol through well defined data contacts, a degree of discipline is generally enforced by the development framework.  However, when we are designing a set of sub-systems which is Intend to communicate through in-process calls, it is very easy to violate clean-contract principle. It’s not that things are not going to work if contracts are not clearly defined, but it makes it very easy to maintain and troubleshoot in long run. Following is the formal definition of the Design by Contract (DbC) from Wikipedia entry.


Design by Contract (DbC) or Programming by Contract is an approach to designing computer software. It prescribes that software designers should define formal, precise and verifiable interface specifications for software components, which extend the ordinary definition of abstract data types with preconditions, post conditions and invariants.

So when I was going through the list of new features in .Net 4.0, Code Contract immediately caught my attention. In pre-4.0 versions of .Net, assertion is the feature we can use to express our design intent about the rules object needs to follow. However, it was more like developer’s internal sanity check. There is no way to expose these assertions to consumer of your library or performing any static or runtime analysis to see if any of the code is violating it. .Net 4.0 Code Contract will help to fill this vacuum.

We can think of .Net Code Contracts as ‘Assertions on steroids’. However, the set of tools built around it makes Code Contract very compelling. Code Contract resides in System.Diagnostics.Contracts namespace.  Currently, Code Contract is a separate download, you can download it from Microsoft DevLabs. It comes with dlls, documentation and samples in addition to Code Contract property pane for Visual Studio.  I am using Visual Studio 2010, Beta 2 but Code Contract works well with Visual Studio 2008 too. If you are running on .Net Framework 3.0/3.5, you need to add reference to Microsoft.Contracts.dll. If you are powered by .Net Framework 4.0 you need not worry as Code Contracts are bundled with mscodelib.dll (still you need to install the Code Contracts from DevLabs to get the property pane in Visual Studio). Following screenshot shows the Code Contract property pane you can use to configure various Code Contract related features.

Image may be NSFW.
Clik here to view.
CodeContractPropertiesPane

Following are three major flavors of the Code Contracts.

Method Contracts
It helps to express method level contracts which callers need to adhere to, in return methods can also promise to hold on to the result. Contract.Requires is used to impose condition on the method arguments (pre-condition). Whereas Contract.Ensure is used to define methods exit condition (post-condition).  You can use any code expression with Contract.Requires and Contract.Ensure which can yield Boolean.

Following is the simple example showing method contracts. I have used contract to ensure the order amount is greater than 0 and connection is open on method call ProcessOrders. I also imposed a condition on this method that the return value must be greater than or equal to 0.

   1:publicint ProcessOrders(int minimumOrderAmount)
   2: {           
   3:     Contract.Requires(minimumOrderAmount > 0, "Minimum order amount must be greater than 0.");
   4:     Contract.Requires(DataProvider.IsConnectionOpen);
   5://Order processing logic will go here
   6:     Contract.Ensures(Contract.Result<int>() >= 0);
   7:return 1; //dummy result
   8: }


Object Invariant
Object invariants can be used to express the conditions under which the object is in a "good" state. Object invariant conditions are applied to each instance of the class. During runtime checking, invariants are checked at the end of each public method. Object invariants need to be defined in instance method decorated with ContractInvariantMethod attribute. The invariant methods need to return void and could not contain code other than calls to Contract.

Following code snippet shows example of object invariant contract. As per this contract, the object of type DataProcessor can never have the dataProvider as null and dataProvider’s connection status as closed.

   1: [ContractInvariantMethod]
   2:void ObjectInvariant()
   3: {
   4:    Contract.Invariant(this.m_dataProvider != null );
   5:    Contract.Invariant(this.m_dataProvider.IsConnectionOpen);
   6: }

 
Interface Contract
Interface contract can be defined at the interface level and all the classes implementing that interface will have to abide by that contract. As .Net doesn’t allow to have any implementation code in interface definition, we need to define a separate class implementing that interface to define the code contracts. This class needs to be decorated with ContractClassFor attribute. Code Contract expects the interface to be implemented explicitly to avoid any ambiguity.

Following code snippet shows the interface contract for our sample interface IDataProvider. Please notice how the default is used to return some value to fulfill interface requirement.

   1:publicinterface IDataProvider
   2: {
   3:bool IsConnectionOpen{get;}       
   4:     List<Tuple<int, string, string, string>> GetOrders(DateTime orderDate);
   5:void AddOrders(List<Tuple<int, string, string, string>> orders);
   6: }
   7:  
   8: [ContractClassFor(typeof(IDataProvider))]
   9:sealedclass IDataProviderContract : IDataProvider
  10: {
  11:bool IDataProvider.IsConnectionOpen
  12:     {
  13:         get { returnfalse; } //dummy return
  14:     }
  15:  
  16:     List<Tuple<int, string, string, string>> IDataProvider.GetOrders(DateTime orderDate)
  17:     {
  18:         Contract.Requires(orderDate < DateTime.Now);
  19:         Contract.Ensures(Contract.Result<List<Tuple<int, string, string, string>>>() != null&& Contract.Result<List<Tuple<int, string, string, string>>>().Count > 0);
  20:returndefault(List<Tuple<int, string, string, string>>); //dummy return
  21:     }
  22:  
  23:void IDataProvider.AddOrders(List<Tuple<int, string, string, string>> orders)
  24:     {
  25:         Contract.Requires(orders != null&& orders.Count > 0);
  26:     }
  27: }


Following screenshot shows static analysis failures and warnings in Visual Studio.

Image may be NSFW.
Clik here to view.
CodeContractErrorsAndWarnings
 

Following screenshot shows the runtime code contract violation exception.

Image may be NSFW.
Clik here to view.
AssertFailure
 

Now as we have developed a bulletproof object API using Code Contracts, we need to put together extensive unit test cases to ensure nothing goes untested. We can use Microsoft DevLab’s Pex (Program EXploration) to generate ‘parameterized’ unit tests. You can download Pex from here. Following is the definition of parameterized unit test.


A parameterized unit test is simply a method that takes parameters, calls the code under test, and states assertions. Given a parameterized unit test written in a .NET language, Pex automatically produces a small unit test suite with high code and assertion coverage. To do so, Pex performs a systematic white box program analysis.

Pex will require a blog post of its own to cover all the aspects. Following is just a brief outline of how it can be used with Code Contracts.

Following screenshot shows Pex Explorer with various parameterized unit tests identified for our test project.

Image may be NSFW.
Clik here to view.
PexExplorer


Following screenshot shows the Pex test execution result. You can see that Pex executed 3 tests on our XMLDataProvider constructor which accepts string as a parameter. First unit test passes null parameter to our constructor, second passes the empty string and third passes some random string.

Image may be NSFW.
Clik here to view.
PeXExplorerResult

You can even save these unit tests as a project in the unit testing framework of your choise. Following screenshot shows various unit testing frameworks currently supported by Pex.

Image may be NSFW.
Clik here to view.
PexTestFrameworkSelector
 
You can generate your code documentation using Sandcastle, however you need to patch the Sandcastle to create section for contracts. Code Contract download provides set of XSL which you need to copy to Sandcastle directory.

I hope you enjoyed this post. You can leave comments for your feedback.



Image may be NSFW.
Clik here to view.

Viewing latest article 4
Browse Latest Browse All 9

Trending Articles