13

I am a somewhat defensive programmer and a big fan of Microsofts Code Contracts.

Now I cannot always use C# and in most languages the only tool I have is assertions. So I usually end up with code like this:

class
{       
    function()
    {   
         checkInvariants();
         assert(/* requirement */);

         try
         {
             /* implementation */
         }
         catch(...)
         {
              assert(/* exceptional ensures */);                  
         }
         finally
         {
              assert(/* ensures */);
              checkInvariants();
         }
    }

    void checkInvariants()
    {
         assert(/* invariant */);
    }
}

However, this paradigm (or whatever you would call it) leads to a lot of code cluttering.

I have started to wonder if it is really worth the effort and whether proper unit test would already cover this?

ronag
  • 1,179
  • 1
  • 10
  • 18
  • 6
    While unit tests allow to move assertions out of the application code (and therefore avoid cluttering), consider that they cannot check everything that can happen in the real production system. So IMO code contracts have some advantages, especially for critical code where correctness is particularly important. – Giorgio Dec 09 '13 at 09:42
  • So it's basically development time, maintainability, readability vs better code coverage? – ronag Dec 09 '13 at 09:57
  • 1
    I am mostly using assertion in code to check parameters correctness (on null for example) and in unit test additionally check those assertions. – artjom Dec 09 '13 at 12:05

6 Answers6

14

I don't think you should think of it as "vs".
As mentioned in comments by @Giorgio, code contracts are to check invariants (in production environment) and unit tests are to make sure you code works as expected when those conditions are met.

duros
  • 2,464
  • 1
  • 21
  • 25
  • 2
    I think it's also important to test whether the code works (e.g. it throws an exception) when the conditions are *not* met. – svick Dec 12 '13 at 20:39
6

Contracts help you with at least one thing that unit tests don't. When you are developing a public API you can't unit test how people use your code. You can however still define contracts for your methods.

I personally would be this rigorous about contracts only when dealing with public API of a module. In many other cases it probably isn't worth the effort (and you can use unit tests instead), but this is just my opinion.

That doesn't mean I advise not to think about contracts in those cases. I always think about them. I just don't think it is necessary to always explicitly code them.

Honza Brabec
  • 602
  • 4
  • 11
1

As already mentioned Contracts and unit tests have different purpose.

Contracts are about defensive programming to make sure that are prerequisites are met, code is called with right parameters, etc.

Unit tests to ensure that code works, in differnt scenarios. These are like 'specs with teeth'.

Asserts are good they make code robust. However, if you are worried that it is adding up lot of code, you may also like to add conditional breakpoints at some places during debugging and reduce the Assert count.

0

Anything you have in your checkVariants() calls could be done from testing, how much effort that might actually be depends many things (external dependencies, coupling levels etc.) but it would clean the code up from one point of view. How testable a code-base developed against assertions would be without some refactoring I'm not sure.

I agree with @duros, these shouldn't be thought of as exclusive or competing approaches. In fact in a TDD environment you could even argue that the 'requirement' assertions would be need to have tests:).

Asserts however DO NOT make code more robust unless you actually do something to fix the failed check, they just stop data getting corrupted or similar, usually by aborting processing at the first sign of trouble.

A test driven/well tested solution will have typically already thought about and/or discovered many of the sources/reasons of bad inputs and outputs whilst developing the interacting components and already dealt with them closer to the source of the problem.

If your source is external and you have no control over it then to avoid cluttering up your code dealing with other codes problems you might consider implementing some sort of data-cleansing/assertion component in between the source and your component and put your checks in there.

Also I'm curious to what languages your using that doesn't have some sort of xUnit or other testing library that someone has developed, I thought there was pretty much something for everything these days?

Chris Lee
  • 278
  • 1
  • 6
0

In addition to unit tests and code contracts, I just thought I'd highlight another aspect, which is the value in defining your interfaces such that you eliminate or reduce the possibility of calling your code incorrectly in the first place.

It's not always easy or possible, but definitely worth asking yourself the question, "Can I make this code more foolproof?"

Anders Hejlsberg, creator of C#, said that one of the biggest mistakes in C# was not including non-nullable reference types. It's one of the main reasons so much necessary guard code clutter exists.

Still, refactoring to only have the necessary and sufficient amount of guard code makes for, in my experience, more usable and maintainable code.

Agree with @duros on the rest of it.

James World
  • 176
  • 3
0

Do both, but make some static helper methods to clarify your intentions. This is what Google did for Java, check out code.google.com/p/guava-libraries/wiki/PreconditionsExplained

Alexander Torstling
  • 1,226
  • 1
  • 8
  • 12