450 likes | 647 Vues
Behavioral Refinement. Principles of Object-Oriented Software Development (Chapter 10). Outline. Types as behavior Verifying behavioral properties Specifying the behavior of a program Verifying behavioral consistency Specifying behavioral compositions. Objectives.
E N D
Behavioral Refinement Principles of Object-Oriented Software Development (Chapter 10)
Outline • Types as behavior • Verifying behavioral properties • Specifying the behavior of a program • Verifying behavioral consistency • Specifying behavioral compositions
Objectives • Present notion of behavioral subtypes • Apply formal program verification techniques to method calls
Liskov Substitution Principle • General principle: • If an object of type S can be substituted in all places where an object of type T is expected, then S is a subtype of T • Object-oriented interpretation: • A class S, which inherits from a superclass T, is considered a subtype of T if S can be substituted in all places where T is expected. • Advantage: new subclasses of T can be written without modifying the methods of T. • Specification inheritance follows the Liskov substitution principle. • How can we formally define this substitution principle?
Review: Subtype refinement relationsto verify if is a subtype of • Sub-range inclusion • Functions • Records • Variants (contravariance)
Functions • If is a subtype of and is a subtype of then The function is a subtype of the function (Function notation: means function taking parameter of type and return value of type ) Subtype can have looser parameter type and/or tighter return type • Examples: float float is not a subtype of float int int float is not a subtype of float int int int is a not subtype of float int float char is a subtype of float int double int is a subtype of float int
Contravariance rule for function subtyping • Function subtypes can have looser parameter type and/or tighter return type • Intuitively, for a subtype function to be used in place of its supertype: • It must be able to support at least the same set of values as the input parameters of the supertype, and, • It must return no value more than what its supertype returns • A subtype function is a refinement of its supertype, relaxing the restrictions for its calling function, while strengthening its obligations to the calling function.
Records • If type i is a subtype of i, for all i = 1..m, then The record defined by a1:1,…,an:n is a subtype of the record defined by a1:1,…,am:m Note that n could be greater than m the subtype can introduce additional fields not in the supertype • Example: {age:int, speed:int, fuel:int} {age:int, speed:int} • Locations that use the supertype are not aware of the new fields so they are never used in those contexts.
Types as behavior • Previously, we defined types and subtypes in terms of refinement relations. • This gives a syntactic definition for determining what is and is not a subtype. • A subtype can still behave in a manner that is semantically inconsistent with its supertype. • Need a way to define the semantic behavior of a subtype and verify its consistency to its supertype.
Questions • How can we extend our notion of types to include a behavioral description? • How can we verify that a subtype respects the behavioral constraints imposed by the supertype?
Questions • How can we extend our notion of types to include a behavioral description? • Contracts (invariants and pre- and post-conditions) • How can we verify that a subtype respects the behavioral constraints imposed by the supertype? • Borrow from axiomatic verification techniques • Hoare logic
Outline • Types as behavior • Verifying behavioral properties • Specifying the behavior of a program • Verifying behavioral consistency • Specifying behavioral compositions
Verifying behavioral properties • Formal verification – mathematically proving that a program satisfies certain assertions about its behavior. • State model • Program execution as a sequence of state transitions • Program state – the collective value of all variables in a program • State:
State transformations • Program state is changed whenever a variable value is changed • Substitution: • Actions correspond to state transformations:
Verifying state transformations • Correctness formulae (Hoare logic) • {P}S{Q} • P: pre-condition • Q: post-condition • S: program statement • Verification
Correctness calculus • Axioms • Assignment: • Composition: • Conditional: • Iteration: • Consequence rules • Procedural abstraction
Outline • Types as behavior • Verifying behavioral properties • Specifying the behavior of a program • Verifying behavioral consistency • Specifying behavioral compositions
Specifying the operational behavior of a system • Recall that a program is a sequence of state transformations • Need a way to specify the operational behavior of a program – a transition system • We now define a transition system for a simple programming language (also called operational semantics)
Simple OO language syntax • Expressions • Elementary statements • Compound statement
Transition system rules for simple OO language • Assignment • Object creation • Method call represents the local context of the object
Compound statements • Composition • Conditional
Compound statements • Iteration
Transition example • Example program • x = new ctr; x.inc(); v = x.n • Transitions • x = new ctr, 1 , 1[x := ctr1] • n := n + 1, 2 →, 2[.n := .n + 1] • x.inc(), 2 , 2[2(x).n := 2(x).n + 1] • v := x.n, 3 →, 3[v := 3(x).n] • Trace • ’ with = 1, ’ = 3 and = ctr1 inc
Outline • Types as behavior • Verifying behavioral properties • Specifying the behavior of a program • Verifying behavioral consistency • Specifying behavioral compositions
Verifying correctness ofbehavioral refinements • Behavioral refinement • Abstract specification to concrete implementation • Supertype to subtype correspondence • How can we verify that a concrete implementation is consistent with its abstract specification? • Behavioral types – characterize the behavioral properties of objects in terms of modifications of an abstract state. • Need a representation abstraction function to map concrete data structures and operations to abstract counterparts.
Abstraction and representation • – representation abstraction function • Must prove that ’ corresponds to (’)
Proof strategy • To prove that an implementation is consistent with its abstract specification • Assume that pre- and post-conditions have been defined for the abstract type • Find representation invariant I relating concrete and abstract representations • Derive pre- and post-conditions P and Q for the concrete implementation • Prove P I (P) and (Q) I Q
An abstract stack specification type stack T { s: seq T; axioms: {true} push(t:T) {s’ = s t} {s } pop() {s = s’ result} }; where: = empty sequence x1,…,xn y1,…,ym = x1,…,xn,y1,…,ym
A stack realization template<class T> class as { int t; T a[MAX]; public: as() { t = 0;} void push(T e) { require(t<MAX-1); a[t++] = e; } T pop(){ require(t>0); return a[--t];} invariant: 0 <= t && t < MAX; };
Verify push() function Abstract: push(e:T) Pre-condition: true Post-condition: s’ = s e Concrete: push(T e) Pre-condition: t < MAX – 1 Post-condition: t’ = t + 1 ^ a’[t’-1] = e Invariant: I(a,t,s) t=length(s) ^ t>=0 ^ s=(a,t) where (a,t)= a[0],…,a[t-1]
Verify push() function Pre-condition: t < MAX – 1 ^ I(a,t,s) true Pre-condition of concrete implies that of abstract Post-condition: s’ = s e ^ I(a’,t’,s’) t’ = t + 1 ^ a’[t’-1] = e I(a’,t’,s’) t’=length(s’) ^ t’>=0 ^ s=(a’,t’) (a’,t’)= a’[0],…,a’[t’-1] s’ = s e length(s’) = length(s) + 1 t’ = t + 1 s’ = s e a[0],…,a[t-1] e = a’[0],…,a’[t-1],e = a’[0],…,a’[t’-2],e (a’,t’) a[0],…,a[t’-2],e a’[t’-1] = e Post-condition of abstract implies that of concrete
Verifying subtype correspondence • How can we verify that a type is a behavioral subtype of another type? • Subtype correspondence mapping • Need to define three sets of maps • - abstraction function – maps values to values • - renaming rule – maps subtype to supertype methods • - extension map – explains effects of extra methods
Behavioral subtyping constraints • If is a subtype of • Signature • dom(m) dom(m) • range(m) range(m) • Behavior • pre(m)[x := (x)] pre(m) • post(m) post(m) [x := (x)] • invariant() invariant() [x := (x)] • Satisfy correspondence mapping
Extension maps • Extension map must be defined such that each method call for object x of type , x.m(a), is mapped to a program m • (x.m(a)) = m • m – only calls methods shared by and its supertype or external functions and methods • Diamond rule:
Object hierarchies • Extension subtypes • Subtypes add more “state” and methods • One-to-one abstraction map: if more methods but same “state” • Additional methods must have well-defined extension map • Many-to-one abstraction map: if more “state” • Methods that change attributes not present in the supertype are safe • Usual methods, such as equality, must be defined in terms of the supertype’s state • Constrained subtypes • Subtypes are subsets of supertype’s behavior • Methods must satisfy the function subtyping rules
Outline • Types as behavior • Verifying behavioral properties • Specifying the behavior of a program • Verifying behavioral consistency • Specifying behavioral compositions
The need for global invariants • Verification of object behavior is inherently a local verification activity • Some inconsistencies cannot be detected locally • May be caused by actions that do not involve the object directly
Example class A { public: A() { forward = 0; } attach(B* b) { forward = b; b->attach(this); } bool invariant() { return !forward || forward->backward == this; } private: B* forward; }; class B { public: B() { backward = 0; } attach(A* a) { backward = a; } bool invariant() { return !backward || backward->forward == this; } private: A* backward; }; A a1, a2; B b; a1.attach(b); a2.attach(b); // violates invariant a1
Formalisms for specifying interactions • Behavioral contracts – behavior of compositions • Formalisms for specification, refinement, conformance, declarations • Characterize the behavioral of compositions of objects • Scripts – cooperation by enrollment • Defines formalisms for roles, initialization/termination policies, critical role set • Specify behavior as a set of roles and the interaction between objects as subscribing/enrolling to a role • Critical role set – minimal set of participants required for successful computation • Multiparty interactions – communication primitive • Communication primitive allows multiple objects to interact simultaneously • Frozen state – invariant during the interaction • Useful in specification of fault tolerant systems • Can assumption of synchrony be weakened in favor of efficiency? • Joint action systems – action-oriented • Assumes there exists some global decision procedure that decides which actions (and interactions) are appropriate • Object behaviors specified by state charts • Implications on inheritance, and refinement by superposition
Joint action systems - example actionservice()by client c; server s is when c.requesting && s.free do <body>
The Model-View contract contract model-view<V> { subject: model supports [ state: V; value(val:V) [state = val]; notify(); notify() v views v.update(); attach()(v:view) v views; detach()(v:view) v views; ] views: set<view> where view suppports [ update() [view reflects state]; subject(m:model) subject = m; ] invariant: v views [v reflects subject.state] instantiation: v views subject.attach(v) & v.subject(subject); subject.notify(); }
Summary • We extended the notion of subtyping to include behavioral properties • Reviewed a correctness calculus for verifying behavioral properties • Defined a set of state transformations corresponding to programming language constructs • Defined mappings to reason about correspondence between abstract and concrete types and between subtypes and supertypes • Presented an overview of formalisms for specifying global interactions between objects