Chapter 7 Programming by contract: preconditions and postconditions
This chapter discusses n An elaboration of precondition and postcondition. n Programming by contract. n Test plans.
Programming by contract n A programming style in which the invocation of a method is viewed as a contract between client and server, with each having explicitly stated responsibilities. n To imply a precondition, we will use the term ‘require:’. n To imply a postcondition, we will use the term ‘ensure:’.
The objective of programming by contract n Delineate, clearly and explicitly, responsibilities between client and server. n Delineate, clearly and explicitly, responsibilities between the user of a method and the implementor of the method. n Ensure that any possible run time error will be detected with minimal explicit error checking. n Unfortunately, Java requires all checking to be coded explicitly as part of the method implementation.
The objective of programming by contract (cont.) n Test for every possible error condition only once (for program efficiency). n Achieve a balance between program reliability and maintainability.
The contract n If the preconditions are satisfied, then the server guarantees that the postconditions will be satisfied when the method completes. n If the preconditions are not satisfied, that is, if the client does not meet his end of the contract, then the server promises nothing.
Explorer class n Constructor: u require: hitStrength >= 0 stamina >= 0 u ensure: this.name() == name this.location() == location this.strength() == strength this.stamina() == stamina
Explorer class (cont.) Method takeHit : u require: hitStrength >= 0 u ensure: this.stamina() <= old.stamina() n “old” refers to the value of the variable at the beginning of the method; it is not a Java construct.
What if preconditions are not met? n We could set the value to a default value if it doesn’t meet criteria. But this isn’t entirely satisfactory, since it treats an error condition as a normal, expected, occurrence. n Usually an error is returned if the preconditions are not met. CSCI.utilities package contains functionality for doing this.
Require class Include the following statement immediately after the package statement. import CSCI.utilities.*; Now you can use the method condition in the Require class. static public void condition (boolean precondition)
Require in Explorer method public Explorer (String name, rooms.Room location, int hitStrength, int stamina) { Require.condition(hitStrength >= 0); Require.condition(stamina >= 0); playerName = name; room = location; strengthPoints = hitStrength; staminaPoints = stamina; }
More on preconditions: n Occasionally, preconditions constrain the order in which methods can be invoked or require that an object be in a certain state before a given method can be invoked. n Example: an automobile must be running before it can move.
More on postconditions: n Query postconditions: u Queries do not change objects’ states. u Query postconditions simply say something about the value returned. n Command postconditions: u Commands change states. u Command postconditions describe the new state after execution of the command. n Constructor postconditions: u describe the initial state of the object.
Part of the specification: n Since preconditions and postconditions are part of the specifications, they should not mention private implementation components. n The reset method. ensure: tally == 0 (This is not correct!)
Named constants n Use named constants rather than literals in preconditions and postconditions. public int suit ( ) ensure: result == Card.CLUB || result == Card.DIAMOND || result == Card.HEART || result == Card.SPADE.
Creating a test plan n Test the implementation to insure that it conforms to the specifications. n Create a “test harness” to interact with the object. n The test system acts as the client of the object: u Invoke the object’s methods. u Examine the behavior of the object.
Testing stamina Provide an initial value for the object’s stamina. Invoke the takeHit method repeatedly. After each invocation, query the object with the method stamina and report the result.
Testing stamina (cont.) Sample test session: Initial stamina value: 100 Stamina is now 100. Strength of hit: 10 Stamina is now 90. Strength of hit: 20 Stamina is now 70. Stength of hit: 5 Stamina is now 65. …
Creating a test plan n Develop a test plan, giving values to be tested, the purpose of the test and the individual test cases, and the expected results. n Test the system thoroughly, but not inordinately. Explicitly include limiting values and “equivalence classes.” u If the system performs properly for one member of an “equivalence class,” it should perform properly for all members of the “equivalence class.”
Testing stamina Purpose: test the stamina property of a Explorer object, as modified by the method takeHit. n Preconditions: Initial value of stamina >=0 hitStrength argument to takeHit >=0 n Postconditions: stamina >=0
Testing stamina (cont.) Test run 1: Input Initial stamina value: 100 hitStrength : Expected Output stamina :
Testing stamina (cont.) Test run 2: Input Initial stamina value: 50 hitStrength : 100 Test run 3: Input Initial stamina value 0 hitStrength 10 Expected Output stamina : 50 0 Expected Output stamina : 0
We’ve covered n Programming by contract. u The client satisfying the precondition. u The server satisfying the postcondition. n Test plans.
Glossary