66
Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Embed Size (px)

Citation preview

Page 1: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Software Design and Implementation:Composition and Substitution

Dror FeitelsonSoftware Engineering

Hebrew University

Page 2: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Composition

• Software systems are composed of multiple modules

• Modules are built and tested in isolation– Should be enough because modules are defined

by their interface• But still may not work correctly when

composed together(that’s why we need integration testing)

Page 3: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Agenda

• Preconditions and postconditions– Defining the interface

• Contracts– Integrating with the programming language

• Liskov substitution principle– When can a subclass be used in place of a

superclass

Page 4: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

C. A. R. Hoare, “An Axiomatic Basis for Computer Programming”. Comm. ACM 12(10) pp. 576-580,583, Oct 1969.

Inventor of Quicksort (at age 26)Inventor of switch/case constructTook responsibility for null referencesInventor of Hoare Logic (this paper)Inventor of formalisms like CSPRecipient of 1980 Turing Award(and many other awards)

Page 5: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

r := xq := 0while (r >= y) do

r := r – yq := q + 1

done

What does this code do?

And how can we express this?

Page 6: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Hoare Triplet

{P} S {Q}• P and Q are predicates• P is the precondition• S is a statement• Q is the postcondition• Semantics: if P holds before you execute S,

then Q will hold after you execute it

Page 7: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

{what is the precondition?}r := xq := 0while (r >= y) do

r := r – yq := q + 1

done{what is the postcondition?}

Page 8: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

{x >= 0 y > 0}r := xq := 0while (r >= y) do

r := r – yq := q + 1

done{¬(y <= r) x = q·y+r}

Page 9: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Axioms

Rule of consequence:If {P0} S {Q0}

and PP0

and Q0Q

Then {P} S {Q}

Page 10: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Axioms

Rule of composition:If {P} S1 {R}

and {R} S2 {Q}

Then {P} S1; S2 {Q}

Page 11: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Axioms

Rule of iteration:If {P B} S {P}

Then {P} while(B) do S done {¬B P}

• P is loop invariant• B is loop condition

Page 12: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Axioms

Rule of conditional:If {P B} S {Q}

and {P ¬B} T {Q}

Then {P} if(B) then S else T end {Q}

Page 13: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Axioms

Axiom of assignment:Denote by P[E/x] the predicate P with free

instances of variable x replaced by expression EThen {P[E/x]} x := E {P}• Not the other way around!• P will hold after the assignment if it would have

held before the assignment had the assignment been made

Page 14: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University
Page 15: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Bertrand Meyer, “Applying ‘Design by Contract’”. Computer 25(10) pp. 40-51, Oct 1992.

Famous for:Advocacy and teaching of object-oriented programmingEiffel programming language and IDEDesign by contractProf. at ETH ZurichRecipient of ACM Software Systems Award

Page 16: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

The problem:• Coordinate between the two sides of an

interface• Who is responsible for what?Solution 1:• Defensive programming• Assume the other side is stupid and

irresponsibleSolution 2:• Contracts

Page 17: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Contracts

Provider Client

ObligationsWhat provider will do

What client must conform to

BenefitsWhat provider does not have to worry about

What client may expect to get

Page 18: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Contracts

Provider Client

ObligationsWhat provider will do

What client must conform to

BenefitsWhat provider does not have to worry about

What client may expect to get

Page 19: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Contracts

Provider Client

ObligationsWhat provider will do

What client must conform to

BenefitsWhat provider does not have to worry about

What client may expect to get

preconditions

postconditions

Page 20: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Indexingdescription: "Simple bank accounts"

classACCOUNT

feature -- Accessbalance: INTEGER

-- Current balancedeposit_count: INTEGER is

-- Number of deposits made since openingdo

if all_deposits /= Void thenResult := all_deposits.count

endend

Automatic documentation

Public member

Default initial value is 0

Page 21: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

feature -- Element changedeposit (sum: INTEGER) is

-- Add sum to account.require

non_negative: sum >= 0do

if all_deposits = Void thencreate all_deposits

endall_deposits.extend (sum)balance := balance + sum

ensureone_more_deposit:

deposit_count = old deposit_count + 1updated: balance = old balance + sum

end

Pre-condition

Post-condition

Optional label used in error

messages

Page 22: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

feature {NONE} -- Implementationall_deposits: DEPOSIT_LIST

-- List of deposits since account’s opening.invariant

consistent_balance:(all_deposits /= Void) implies (balance =

all_deposits.total)zero_if_no_deposits:

(all_deposits = Void) implies (balance = 0)end -- class ACCOUNT

Class invariant

Private member (seen by no other class)

Holds before and after every call to

every function

Page 23: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Invariants

• A general property of the class• Expressed as a predicate• Holds after the constructor• Holds before and after each method call– Not necessarily during method execution

• Effective precondition is precondition AND invariant

• Effective postcondition is postcondition AND invariant

Page 24: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Advantages

• Better methodology– Think clearly and express your assumptions

• Documentation– The contract is part of the interface– This is all the client needs to know

• Runtime verification by the system– Debugging (identify bugs early)– During production execution

Page 25: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Potential Disadvantage

• Provider x function f has precondition p• All clients will replicate the calling code

if p then x.felse …

• But:– p may be known already from context

(postcondition of previous operation)– else may be different in different clients (e.g. what

to do if pop’ing from an empty stack)

Page 26: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Inheritance

• Class SUB inherits from class SUPER• SUB may have a weaker precondition– SUPER.pre SUB.pre– If caller satisfies SUPER, will also work with SUB

• SUB may have a stronger postcondition– SUB.post SUPER.post– What SUB does is good enough for callers of SUPER

• SUB may also have stronger invariant• Part of the Liskov Substitution Principle

Page 27: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Violations

• Contracts do not check for special conditions• A runtime assertion violation is the

manifestation of a bug– Precondition: bug in client– Postcondition or invariant: bug in supplier

Page 28: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Verification

• Client is responsible for precondition• Supplier is responsible for postcondition• System can check this– Contract is part of the language

• Supplier can ignore bad input– Simpler code– Safe

• Client can assume result is correct– If not there should have been an exception

Page 29: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Verification Options• None– If program is correct, why waste time on checks?

• Preconditions only (default)– Useful for libraries with unknown clients

• Preconditions and postconditions• Preconditions, postconditions, and invariants• All (development and debugging): the above plus– Loop invariants– Loop variants (monotonically decreasing positive value

to ensure termination)– Assertions

Page 30: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Verification Options• None– If program is correct, why waste time on checks?

• Preconditions only (default)– Useful for libraries with unknown clients

• Preconditions and Postconditions• Preconditions, Postconditions, and invariants• All (development and debugging): the above plus– Loop invariants– Loop variants (monotonically decreasing positive value

to ensure termination)– Assertions

What would we think of a

sailing enthusiast who wears

his lifejacket when training on

dry land, but takes it off as

soon as he goes to sea?

-- C. A. R. Hoare

Page 31: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Exceptions

• Violating a monitored assertion causes an exception

• An exception may cause a failure• But you can sometimes avoid this!– Catch exception– Change something in conditions– Retry

Page 32: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

connect_to_server (server: SOCKET)-- Connect to a server or give up after 10 attemptsrequire

server /= Void and then server.address /= Voidlocal

attempts: INTEGERdo

server.connectensure

connected: server.is_connectedrescue

if attempts < 10 thenattempts := attempts + 1retry

endend

Page 33: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Examples

r = sqrt( x )

l = log( x )

Page 34: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Examples

{ x ≥ 0 }r = sqrt( x ){ x = r² }

{ x > 0 }l = log( x ){ el = x }

Precondition is an algorithmic

necessity

Page 35: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Examples

account.deposit( s )

Page 36: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Examples

{ s > 0 }account.deposit( s ){ balance = old.balance + s }

Precondition reflects logic and semantics: if s < 0 it is a withdrawal

Page 37: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Examples

account.withdraw( s )

Page 38: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Examples

{ s ≤ balance}account.withdraw( s ){ balance = old.balance - s }

Precondition reflects design decision: does this

function deal with attempted overdraft or does it just handle the

technicalities?

Page 39: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

B. H. Liskov and J. M. Wing, "A behavioral notion of subtyping". ACM Trans. Programing Languages and Systems 16(6) pp. 1811–1841, Nov 1994

Famous for:Contributions to programming languages and distributed computingLiskov Substitution Principle (this paper)Recipient of IEEE John von Neumann Medal (2004)Recipient of Turing Award (2008)

Page 40: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Substitution

If S is a subtype of Tthen

objects of type S may be used in place of objects of type T

without affecting correctness

Page 41: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Polymorphismabstract class Animal {

abstract String sound();}class Cat extends Animal {

String sound() { return "Meow!"; }}class Dog extends Animal {

String sound() { return "Woof!"; }}Vector<Animal> macdonalds = new…;for (Animal farmAnimal : macdonalds) {

farmAnimal.sound();}

Each farmAnimal at MacDonald’s is some

subtype of Animal and can be used in its place

Page 42: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Problem Example

• Inheritance embodies the ISA relationship

• A square is a special case of a rectangle

• So it seems natural to use inheritance

Rectangle

Square

Page 43: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Problem Example• But a rectangle has

separate width and height

• And they can be changed independently

• While in a square setting one changes the other

• So a square does not behave like a rectangle

Rectangleint: widthint: heightsetWidth()setHeight()

Square

Page 44: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Boolean checkArea(Rectangle r){

r.setWidth(4);r.setHeight(5);return (r.getWidth()*r.getHeight() == 20);

}

Page 45: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Formal Statement of LSP

If x is of type T and P(x) // property P holds for x and S is a subtype of T and y is of type SthenP(y) // property P also holds for y

Page 46: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Requirements

• Method signatures should be compatible• Contracts and invariants should be compatible• Exceptions should be compatible• Behavior should be indistinguishable– When using the subtype via the supertype

interface– Subtype may add things that are invisible via the

supertype interface

Page 47: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Syntactic Constraints

Page 48: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Method Signatures

• Return type of a method in a subtype can be more specific

returning a Dog instead of an Animal is OK• Argument types of a method in a subtype can

be more generalaccepting any Animal instead of just a Cat is

OK

Page 49: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Example

What happens if we substitute a DogShelter for an AnimalShelter?• Try to accept a horse

to the shelter• Try to adopt an

animal from the shelter

AnimalShelter

Void: accept(Animal)Animal: adopt()

DogShelter

Void: accept(Dog)Dog: adopt()

Page 50: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Exceptions

• Subtype may not throw new exceptions• But thrown exceptions may be subtypes of

exceptions of the supertype• The idea: calling environment must expect

these exceptions– So it can handle them

Page 51: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Semantic Constraints

Page 52: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Contracts

• Subtype cannot have stronger precondition• Subtype cannot have weaker postcondition• Subtype must preserve supertype’s invariant– Can be stronger

Page 53: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Example• Original postcondition

of setWidth(w):(width == w) && (height ==

old.height)• Square weakens this

by removing second clause

• Violation of LSP

Rectangleint: widthint: heightsetWidth()setHeight()

Square

Page 54: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Example

• In Naturals, subtract cannot accept large argument because result may not be negative

• Precondition is stronger

• Violation of LSP

Integers

int: add(int)int: subtract(int)

Naturals

int: add(int)int: subtract(int)

Page 55: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Example

• Naturals have the invariant that the value is non-negative

• Integers do not maintain this invariant

• Violation of LSP

Naturals

int: add(int)int: subtract(int)

Integers

int: add(int)int: subtract(int)

Page 56: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

History Constraint

• Subtype may add new methods• These methods may change the object’s state• But the subtype may not change in ways that

the supertype could not• Changing new members that did not exist in

the supertype is OK

Page 57: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Example

• Immutable point cannot be moved

• Mutable point adds a function to move it

• But this can lead to a history (where point moves) which contradicts the possible histories of an immutable point (where it stays put)

ImmutablePointint: xint: y

MutablePoint

void: moveTo(x,y)

Page 58: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

The Test

• I promise to give you an object of type T• Instead I give you an object of type S which is

a subtype of T• You may perform any test you wish on S using

T’s signature• If you cannot tell that the object is actually not

a T, then the LSP holds

Page 59: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Applicability

Page 60: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Mutability

• Problems mainly for mutable objects– If object is immutable (only getters, no setters)

then the behavior is simplified– ImmutableSquare inheriting from

ImmutableRectangle is OK• Subtype can have new fields that are mutable

Page 61: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Example

• Immutable point cannot be moved

• Center of fixed circle cannot be moved

• But its radius can be changed

ImmutablePointint: xint: y

ImmovableCircle

int: radius

void: setRadius(r)

Page 62: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Problem with ContractsPostcondition of setWidth(w):

(width == w) && (height == old.height) && (color == old.color) && (shadow == old.shadow) && (line == old.line) && …

Rectangleint: widthint: heightsetWidth()setHeight()

Square

Page 63: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Strong Behavioral Substitution

• The requirements of LSP are strong• Many hierarchies that look natural violate LSP• May not really be a problem– Depends on what the environment actually

expects and uses• A safety condition– Without LSP, when using a type T you need to

know about all possible subtypes S

Page 64: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Documentation

• The LSP is about expected behavior• Expected behavior often cannot be deduced

from code• Thus it is important to document expected

behavior• Especially crucial in methods that may be

overridden

Page 65: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University

Rectangle / Square Resolved• Violating LSP

indicates a problematic design

• Extract interfaces and/or inherit from abstract base classes

Boxint: widthint: height

Square

setSide()

Rectangle

setWidth()setHeight()

Page 66: Software Design and Implementation: Composition and Substitution Dror Feitelson Software Engineering Hebrew University