Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I recently stumbled upon Microsoft's framework for code contracts.

I read a bit of documentation and found myself constantly asking: "Why would I ever want to do this, as it does not and often cannot perform a static analysis."

Now, I have a kind of defensive programming style already, with guarding exceptions like this:

if(var == null) { throw new NullArgumentException(); }

I'm also using NullObject Pattern alot and have rarely any problems. Add Unit Tests to it and you're all set up.

I have never used asserts and never missed them. Quite the contrary. I really hate code that has lots of meaningless asserts in it, which is just noise to me and distracts me from what I really want to see. Code contracts, at least the Microsoft way are much the same - and even worse. They add lots of noise and complexity to the code. In 99% an exception will be thrown anyway - so I don't care whether it's from the assert/contract or the actual problem. Just very, very few cases remain in which the program states really becomes corrupted.

So frankly, what is the benefit of using code contracts? Is there any at all? If you already use unit tests and code defensively I feel that introducing contracts is just not worth the cost and puts noise in your code that a maintainer will curse when he's updating that method, much like I do when I cannot see what the code is doing due to useless asserts. I have yet to see a good reason to pay that price.

share|improve this question
    
1  
Why do you say "it does not and often cannot perform a static analysis"? I thought that was one of the points of this project (as opposed to just using Asserts or defensive exception throwing)? –  Carson63000 Sep 13 '13 at 4:17
    
@Carson63000 Read the documentation carefully and you'll find that the static checker will just output lots and lots of warnings, most unecessary, (the developers admit it to be so) and that most defined contracts will just throw an exception and do nothing besides. –  Falcon Sep 13 '13 at 6:28
    
@Falcon: strangely, my experience is completely different. Static analysis works not flawlessly, but pretty well, and I rarely see unnecessary warnings, even when working at warning level 4 (the highest). –  MainMa Sep 13 '13 at 6:48
    
I guess I'll have to try it to find out how it behaves. –  Falcon Sep 13 '13 at 8:28

3 Answers 3

up vote 21 down vote accepted

You might just as well have asked when static typing is better than dynamic typing. A debate that has been raging for years with no end in sight. So have a look at questions like Dynamically vs Statically typed languages studies

But the basic argument would be the potential to discover and fix issues at compile time that might otherwise have slipped into production.

Contracts vs. Guards

Even with guards and exceptions you are still faced with the issue that the system will fail to perform it's intended task in some instance. Possibly an instance that will be quite critical and costly to fail at.

Contracts vs. Unit tests

The usual argument on this one is that tests prove the presence of bugs, while types (contracts) prove the absence. F.ex. using a type you know that no path in the program could possibly supply invalid input, while a test could only tell you that the covered path did supply the correct input.

Contracts vs. Null Object pattern

Now this is at least in the same ball park. Languages like Scala and Haskell has had great success with this approach to eliminating null references entirely from programs. (Even if Scala formally allows nulls the convention is to never use them)

If you already employ this pattern to eliminate NREs you've basically removed the largest source of runtime failures there is in basically the manner contracts allow you to do it.

The difference might be that contracts has an option to automatically require all your code to avoid null, and thus force you to use this pattern in more places to pass compilation.

On top of that contracts also give you the flexibility to target things beyond null. So if you no longer see any NRE in your bugs you might want to use contracts to strangle the next most common issue you might have. Off by one? Index out of range?

But...

All that being said. I do agree that the syntactic noise (and even structural noise) contracts add to the code is quite substantial and the impact the analysis has on your buildtime should not be underestimated. So if you decide to add contracts to your system it would probably be wise to do so very carefully with a narrow focus on which class of bugs one tries to address.

share|improve this answer
2  
That's a great first answer on Programmers. Glad to have your participation in the community. –  GlenH7 Sep 13 '13 at 0:03

I don't know where the assertion that "it does not and often cannot perform a static analysis" comes from. The first part of the assertion is plainly wrong. The second one depends of what you mean by "often". I would rather say that often, it performs static analysis, and rarely, it fails at it. In ordinary business application, rarely becomes much closer to never.

So here it comes, the first benefit:

Benefit 1: static analysis

Ordinary assertions and argument checking have a drawback: they are postponed until the code is executed. On the other hand, code contracts manifest themselves at a much earlier level, either at the coding step or while compiling the application. The earlier you catch an error, the less expensive it is to fix it.

Benefit 2: sort of always up to date documentation

Code contracts also provide a sort of documentation which is always up to date. If the XML comment of the method SetProductPrice(int newPrice) tells that newPrice should be superior or equal to zero, you may hope that the documentation is up to date, but you may also discover that somebody changed the method so that newPrice = 0 throws an ArgumentOutOfRangeException, but never changed the corresponding documentation. Given the correlation between code contracts and the code itself, you don't have the out-of-sync documentation problem.

The sort of documentation provided by code contracts is also precious in a way that often, XML comments don't explain the acceptable values well. How many times was I wondering if null or string.Empty or \r\n is an authorized value for a method, and XML comments were silent on that!

In conclusion, without code contracts, lots of pieces of code are like that:

I'll accept some values but not others, but you'll have to guess or read the documentation, if any. Actually, don't read the documentation: it's outdated. Simply loop through all values and you'll see the ones which make me throw exceptions. You also have to guess the range of values which may be returned, because even if I would tell a bit more to you about them, it may not be true, given the hundreds of changes made to me for the last years.

With code contracts, it becomes:

The title argument can be a non-null string with a length of 0..500. The integer which follows is a positive value, which can be zero only when the string is empty. Finally, I'll return a IDefinition object, never null.

Benefit 3: contracts of interfaces

A third benefit is that code contracts empower interfaces. Let's say you have something like:

public interface ICommittable
{
    public ICollection<AtomicChange> PendingChanges { get; }

    public void CommitChanges();

    ...
}

How would you, using only asserts and exceptions, guarantee that CommitChanges can be called only when PendingChanges is not empty? How would you guarantee that PendingChanges is never null?

Benefit 4: enforce the results of a method

Finally, the fourth benefit is to be able to Contract.Ensure the results. What if, when writing a method which returns an integer, I want to be sure that the value is never inferior or equal to zero? Including five years later, after suffering from lots of changes from lots of developers? As soon as a method has multiple return points, Asserts become a maintenance nightmare for that.


Consider code contracts not only as a mean of correctness of your code, but a stricter way to write code. In a similar way, a person who used exclusively dynamic languages may ask why would you enforce types at language level, while you can do the same thing in assertions when needed. You can, but static typing is easier to use, less error-prone compared to a bunch of assertions, and self-documenting.

The difference between dynamic typing and static typing is extremely close to the difference between ordinary programming and programming by contracts.

share|improve this answer

Two things really:

  1. Tooling support, VS can make contract data apart of intellisence so that it is part of auto complete help.
  2. When a subclass overrides a method you lose all your checks (which should still be valid if you follow the LSP) with contracts they follow their child classes automatically.
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.