Click here to Skip to main content
15,884,388 members
Articles / Programming Languages / C#

My Practise On Design By Contract. in C#.

Rate me:
Please Sign up or sign in to vote.
1.00/5 (5 votes)
2 Dec 2009CPOL5 min read 272.5K   6   22
My Practise On Design By Contract. in C#.

Introduction

Recently I try to develop a verification framework to reduce the bug in system. And I come to Design by Contract(DbC). The idea of DbC is indeed great! But, there are still no workable practise now. So I work out one.

Updated 2009-12-02 200400: Many people still don't know what I want to say.. So I refactoring the article.

Background

Design by Contract was first introducted by Bertrand Meyer. You can visit the homepage: Design by Contract, EIFFEL. the guy also develop the Eiffel for DbC.

In dotnet, we also have some talent work on DbC, for example: Spec#,LinFu. But all of them just try to deveop a new language(spec#), or use AOP(LinFu), or use Attribute(Microsoft...en.). What's the result? Still in the mess.

Why Design by Contract cannot be the main stream in OO, in XP? Because all of them walk to the wrong direction. So... Please take a look on my job.

Using the code

In Design by contract, when we write a method in class, we assume the user should meet the Constraints of the method, then the method would return the committed result. This is DbC. Like the follow code:

public class Log
{
    public void Info(string message)
    {
        //do something here
    }
}

When I want to call Log.Info, the message must be NOT NULL, otherwise, the function would not assume to return the correct result.

Previously, We would try to check the message in Info.

public class Log
{
    public void Info(string message)
    {
     if(string.IsNullorEmpty(message))
       throw new Exception("missing message.");

        //do something here
    }
}
This is called: Defence Programming. However, if the case become complicated, we would find thousands of defence codes in our business logic. THIS IS REALLY SAD!!!

Updated 2009-12-02:What's happen in .net framework 4.0? take a look at: microsoft .net 4.0 design by contract

public class Log
{
     public void Info(string message)
     {
      CodeContract.Requires(null != message);

      //do something here
     }
}
Now, take a break, and think it twice. Is there any changes to the previous code? Maybe microsoft would said, It is design by contract, when complie the code, we would get the warning...blablabla..

PLEASE STOP LYING TO YOURSELF. If it is really what you think, why not use it everwhere? (Because sometimes we are already sure that the code is correct.) So why there are still many bugs? (Well.. Some mistakes cannot be caught by DbC.) Ok.. Please stop giving any excuse. I tell you the truth.

The ability of computer language is limited, but the requirement of human being is complicated. Microsoft have develop a great tool call .net, and the language call c#. It can meet most of the human requirements, and translate the requirements into machine code. But in design by contract, it is another story.

If we follow the traditional way, whatever kind of technique we use, we would find that the time we spend on writing CONTRACT is as much as we spend on BUSINESS LOGIC. Finally, half of the code is contract. SO that's the reason why we do not accept DbC.

To judge the input parameter is not null, it is very simple. But, if we pass a object? if the object contains another object? If... So, if we still want to write down the contract as computer language(c#/java/ whatever), we are just wasting our time. We need another idea.

Design by Contract do not support Defence Programming.

Unfortunately, even Microsoft still work on Defence Programming.. Please see the Spec#.... SO I try to walk into another way.

First, I set a Constraint on Log.Info

public class Log
{
    [Contract.Constraint("message is not null")]
    public void Info(string message)
    {
        //do something here
    }
}
In the code above, I actually do nothing but set a attribute on the method.

Then, I try to call the method, Log.Info, like follow:

public class TestCase
{
    public void call001()
    {
        string message = "hello world";
        Log log = new Log();
        log.Info(message);
    }
}
It work. Right? Of course. So is there something to do with Design by Contract? Be patient, we still do not verify the contract.

public class TestCase
{
    public void test001()
    {
        MethodInfo method = typeof(TestCase).GetMethod("call001");

        Console.WriteLine("check the call001 can be approved by contract.");

        Console.WriteLine("approval result = :" + Contract.Approval(method));

        foreach (IConstraint cons in Contract.GetOpenConstraints(method))
        {
            Console.WriteLine("the constraint of \"" + cons.ConstraintName + "\" is not committed.");
        }
    }
    public void call001()
    {
        string message = "hello world";

        Log log = new Log();

        log.Info(message);
    }
}
In Testcase.test001, I use 'Contract.Approval' to verify the method call001. and get the result:
check the call001 can be approved by contract.
approval result = :False
the constraint of "message is not null" is not committed.
It means, the constraint of Log.Info is not committed in call001, so call001 is not a valid method. Now you can feel something about Design by contract. What to do next? READ THE CONTRACT, and FOLLOWING THE CONTRACT. for example above, we are definitely sure message is not null, then go no next example:
public class TestCase
{
    public void test002()
    {
        MethodInfo method = typeof(TestCase).GetMethod("call002");

        Console.WriteLine("check the call002 can be approved by contract.");

        Console.WriteLine("approval result = :" + Contract.Approval(method));

        foreach (IConstraint cons in Contract.GetOpenConstraints(method))
        {
            Console.WriteLine("the constraint of \"" + cons.ConstraintName + "\" is not committed.");
        }
    }
    [Contract.Commitment("input of log is not null")]
    public void call002()
    {
        string message = "hello world";

        Log log = new Log();

        log.Info(message);
    }
}
In this case, call002 call the Log.Info, but I set a Contract.Commitment on call002. It is committed that input of log is not null. So When I run test002, I got:
check the call002 can be approved by contract.
approval result = :True
YES!GREAT! PASS! It is what I need! So, now you can understand what I mean.

So.. aha..yes, I do not use machine to verify the constraint. But, instead, I apply Design by Contract on CODING, on 'DESIGN'. This is what I want, and I believe, THIS IS design by contact.

Summary

When problem comes, find the simplest solution. It is the best solution. Design by Contract is not a new Language, not the coding, not some around our code. Design by Contract is a Practise, just like TestDriven. I believe Design by Contract would become something in XP, and become the friend of TestDriven.

Update 2009-12-02: Man, we are living by creating, not by copy/paste, not by downloading. Design by contract is a practise. Not a new language, or some attribute/ or AOP.

If some day in future, when we write down a method name: call001(), it use the method in microsoft .net framework 12.0, the method is Log.info

public void call001()
{
    string message = "hello world";

    Log log = new Log();

    log.Info(message);
}
and after complieing the code, VS2020 show me the warning that log.Info have the contract = 'message is not null' that we need to commit, then you would finally understand my work.

Well, typing every single word from my mind is very tired. Hope someone in future can use JUMP THINKING to read my article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer Pixysoft.net
China China
Working on database for 5 years, and develop many framework.

Skilled on persistency layer/ ORM / database consistency ..

Comments and Discussions

 
GeneralMy vote of 1 Pin
Philip Laureano11-Feb-10 17:40
Philip Laureano11-Feb-10 17:40 
GeneralMy vote of 1 Pin
Alexander Müller3-Dec-09 9:00
Alexander Müller3-Dec-09 9:00 
GeneralA joke here, and let you try to think twice of my idea. Pin
reborn_zhang2-Dec-09 22:19
reborn_zhang2-Dec-09 22:19 
GeneralMy vote of 1 Pin
Adam Robinson2-Dec-09 3:15
Adam Robinson2-Dec-09 3:15 
GeneralRe: My vote of 1 [modified] Pin
reborn_zhang2-Dec-09 21:45
reborn_zhang2-Dec-09 21:45 
GeneralRe: My vote of 1 Pin
Adam Robinson3-Dec-09 3:08
Adam Robinson3-Dec-09 3:08 
GeneralNot sure I understood Pin
Nicolas Dorier2-Dec-09 2:36
professionalNicolas Dorier2-Dec-09 2:36 
GeneralRe: Not sure I understood Pin
reborn_zhang2-Dec-09 21:57
reborn_zhang2-Dec-09 21:57 
Generalsometimes [modified] Pin
reborn_zhang1-Dec-09 22:06
reborn_zhang1-Dec-09 22:06 
GeneralRe: sometimes Pin
Adam Robinson2-Dec-09 11:30
Adam Robinson2-Dec-09 11:30 
GeneralRe: sometimes Pin
reborn_zhang2-Dec-09 22:00
reborn_zhang2-Dec-09 22:00 
GeneralRe: sometimes Pin
Adam Robinson3-Dec-09 3:15
Adam Robinson3-Dec-09 3:15 
GeneralRe: sometimes Pin
reborn_zhang3-Dec-09 3:22
reborn_zhang3-Dec-09 3:22 
We do not need to focus on this point.

I have write another article: My Practise On Design By Contract. in C# Advanced

But, maybe I can do a little defencing. No one's job is meaningless. What happen to you, if your BOSS say, your job is meaningless, after you write a paper.

I use code contract in my project, so I feel the trouble of current .net 4.0, or SPEC#, or LinFu.

You can try to write some contracts.

I believe the people left 'I vote 1' here had never used code contract in their project.
GeneralRe: sometimes Pin
Adam Robinson3-Dec-09 3:36
Adam Robinson3-Dec-09 3:36 
GeneralRe: sometimes Pin
reborn_zhang3-Dec-09 3:46
reborn_zhang3-Dec-09 3:46 
GeneralRe: sometimes Pin
Adam Robinson3-Dec-09 4:03
Adam Robinson3-Dec-09 4:03 
GeneralRe: sometimes Pin
reborn_zhang3-Dec-09 3:54
reborn_zhang3-Dec-09 3:54 
GeneralRe: sometimes Pin
Adam Robinson3-Dec-09 4:01
Adam Robinson3-Dec-09 4:01 
GeneralMy vote of 1 Pin
SuperToha1-Dec-09 21:48
SuperToha1-Dec-09 21:48 
GeneralMy vote of 1 Pin
hammerstein051-Dec-09 11:58
hammerstein051-Dec-09 11:58 
GeneralMy vote of 1 Pin
Alexander Müller1-Dec-09 9:44
Alexander Müller1-Dec-09 9:44 
GeneralRe: My vote of 1 Pin
reborn_zhang1-Dec-09 22:04
reborn_zhang1-Dec-09 22:04 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.