Keep your objects in a consistent state

Julien on Apr 12th 2008

Part of a good object oriented design is to keep the objects in a correct state.

For instance, in the financial world, we have financial instruments called "derivatives". According to Wikipedia:

Derivatives are financial instruments whose value changes in response to the changes in underlying variables. The main types of derivatives are futures, forwards, options, and swaps.

In the real world, a derivative can't exist if there isn't an underlying financial instrument associated. A future on the dow jones could not have been created without the dow jones in the first place. If we want to represent a derivative in a software, we must make sure that we follow the same rule.

So let's assume that I have the following class:

  1. class Derivative
  2. {
  3. private string _name;
  4. private Instrument _underlyingInstrument ;
  5.  
  6. public string Name
  7. {
  8. get { return _name; }
  9. }
  10.  
  11. public Instrument UnderlyingInstrument
  12. {
  13. get { return _underlyingInstrument; }
  14. }
  15.  
  16. public Derivative(string name, Instrument underlyingInstrument)
  17. {
  18. _name = name;
  19. _underlyingInstrument = underlyingInstrument;
  20. }
  21. }

Any new developer on a project that uses this Derivative class will mentally map the Derivative class to the corresponding financial concept. He will expect the UnderlyingInstrument property to return a non-null object. However, this is not guaranteed in the current implementation. As a matter of fact, this class can currently be used to only convey the name of a Derivative. If we wanted to do that, we would need to create a new class for that purpose only. So in the mean time, if we want our code to stay in a maintainable state, we need to make sure that each Derivative object will be constructed correctly. If not, different people will make different usage of the class.

In that case, ensuring the correctness of the object can be done very easily. We just need to do a bit of Design By Contract. So our constructor will become:

  1. public Derivative(string name, Instrument underlyingInstrument)
  2. {
  3. if(name == null || name.Length == 0)
  4. {
  5. throw new Exception("The name of the derivative can't be null or empty");
  6. }
  7. else if(underlyingInstrument == null)
  8. {
  9. throw new Exception("A derivative must have an underlying instrument");
  10. }
  11.  
  12. _name = name;
  13. _underlyingInstrument = underlyingInstrument ;
  14. }

Now you're sure that a fellow developer won't use your object to do a weird thing :).

Of course, you can improve the clarity of this piece of code significantly by using various techniques and frameworks(including Debug.Assert or your own Assert class). For instance, I would write something like that:

  1. public Derivative(string name, Instrument underlyingInstrument )
  2. {
  3. Guard.Against(name == null, "The name of the derivative can't be null");
  4. Guard.Against(name.Length == 0, "The name of the derivative can't be empty");
  5. Guard.Against(underlyingInstrument == null, "The underlying instrument of the derivative can't be null");
  6.  
  7. _name = name;
  8. _underlyingInstrument = underlyingInstrument;
  9. }

But that's a topic for another day!

Filed in .NET, General development | 2 responses so far

2 Responses to “Keep your objects in a consistent state”

  1. Spec#: should we really wait for it? | The .Net frog May 13th 2008 at 06:52 pm 1

    [...] The bottom line is that I believe that we should focus our efforts on improving the way we do defensive programming with the framework as it is, and not hope for a white knight. Even if they are not perfect solutions, I think we can cover a lot of ground by systematically checking the inputs, checking the post conditions/side effects with unit testing, and checking that our object are satisfying invariants. [...]

  2. Greg Young May 17th 2008 at 01:51 am 2

    This works great for naive invariants but what about more complex ones?

    An example of …

    List.Count == number of List.Items is a good one.

    Another good one might be in an object that is validating data off its contingent parts ex:

    I have a Customer who has a field “TotalAvailableCredit” this customer also has children “OustandingItemsOnCredit” I have an invariant that the total of all OutstandingItemsOnCredit can never total more than the TotalAvailableCredit. You can insure this invariant but it is much more difficult to insure (especially if you allow a caller to directly access the OutstandingItemsOnCredit as the invariant needs to be enforced from two objects.

    One of the huge benefits of static verification is that it will manage this invariant for me. It will prove that I never break the invariant in anyway. This combined with the fact that the invariant is now exposed from the object so a consumer can understand that it will always be true is a huge benefit in terms of the caller understanding what they can expect from my code.

    Cheers,

    Greg

Trackback URI | Comments RSS

Leave a Reply