Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code Contracts what to do with exceptions

My main question is what to do with those Exceptions that I throw ?

For example:

 Contract.Requires(foo != null);

What to do in uper levels of the function call with this thrown exception ?

Should I ignore it , and just when I see it know that something wrong with my design and fix it ?

But what would happen in deployment if I deploy without the Contracts and I will get an argument that is foo == null ,and my logic has no clue how to deal with argument like this .Then everything will crash .

Could someone explain how to deal with all those scenarios ?

Thanks

like image 633
Night Walker Avatar asked Nov 29 '22 17:11

Night Walker


2 Answers

My main question is what to do with those Exceptions that I throw?

First of all, you technically cannot catch these exceptions. All methods except Contract.Requires<TExc>() throw a System.Diagnostics.Contracts.__ContractsRuntime.ContractException which is embedded into your assembly and is private. In order to catch it you'd have to catch all exceptions which is the worst thing you could do.

Contracts as well as assertions are conditions that must always be true. If they are not, then the program is in a state that it has not been designed for, and you cannot be sure if it can continue safely. You can think of contracts as of extensions to the language. You don't expect a .NET program to let you violate type safety in 'a special case', do you? The same is true for contracts.

What to do in uper levels of the function call with this thrown exception?

The whole idea of contracts is enforcing the caller to check before calling a method with contracts. And if the caller doesn't check and does something wrong - it must be fixed. I mean: if you have a method with Contract.Requires(arg != null), well, then don't call it if you have a null value.

Another question is 'should you leave all contracts in released bits or not?' From the safety position, you'd better keep them all.

If your code doesn't expect some values but it gets them, the only absolutely safe decision is halting the current operation with an error. You cannot be sure that if you ignore your contract you won't corrupt data or do other bad things. Of course, you need some degree of granularity to let your program continue in a safe state instead of terminating with a big bang, although in some cases termination is required.

Should I ignore it , and just when I see it know that something wrong with my design and fix it?

If you release your software and discover that there is a use case that doesn't work because of a contract failure, it probably wouldn't work even if there were no contracts - you just haven't thought it over and have to do some extra work to support it. You should worry about carefully designing all use cases and carrying out thorough QA to avoid this. Contracts have no relation to these issues.

But what would happen in deployment if I deploy without the Contracts and I will get an argument that is foo == null, and my logic has no clue how to deal with argument like this. Then everything will crash.

This is another reason for leaving the contracts in place. It's better to have a crash in a pre-designed place than somewhere you don't expect it to happen.

Perhaps, the only significant reason to remove some contracts is performance: checking invariants after each method may be very costly.

like image 75
Pavel Gatilov Avatar answered Dec 01 '22 08:12

Pavel Gatilov


Code Contracts allow you to more precisely declare what arguments your method accepts and also what it returns (preconditions and postconditions). Instead of having a function that accepts a string (any string) you can declare that the string should be non-null, have a length greater than 10, be entirely made up of upper case characters etc.

If the caller doesn't adhere to the contract it is an error and should be reported as such (e.g. an exception should be thrown). However, putting Contract.Requires() statements in your source doesn't generate any actual IL code. You have to run the Code Contracts rewriter to postprocess your code. This will insert contracts check into the final IL and these checks will throw exceptions if the contract is not adhered to.

You can also use the Code Contracts static checker to prove that contracts are enforced throughout your code. If that is true you can instruct the rewriter to not insert checks as you have already proven that contracts are always adhered to. With a public API you cannot do that because the static checker don't know how your code will be called. However, if you have declare code contracts on your public API your caller can use the static checker to verify that his code is correct.

So to answer your question, you should expect your caller to adhere to your contract. You should use the rewriter to insert checks and fail in a controlled maner if in fact the caller doesn't adhere to your contract.

MSDN Magazine has an article about Code Contracts that is a good starting point for learning about the concepts.

like image 44
Martin Liversage Avatar answered Dec 01 '22 08:12

Martin Liversage