8

In the book coders at work, the author asks "How do you use invariants in your code". Please explain what this question means.

I saw class invariants on wiki, but the example is in Java and I am not skilled enough in Java to relate this example to C#. .NET 4.0 introduces invariance, covariance, and contravariance and is well explained here. Invariance is so broad. The authors usage of the word seems unit test related. For those that read the book, what does the author mean? Are we talking about making an assumption and simply testing the validity after the unit test?

P.Brian.Mackey
  • 43,228
  • 68
  • 238
  • 348

4 Answers4

10

The word invariant doesn't mean more than something doesn't change under certain conditions. There are many different kinds of invariants. For example in physics the speed of light is invariant under lorentz-transform, i.e. it doesn't change if you change to reference frame. In programming there are many kinds of invariants too. There are class invariants which don't change over the lifetime of an object, method invariants which don't change during the life of a function,...

A class invariant is something that's always(at least at publicly observable times) true in an instance of that class.

This is in no way related to co-/contra-variance. Co-/Contra-variance describes which types can be substituted for other types with different (generic) parameters or return types. While you can call something invariant because it doesn't support Co-/Contra-variance this is a completely different kind of invariance than a class or method invariant.

For example some kind of collection might have the following invariants:

  • data != null
  • Size >= 0
  • Capacity >= 0
  • Size <= Capacity

With this class:

class MyCollection<T>
{
  private T[] data;
  private int size;

  public MyCollection()
  {
    data=new T[4];
  }

  public int Size{get{return size;}}
  public int Capacity{get{return data.Length;}}

  [ContractInvariantMethod]
  protected void ClassInvariant()
  {
    Contract.Invariant(data != null);
    Contract.Invariant(Size >= 0);
    Contract.Invariant(Capacity >= 0);
    Contract.Invariant(Size < Capacity);
  }
}

Almost every class has some invariants, but not everybody enforces them. .net 4 adds a nice way to document and assert them using code contracts.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • 1
    Its funny you say .NET invariance is not related to other kinds of invariance. I don't agree, but perhaps that's where I am wrong. Perhaps type-invariance is unrelated to class-invariance and the unit test usage, or related only on a rudimentary level. If we define "invariance" as simply "doesn't change". The question is "How do you test for things that don't change". Or, is the question "How do you test for a range of valid values"? – P.Brian.Mackey Jan 03 '11 at 16:43
  • @P.Brian There are many types of invariants. And type variance is completely unrelated to class-invariants. I've added an introductory paragraph. – CodesInChaos Jan 03 '11 at 16:47
  • @P.Brian To see how to enforce a class invariant in .net 4 see "Lee"'s answer. If you do that(and choose the correct compiler settings) your code will be rewritten so it tests the invariant at the end of any public method. – CodesInChaos Jan 03 '11 at 16:48
  • 1
    Thanks, the ClassInvariant() implementation really helps me to visualize what your talking about. – P.Brian.Mackey Jan 03 '11 at 16:59
  • 1
    @P.Brian Mackey: You seem to have been somewhat misled by the similarity in pronunciation between "invariance" and "invariants". They are pronounced similarly enough to be confusing, but CodeInChaos is absolutely right: they have nothing whatsoever to do with each other. – Eric Lippert Jan 03 '11 at 23:38
  • @Eric Lippert - I was thinking about that yesterday. I found Invariant and Invariance listed together on wiki http://en.wikipedia.org/wiki/Invariant. Their dictionary.com definitions are practically the same as well. I suppose the difference really come out in our particular field. CodeInChaos laid it out pretty well though. – P.Brian.Mackey Jan 04 '11 at 15:03
  • invariants are checked after creating the object and after call a routine only? – Tomas Ramirez Sarduy Jun 15 '11 at 00:13
  • @Tom I assume that they are only checked after public methods/object creation. Invariants don't need to hold at all times, but only at publicly observable times. But I haven't used CodeContracts myself yet, so I don't know for sure how it works. – CodesInChaos Jun 15 '11 at 08:43
2

In this case, invariants mean the conditions that apply to parameters and that remain true throughout the life of the function/method.

From wikipedia:

In computer science, a predicate is called an invariant to a sequence of operations provided that: if the predicate is true before starting the sequence, then it is true at the end of the sequence.

In .NET, invariants can be checked/enforced using Code Contracts.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
  • I don't think you need to have read the book to understand my question, but the way the author asks the question is a "matter of fact" or "how do you use these things" as if everybody does it. I've never knowingly used invariants for any purpose, and in .NET it seems we need an off the wall Attribute to even consider them. So, is common use of invariants a thing of the past or limited to assembly/C/C++? – P.Brian.Mackey Jan 03 '11 at 16:12
  • @P.Brian.Mackey - I have never used them either, however, it appears that those coming from a CS background do try to use them it an attempt to get better "correctness". I guess he assumes everyone knows about invariants and how to use them - consider the people that are featured in the book :) – Oded Jan 03 '11 at 16:16
2

That example in the Wiki is implementing invariants with JML, which is a very specific, exotic and perhaps well-thought-out research technology, but it isn't necessary mainstream at all. Also its not just talking about invariants but just talking about asserting a mutator did what was expected, which isn't what I think of when I think of invariants. I haven't read Coders at Work but I doubt anyone in Coders at Work used JML.

Anyway, I always thought invariants were a great way to "crash early" and keep your code from trying to do reasonable things when in fact the program state is in an unreasonable (unplanned-for) state.

A good example of an invariant in C# code might be to never give an object to N-Hibernate for saving unless that object has passed on its invariants, of which there should be many in order to prevent non-sensical data from entering the database. Let's see if I can think of any other examples...

  • Suppose you have a User class that is always supposed to have a primary email address property, then an invariant to check before Saving might be to make sure the email address field isn't empty. Otherwise, other application logic down the road that assumes email addresses exist for all users might mess up when trying to send a User an email later.

  • Suppose further that a User object "has many" Email objects, and suppose that it doesn't make any sense for an Email to exist without an owning user, then an invariant on the Email class might be to make sure the Email's reference to its user is always not null, otherwise you have an orphan Email object which could result in null pointer exceptions when you try to refer to the email's owner.

  • Suppose you're writing a GUI that is supposed to present the status of an Amazon S3 object in a conventional WPF form. An invariant on the form might be to make sure that the form is properly bound to its object before executing any event handlers on that form.

  • Suppose you're writing StackOverflow. An invariant here might be to make sure a user's reputation level is never negative, even if the user is taking reputation penalties. Negative reputation might break those pretty graphs that render experience as a function of time (unless those graphs are prepared to chart lines below the 0 y-axis, which they very may well be...).

As for when to check for invariants, you could do this at the end of any method that mutates data state. At the most aggressive and paranoid level of defensive programming, you could check an invariant before and after all methods.

Michael Rivera
  • 193
  • 1
  • 7
1

The meaning in this context is not related to co and contra variance for generics introduced in C#4, but rather in the same sense as the wikipedia article you link to. In C# this can be debug assertions (i.e. Debug.Assert(condition)) as well as the code contracts library. There is for example the ContractInvariantMethodAttribute which can be applied to a method in a class which asserts the class invariants:

[ContractInvariantMethod]
protected void ClassInvariant()
{
    Contract.Invariant(someCondition);
}
Lee
  • 142,018
  • 20
  • 234
  • 287