SE381-10 (Week 7, lecture 3)
Z in software design and implementation
What have we done with Z so far?
Class discussion
[Section 1]
Z notation syntax
Proof methods
Z as formal specification
Specifying operations
Identifying cases
Specifying constraints
Specifying attributes as state variables
Rigorous notation may allow discovery of inconsistencies
Helps to plan error checking and testing
Similar to use cases
[Section 2]
Structured programming - functions
Formally specified system
Proved totality on some operations
Have thought out logic and attempted to prove
Summary
Model (subset of?) system requirements
Global constants/parameters/functions
Represented by axiomatic definitions
System components (objects?)
State variables and constraints
Represented by state schemas
System operations
Inputs, outputs, state changes
Represented by operation schemas . . .
Often, composed of partial operations . . .
Combined using schema calculus to form total operation
Proofs
Totality of operations . . .
Prove that we have covered all the cases . . .
Combinations of system state and inputs
Effectiveness of operations . . .
Prove that operations do what we expect them to do
Analogous to runnings tests for verification
(Haven't done much of this yet)
Does this have anything to do with developing software?
What does the textbook say about this? [Chapter 28]
Class discussion
[Section 1]
Operations and preconditions will somehow appear in design/code
[Section 2]
Have ideas thought out before design of software
Summary
Eventually, we need to produce program code
But, we have developed some confidence in our model
Interative model development
Proofs
Would like to maintain "good" model characteristics in our code
Approach: map model elements into code
Why?
Carry over verified ideas into the code
Make it easy (easier?) to confirm that code matches model
How?
Textbook examples: C code, limited by not having OO constructs
With C++ and STL, more options
Data
Z given sets can map to C++ class or primitive types
Z free types can map to C++ enumerations (or ??)
Z variables map to C++ variables
Z set variables map to STL sets (or ??)
Predicates
Testing set membership
if (mySet.find(theValue) != mySet.end()) . . .
Quantifiers
Generally represented by a loop (or STL algorithm equivalent)
For multiple bound variables, use nested loops (or algorithms)
Loop operation
Existential ("exists") quantifier . . .
Initialize result to "false"
Single "successful" case terminates loop with "true"
Universal ("for all") quantifier . . .
Initialize result to "true"
Single "failed" case terminates the loop with "false"
State schemas
Represent by a C++ class?
State variables become C++ data members
What about "invariant" predicates?
May add "AssertValid" member function to test them
Return boolean, or throw exception on failure?
Initialization schemas
Represent by C++ class constructor?
Operation schemas
Represent by C++ class member functions?
How should partial operations be handled?
Option 1: Each partial operation is a separate member function
Implement operation predicates:
Test precondition
Perform actions (but be careful . . .)
Action should be all or nothing, as determined by precondition
Usually no need to explicitly implement "no change" predicates
Combine partial operations with "main" operation member function
If logic is more than simple disjunction, look out for side effects!
Must test that postconditions (invariants applied to result) are OK before storing results
Option 2: Integrate partial operations into one member function
Be careful, and document well
Functions and relations
Can implement in Z style
Perhaps using STL map or multimap, or STL set of pairs
Look up values or perform other set operations
Or, implement directly as C++ function
If function is generated by a Z expression (e.g., lambda) . . .
Function body may implement generating expression
Examples from elevator problem