CSC 520 - Advanced Object Oriented Programming, Spring 2018 Specification
Specification A specification is an unambiguous description of the way the components of the software system should be used and how they behave if used properly. In object-oriented design, this relates to the interfaces of the system components, and classes in particular.
Reasons for Specification To remove ambiguity remaining after earlier phases. To improve our understanding of the implementation. To increase our confidence that the system will work. To help us debug our software. To help us test our software. To help us modify our software. To allow us to pass the implementation task to other developers. To provide better documentation.
Specification in Terms of Client-Supplier Boundaries What information the client can pass over the boundary and when they are allowed to pass it. What information the client can retrieve from the boundary and when they are allowed to retrieve it. When an even will be broadcast to registered clients and what information the clients will receive. The legal states of the information managed by the boundary.
Formal Specification Formal specification is scientific and rigorous. The following steps are used to mathematically prove that software is correct: 1 Produce a formal specification in a mathematical language that describes how the software should behave. 2 Prove that the specification is feasible, that is, there are no logical contradictions or impossibilities. 3 Prove that the software conforms to the specification.
Informal Specification Informal specification is pragmatic and partial. The simplest informal specifications are code comments that describe thins such as: when the client should call the function what parameters should be passed what kind of result is returned (type and value) what effect the function has on global data what action the function takes if there is a problem
Dynamic Checking A dynamic check is code embedded in the implementation that verifies that the software is not breaking the specification. Dynamic checking only makes sense for informal specifications: Formal specification guarantees that the implementation does not violate the specification; dynamic checking assumes that implementations tend to have faults. Some formal requirements cannot be feasibly checked. Some formal requirements cannot be expressed using imperative code. Some formal requirements cannot be expressed accurately as imperative code.
Object-Oriented Specification An object-oriented specification language allows us to assert: when a message can legally be sent to an object (message preconditions, expressed in terms of public attributes) the valid parameters for each message (message preconditions) the effect a message has on the receiving object (message postconditions, expressed in terms of public attributes) the valid replies from each message (message postconditions) the conditions that are always met by the object (class invariants)
Object-Oriented Specification Example Consider a Container class with an add method. Possible assertions: Precondition: an object reference passed to the add message must not be null Precondition: an object passed to the add message must not already be in the Container Postcondition: after the add message, the Container will contain the object that was passed in as a parameter. Invariant: the Container always contains a positive number of objects.
Design by Contract Design by Contract specifies the obligations between a client object and a supplier object: The client must respect the suppliers invariants. The use of a supplier method is subject to its preconditions. The implementation of a supplier method must guarantee its postconditions. The implementation of a supplier method the supplier s invariants. Abiding by the contract allows us to write less error checking code.
Contracts and Inheritance Inheritance effects contracts due to subtype polymorphism. The following Class invariants are combined using and as we move down the class hierarchy: we can only add invariants. Preconditions and postconditions are only an issue if the associate method is overridden. Preconditions can only be weakened as we move down the class hierarchy; preconditions added to a redefined method are combined with the inherited method using or. Postconditions can only be strengthened as we move down the class hierarchy; postconditions added to a redefined method are combined with and.
Enforcing Contracts Design by Contract assumes that the client and supplier objects meet their obligations. Programmers are fallible; error checking responsibilities: The supplier half of the contract (postconditions and invariants) should be checked at the end of the supplier method. The client is responsible for checking invariants and preconditions before calling the supplier, but this can lead to code duplication The supplier side of the contract can offer client side checking of the contract as a service to avoid code duplication.
Enforcing Contracts Example public int supplier ( Object o) { if (!... check invariants...) { fail (" Invariants broken "); } if (!... check preconditions...) { fail (" Preconditions broken "); } } // do the work if (!... check postconditions...) { fail (" Postconditions broken "); } if (!... check invariants...) { fail (" Invariants broken "); }
Informal Specification in Java Document contracts using code comments Check conditions dynamically Signal contract violations using RuntimeExceptions