Geeks With Blogs
Josh Reuben

 

I've gotten used to Resharper's recommendation for defensive coding (see http://en.wikipedia.org/wiki/Defensive_programming) – never trust the client!

 

private void Bar(string x)
{
    if (x == nullreturn;

 

But how to get this to play with Design By Contract using Code Contracts?

I had a look at http://weblogs.asp.net/gunnarpeipman/archive/2010/05/05/code-contracts-hiding-contractexception.aspx - which shows me how to leverage the ContractFailed event and throw my own exceptions.

I don't want to throw exceptions – the user should not see exceptions and I don't want my exposed method calls to potentially unwind the call stack for performance reasons.

My preconditions should log and return. See http://bytes.com/topic/visual-basic-net/answers/349361-try-catch-vs-regular-defensive-programming and http://weblogs.asp.net/fredriknormen/archive/2007/11/28/defensive-programming-and-design-by-contract-on-a-routine-level.aspx for the argument.

The client should be wise enough to pass me decent data.

 

Contract.ContractFailed += new EventHandler<ContractFailedEventArgs>(Contract_ContractFailed);

 

 

        void Contract_ContractFailed(object sender, ContractFailedEventArgs e)
        {
            Log(e.Condition); 
            _isPreconditionFailure = (e.FailureKind == ContractFailureKind.Precondition);
            e.SetHandled();
        }

       

        private void Log(string condition)
        {
            Debug.Print(condition);
        }

 

I can then leverage this infra like so:

 

        public string Bar (string x)
        {
            Contract.Requires(x != null);
            if (_isPreconditionFailure)
            {
                _isPreconditionFailure = false;
                return string.Empty;
            }
            
            return x.ToUpper();
        }

 

 

And call the method (and see my static check squiggly lines):

 

            var x = p.Bar(null);

 

 

However, if I want to check multiple preconditions where 1 precondition is dependent upon another

 

            Contract.Requires(x != null);
            if (_isPreconditionFailure)
            {
                _isPreconditionFailure = false;
                return string.Empty;
            }
            Contract.Requires(x.Length > 0);
            if (_isPreconditionFailure)
            {
                _isPreconditionFailure = false;
                return string.Empty;
            }

– I get malformed contract section:

 

A Precondition contract block cannot contain assignments

I need to massage the code – replace Contract.Precondition with Contract.Assert

 

        public string Bar (string x)
        {
            _contractFailure = null
            Contract.Assert(x != null);
            if (_contractFailure != null)
            {
                _contractFailure = null;
                return string.Empty;
            }
            Contract.Assert(x.Length > 0);
            if (_contractFailure != null)
            {
                _contractFailure = null;
                return string.Empty;
            }
            
            return x.ToUpper();
        }

 

Now I have Design By Contract + Defensive Programming!

 

But… visual studio code contracts static check tells me Asserts are unproven.

From here - http://social.msdn.microsoft.com/Forums/en/codecontracts/thread/6d2d8ed0-d6a1-4f7d-8cbb-394a3da92b97

"The static checker's job is to point out all that could be going wrong. It tries to prove all contracts, and also all asserts. Now, clearly, the static checker is limited and there are many things it will not be able to prove. To express such cases, you can use another form of assertion called Contract.Assume. Contract.Assume behaves the same way as Assert for runtime checking. But for static checking, it tells the checker: 'Believe me, this should be true'. The static checker then simply takes advantage of the condition, without trying to prove it itself."

 

So I replaced Contract.Assert with Contract.Assume

 

        public string Bar (string x)
        {
            _contractFailure = null
            Contract.Assume(x != null);
            if (_contractFailure != null)
            {
                _contractFailure = null;
                return string.Empty;
            }
            Contract.Assume(x.Length > 0);
            if (_contractFailure != null)
            {
                _contractFailure = null;
                return string.Empty;
            }
            
            return x.ToUpper();
        }

 

Note: now that I am no longer using Contract.Precondition – is this still design by contract ? Pex thinks so – it picks up Assume to generate Asserts in PUTs. – see http://angler.wordpress.com/2010/02/01/code-contracts-pex-assertions-and-assumptions-for-expressive-tests/

Posted on Sunday, November 28, 2010 7:19 AM Meta-Programming | Back to top


Comments on this post: Code Contracts and Defensive Programming

# re: Code Contracts and Defensive Programming
Requesting Gravatar...
It's a great learning to understand now. It is worth reading now. - Morgan Exteriors
Left by Jaime Payne on Dec 30, 2016 3:26 PM

Your comment:
 (will show your gravatar)


Copyright © JoshReuben | Powered by: GeeksWithBlogs.net