Article Discussion
Contract Programming 101
Summary: Contract Programming is something that�s been around for a long time but is getting far more air play, and rigorous examination, in recent times. Despite general agreement regarding the attraction of software contracts to programmers (and users!), there remains equivocation on what to do when contracts are broken. This is Part One of a series that takes a slightly philosophical look at this important issue, considers the tradeoffs between information and safety in reacting to contract violations, looks at practical measures for shutting errant processes, and introduces a new technique for the implementation of unrecoverable exceptions in C++.
18 posts.
The ability to add new comments in this discussion is temporarily disabled.
Most recent reply: January 25, 2006 4:05 AM by Jussi
    Chuck
     
    Posts: 32 / Nickname: cda / Registered: February 11, 2003 0:06 PM
    Contract Programming 101
    December 31, 2005 9:00 PM      
    This is Part One of a series that takes a slightly
    philosophical look at contract programming, considers the tradeoffs between information and safety in reacting to contract violations, looks at practical measures for shutting errant processes, and introduces a new technique for the implementation of unrecoverable exceptions in C++.

    http://www.artima.com/cppsource/deepspace.html
    • Harrison
       
      Posts: 7 / Nickname: hxa7241 / Registered: April 10, 2005 7:41 AM
      Re: The Nuclear Reactor and The Deep Space Probe
      January 2, 2006 10:44 AM      
      Contracts work at a particular level. They do not check:
      * if memory is faulty -- that is a hardware matter
      * if variables are of the correct type -- that is a type-system matter
      * if class axioms hold -- that is a testing matter
      * if use cases are fulfilled -- that is a requirements matter
      Contracts check abstractions. An abstraction holds a variable value within a fixed schema. A contract checks that schema is properly fixed. Since abstractions are defined during design, and the values at runtime, it follows that contracts are concerned with design.

      One corollary is that if the parameters to a method are of properly defined types, then pre/post-condition checks are superflous. The validity of the types guarantees the conditions. Not all method parameters are conveniently/practically expressed like this though.

      Why check invariants at the beginning *and* end of a method? There is an obvious redundancy. Meyer points out that this is needed with mulithreaded software. But if you like an easy life you will be avoiding multithreading and it rarely applies. So invariant checks are only needed in non-const methods, at the end, and before self-calls.

      It is going too far to check invariants against "some other part of the processing tramping on its memory". If something else has free access to the object through a pointer, then either: encapsulation has not been secured somewhere -- and *that* part of the design needs addressing. Or whatever else owns that pointer is behaving faultily -- and that's a failure of *its* class invariant checking. Either way, the cautionary code should be local, not spread across all other code in the program. It's part of the modularisation.
      • cdiggins
         
        Posts: 21 / Nickname: cdiggins / Registered: February 4, 2004 1:54 PM
        Re: The Nuclear Reactor and The Deep Space Probe
        January 2, 2006 1:35 PM      
        > It is going too far to check invariants against "some
        > other part of the processing tramping on its memory".

        In C/C++ designs lacking proper encapsulation are common and sometimes even neccessary for performance reasons. Theoretically your arguments appear to me to be sound, however in real-world scenarios C++ programming is rarely theoretical ideal. Constness can be easily violated, memory is often overwritten. There is no reason that I can see to not use contracts to help detect these kinds defects.
    • Roland
       
      Posts: 25 / Nickname: rp123 / Registered: January 7, 2006 9:42 PM
      Input validation vs. Precondition
      January 8, 2006 3:26 AM      
      "Contract Violations are Not Invalid Input Data" but your Precondition checks are called IsVALIDReadableString() or IsDateVALID(). The distinction between Preconditon and Input Validation is unclear in your description (and in general in all texts I've read so far).
      I appreciate that you try to put Contract Programming in C++ into a conceptual frame but the notions of C.P. are so ambiguous and arbitrarily interpretable that I doubt it's worth the effort.
    • Radek
       
      Posts: 7 / Nickname: radek / Registered: December 20, 2005 11:23 PM
      Re: Contract Programming 101
      January 3, 2006 5:53 AM      
      > Contract violations are not exceptional conditions

      There is lots of different definitions about what exceptional conditions are. Languages such as Java and C/C++ don't provide a mechanism to handle multiple mutually exclusive outcomes of method or function calls comfortably. Due to this lack, what I see is, that programmers use the language construct "exception" as a tool to signal a certain outcome out of a set of possible outcomes to the caller. Handcoded alternatives, such as using return values for the signalling of a specific outcome are rather awkward to handle and have no compiler support. But that means: using an exception in Java or C++ does not automatically imply there is an exceptional condition! Instead, these are return values. That is why such "kind of exceptions" are used in control flow.

      When making such a conscious distinction between using exceptions as a replacement for return values and using exceptions, well, for exceptional conditions, then I very well opt for contract violations being exceptional conditions.

      > And if you're still sceptical whether exceptions may be part of a function's contract, consider the case of the operator new() function. If throwing an instance of bad_alloc (or something derived from bad_alloc) were not within its contract, it would mean that memory exhaustion - a runtime condition largely outside the control of the program designer - would be a contract violation,

      If an exception is part of a function's contract then it is nothing different from a return value. This usage of exceptions is widely adopted to cope with multiple mutually exclusive outcomes. But it then is not really an "exception" anymore.
      Might it be, that "real" exceptions are exceptions because they exactly are not part of the functions contract?
      • cdiggins
         
        Posts: 21 / Nickname: cdiggins / Registered: February 4, 2004 1:54 PM
        Re: Contract Programming 101
        January 3, 2006 6:01 AM      
        > This usage of
        > exceptions is widely adopted to cope with multiple
        > mutually exclusive outcomes. But it then is not really an
        > "exception" anymore.

        I beg your pardon, but that doesn't make any sense. Perhaps an exception is not an error, but an exception is always an exception!
        • Radek
           
          Posts: 7 / Nickname: radek / Registered: December 20, 2005 11:23 PM
          Re: Contract Programming 101
          January 3, 2006 6:28 AM      
          > I beg your pardon, but that doesn't make any sense.
          > Perhaps an exception is not an error, but an exception is
          > always an exception!

          There is the language construct/mechanism "exception". And then there is the word "exception". What I mean is, you can use the language construct "exception" for a situation that is not exceptional in the sense of the word "exception".

          I tried to point out, that many programmers use the exception mechanism as a replacement for return values where the function has multiple mutually exclusive outcomes. I don't see why one outcome out of a set of possible outcomes should be superiour or inferior to the others (and thus "exceptional"). So, when using the language construct exceptions in such a sense, there is nothing "exceptional" about them at all.

          An example for multiple mutually exclusive outcomes: function to execute a transfer between banking accounts. Possible outcomes:

          1. transfer finished

          2. account A does not exist

          3. account B does not exist

          4. account A is not covered

          5. ...

          Now, is (2) an exceptional situation or an expected outcome?

          It depends on the contract. If the contract says, I will tell you if account A does not exist, then it is an expected outcome, not an exceptional situation. If the contract says nothing about account A then account A not existing is an exceptional situation.
          • Vladimir
             
            Posts: 4 / Nickname: robotact / Registered: August 27, 2005 2:15 AM
            Re: Contract Programming 101
            January 9, 2006 0:19 PM      
            > There is the language construct/mechanism "exception". And
            > then there is the word "exception". What I mean is, you
            > can use the language construct "exception" for a situation
            > that is not exceptional in the sense of the word
            > "exception".
            No, generally you can't. Problem is, laguages unambiguously state that exception is something exceptional and therefore most implementations optimize based on this assumption - in addition to the fact that exceptions are not that obvious to implement efficiently. You may have 100x or 1000x penalty if you use, say, exception instead of return value.
            • Max
               
              Posts: 18 / Nickname: mlybbert / Registered: April 27, 2005 11:51 AM
              About abusing exceptions
              January 11, 2006 10:12 AM      
              /* [original] What I mean is, you can use the language construct "exception" for a situation that is not exceptional ...

              [response] No, generally you can't.
              */

              Generally you shouldn't, but I'm not aware of any language that prevents you from abusing the exception system.

              Consider:

              void function(int x)
              { throw x;
              };

              Very bad idea. Even so, the language won't stop me from doing this.
            • Radek
               
              Posts: 7 / Nickname: radek / Registered: December 20, 2005 11:23 PM
              Re: Contract Programming 101
              January 10, 2006 2:30 AM      
              > No, generally you can't. Problem is, laguages
              > unambiguously state that exception is something
              > exceptional and therefore most implementations optimize
              > based on this assumption - in addition to the fact that
              > exceptions are not that obvious to implement efficiently.
              > You may have 100x or 1000x penalty if you use, say,
              > exception instead of return value.
              Yes, thank you, I am very aware of the possible performance penalty. While I said "you can" I didn't mean you should (even the performance penalty set aside). What I see is that many APIs (at least in Java) do. They use an exception where a return value would be more appropriate (not only for performance reasons, mainly for contract definition ones!). They do it because the exception mechanism offers a more convenient (read: less typing) way to signal and handle multiple mutually exclusive outcomes of a method call when compared to fiddling around with return values.

              In this sense my original post tried to pinpoint the ambiguity in the authors statement that "exceptions may be part of the contract". If exceptions are not used as a replacement for return values, then they just can't be part of the contract. I feel a need for clarification in that "exceptions may be part of the contract", iff used as a replacement for return values, but may never be part of the contract otherwise.
              • Thorsten
                 
                Posts: 4 / Nickname: nesotto / Registered: December 10, 2003 1:42 AM
                Re: Contract Programming 101
                January 10, 2006 9:31 AM      
                > In this sense my original post tried to pinpoint the
                > ambiguity in the authors statement that "exceptions may be
                > part of the contract". If exceptions are not used as a
                > replacement for return values, then they just can't
                > be part of the contract. I feel a need for clarification
                > in that "exceptions may be part of the contract", iff used
                > as a replacement for return values, but may never be part
                > of the contract otherwise.

                I would say that they are *always* part of the contract.

                Even if an exception is not used as a return-value, the state of the object just before exception is throw may be specified. It is a variant of a post-condition where you give additional guarantees if certain exceptions are thrown.

                Some tools use the pseudo-keyword "exsure" for this.

                -Thorsten
                • Radek
                   
                  Posts: 7 / Nickname: radek / Registered: December 20, 2005 11:23 PM
                  Re: Contract Programming 101
                  January 11, 2006 1:50 AM      
                  > Even if an exception is not used as a return-value, the
                  > state of the object just before exception is throw may be
                  > specified.

                  To repeat you in my own words: The contract defines to throw a certain exception if the object reaches a specified state. Is this correct? This raises a question: How is this different from a contract defining to return a certain value if the object reaches a specified state? In other words: Why do you think this proposed usage of exceptions is not just another example of replacing return values by exceptions?

                  > It is a variant of a post-condition where you
                  > give additional guarantees if certain exceptions are
                  > thrown.

                  I don't think that enforcement of contract conditions should become part of the function or method interface (and, therefore, extending it as a side effect). Rather, this enforcement takes place on a higher level, unknown to the fundamental application code (exceptions on contract violations, yes, but not part of a interface or contract).
                  • Max
                     
                    Posts: 18 / Nickname: mlybbert / Registered: April 27, 2005 11:51 AM
                    Re: Contract Programming 101
                    January 11, 2006 10:18 AM      
                    /* To repeat you in my own words: The contract defines to throw a certain exception if the object reaches a specified state. Is this correct?
                    */

                    The original article said "Contracts *may* be enforced in other ways, e.g. via exceptions ..." (emphasis added).

                    The reason for using exceptions to enforce contracts is simple -- the preconditions/postconditions/invariants must hold for the function to be able to do anything reasonable. If they don't hold, by definition the function can't do anything reasonable. Depending on the function signature, it may not be possible to return a good error code, but it's always possible to abort and throw.

                    Then people have to get used to watching for exceptions. But they may not remember to watch for error codes. There's a reason that Perl programmers are encouraged to die on error instead of returning error codes. I like error codes in the tradition of C, but I don't like return codes that are overloaded like fork()'s.
                  • Thorsten
                     
                    Posts: 4 / Nickname: nesotto / Registered: December 10, 2003 1:42 AM
                    Re: Contract Programming 101
                    January 16, 2006 2:49 PM      
                    > > Even if an exception is not used as a return-value, the
                    > > state of the object just before exception is throw may
                    > be
                    > > specified.
                    >
                    > To repeat you in my own words: The contract defines to
                    > throw a certain exception if the object reaches a
                    > specified state. Is this correct?

                    The contract may not when the exception is thrown, or that condition may not be easily expressed. However, irrelevant of when or why the exception is thrown, the function may guarantee, as part of its contract, that certain parameters (eg. the implicit this pointer in member functions) are left in a certain state.

                    As an example, look at exception-safety guarantees. If your function provides the basic guarantee, it promises that the invariant holds if an exception is thrown. It doesn't state when the exception is thrown or why.

                    Now the contract might be much more specific that that, maybe you can guarantee that X.foo() returns true too.

                    > This raises a question:
                    > How is this different from a contract defining to return a
                    > certain value if the object reaches a specified state? In
                    > other words: Why do you think this proposed usage of
                    > exceptions is not just another example of replacing return
                    > values by exceptions?

                    I feel that I don't have a good understanding of your definition of when exception are not used as return values.
                    Maybe you can elaborate.

                    -Thorsten
                    • Radek
                       
                      Posts: 7 / Nickname: radek / Registered: December 20, 2005 11:23 PM
                      Re: Contract Programming 101
                      January 18, 2006 1:31 AM      
                      > I feel that I don't have a good understanding of your
                      > definition of when exception are not used as return
                      > values.
                      > Maybe you can elaborate.

                      I will try to. Pls give me 2-3 days, I'm currently heavily involved.
                    • Radek
                       
                      Posts: 7 / Nickname: radek / Registered: December 20, 2005 11:23 PM
                      Re: Contract Programming 101
                      January 24, 2006 8:12 AM      
                      > I feel that I don't have a good understanding of your
                      > definition of when exception are not used as return
                      > values.
                      > Maybe you can elaborate.

                      If an exception gets thrown, it propagates up the call stack automatically. Code on the call stack need not do anything actively to support this behaviour. Basically, exceptions are transparent to application code.

                      This is not true for return values. Return values are never transparent to any application code. Application code always needs to know what to expect and what a specific return value does mean.

                      This is a fundamental difference between exceptions and return values. Now, you can start to model the behaviour of exceptions by using return values in a certain consistent way in your application code. Granted, this will never be really transparent to your application, but you do create a kind of metalevel code upon which you build your application. The better choice, though, is native support in the language, the way exception mechanisms provide. You can also start to model the behaviour of return values by using exceptions. You just need to define which exceptions you throw upon which conditions and stop using return values for the named cases. Clients of function/method interfaces are forced to handle exceptions instead of return values. You obtain the very same effect like you used return values.

                      So, when don't you use exceptions as a replacement for return values? When, as an implementor of a function/method interface, you do not name/document the exceptions you throw. Because, if you do, these are not really transparent to the application code anymore. If code is aware of and behaves depending on the concrete types of exception thrown by called code, the transparency is gone, the exceptions become part of the contract and could as well be modeled by usage of return values.
                      • Thorsten
                         
                        Posts: 4 / Nickname: nesotto / Registered: December 10, 2003 1:42 AM
                        Re: Contract Programming 101
                        January 24, 2006 0:58 PM      
                        > This is not true for return values. Return values are
                        > never transparent to any application code. Application
                        > code always needs to know what to expect and what a
                        > specific return value does mean.

                        well, you could ignore the return-value.

                        > This is a fundamental difference between exceptions and
                        > return values. Now, you can start to model the behaviour
                        > of exceptions by using return values in a certain
                        > consistent way in your application code. Granted, this
                        > will never be really transparent to your application, but
                        > you do create a kind of metalevel code upon which you
                        > build your application. The better choice, though, is
                        > native support in the language, the way exception
                        > mechanisms provide. You can also start to model the
                        > behaviour of return values by using exceptions. You just
                        > need to define which exceptions you throw upon which
                        > conditions and stop using return values for the named
                        > cases. Clients of function/method interfaces are forced to
                        > handle exceptions instead of return values. You obtain the
                        > very same effect like you used return values.

                        Right.

                        > So, when don't you use exceptions as a replacement for
                        > return values? When, as an implementor of a
                        > function/method interface, you do not name/document the
                        > exceptions you throw.

                        right, but you probably document whether the functions can throw or not.

                        > Because, if you do, these are not
                        > really transparent to the application code anymore. If
                        > code is aware of and behaves depending on the concrete
                        > types of exception thrown by called code, the transparency
                        > is gone, the exceptions become part of the contract and
                        > could as well be modeled by usage of return values.

                        Your views are quite reasonable. If an exception is not documented, it is not part of the contract.
                        I think I had two points with my original post

                        1. even if you don't know what exception is thrown, knowing that one can be thrown or not is part of the contract

                        2. even if you don't know what exception is trown, knowing the state of some relevant objects if it is thrown may be part of the contract

                        best regards

                        Thorsten
                        • Radek
                           
                          Posts: 7 / Nickname: radek / Registered: December 20, 2005 11:23 PM
                          Re: Contract Programming 101
                          January 25, 2006 0:52 AM      
                          > > This is not true for return values. Return values are
                          > > never transparent to any application code. Application
                          > > code always needs to know what to expect and what a
                          > > specific return value does mean.
                          > well, you could ignore the return-value.

                          But then you know you do actively ignore something. With exceptions (the non-documented, the not-used-like-return values) this is completely transparent (and this has been the initial motivation for exceptions, I guess).

                          > > So, when don't you use exceptions as a replacement for
                          > > return values? When, as an implementor of a
                          > > function/method interface, you do not name/document the
                          > > exceptions you throw.
                          > right, but you probably document whether the functions can
                          > throw or not.

                          Documenting that the function can/does throw an exception (possibly in circumstances you don't specify clearly, even without stating the exact exception type) is essentially the same as defining an integer return value with 0 on success, -1 on failure.

                          > If an exception is not
                          > documented, it is not part of the contract.

                          Yes. I wish, the article would clearify this.

                          > I think I had two points with my original post
                          > 1. even if you don't know what exception is thrown,
                          > knowing that one can be thrown or not is part of the
                          > contract

                          Agree completely, see above.

                          > 2. even if you don't know what exception is trown, knowing
                          > the state of some relevant objects if it is thrown may be
                          > part of the contract

                          Richtig. Both cases belong to my exceptions-used-like-return-values view.
                          • Jussi
                             
                            Posts: 1 / Nickname: jussi / Registered: June 16, 2005 8:53 PM
                            Re: Contract Programming 101
                            January 25, 2006 4:05 AM      
                            > Richtig. Both cases belong to my
                            > exceptions-used-like-return-values view.

                            In other words exceptions-used-as-program-flow-control-constructs to aid return values handling.