1 / 141

Software Architecture Prof. Dr. Bertrand Meyer

Software Architecture Prof. Dr. Bertrand Meyer. Lecture 4: Design by Contract. Reading material. OOSC2: Chapter 11: Design by Contract. Design by Contract. A discipline of analysis, design, implementation, management. Applications. Getting the software right Analysis Design

laurie
Download Presentation

Software Architecture Prof. Dr. Bertrand Meyer

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Software ArchitectureProf. Dr. Bertrand Meyer Lecture 4: Design by Contract

  2. Reading material • OOSC2: • Chapter 11: Design by Contract

  3. Design by Contract • A discipline of analysis, design, implementation, management

  4. Applications • Getting the software right • Analysis • Design • Implementation • Debugging • Testing • Management • Maintenance • Documentation

  5. Design by Contract • Origin: work on “axiomatic semantics” (Floyd, Hoare, Dijkstra), early seventies • Some research languages had a built-in assertion mechanism: Euclid, Alphard • Eiffel introduced the connection with object-oriented programming and made contracts a software construction methodology and an integral part of the language • Mechanisms for other languages: Nana macro package for C++, JML for Java, Spec# (and dozens of others)

  6. Documentation Issues Who will do the program documentation (technical writers, developers) ? How to ensure that it doesn’t diverge from the code (the French driver’s license / reverse Dorian Gray syndrome) ? The Single Product principle The product is the software

  7. Design by Contract • Every software element is intended to satisfy a certain goal, for the benefit of other software elements (and ultimately of human users). • This goal is the element’s contract. • The contract of any software element should be • Explicit. • Part of the software element itself.

  8. Ariane 5, 1996 • $500 million, not insured. • 37 seconds into flight, exception in Ada program not processed; order given to abort the mission. • Exception was caused by an incorrect conversion: a 64-bit real value was incorrectly translated into a 16-bit integer. • Not a design error. • Not an implementation error. • Not a language issue. • Not really a testing problem. • Only partly a quality assurance issue. • Systematic analysis had “proved” that the exception could not occur – the 64-bit value (“horizontal bias” of the flight) was proved to be always representable as a 16-bit integer !

  9. Ariane-5 (Continued) • It was a REUSE error: • The analysis was correct – for Ariane 4 ! • The assumption was documented – in a design document ! • With assertions, the error would almost certainly (if not avoided in the first place) detected by either static inspection or testing: integer_bias(b:REAL):INTEGERis require representable(b) do … ensure equivalent(b,Result) end

  10. Ariane 5 (Conclusion) The main lesson: Reuse without a contract is sheer folly See: Jean-Marc Jézéquel and Bertrand Meyer Design by Contract: The Lessons of Ariane IEEE Computer, January 1997 Also athttp://www.eiffel.com

  11. A human contract OBLIGATIONS BENEFITS deliver (Satisfy precondition:) Bring package before 4 p.m.; pay fee. (From postcondition:) Get package delivered by 10 a.m. next day. Client (Satisfy postcondition:) Deliver package by 10 a.m. next day. (From precondition:) Not required to do anything if package delivered after 4 p.m., or fee not paid. Supplier

  12. A view of software construction • Constructing systems as structured collections of cooperating software elements — suppliers and clients — cooperating on the basis of clear definitions of obligations and benefits. • These definitions are the contracts.

  13. Properties of contracts • A contract: • Binds two parties (or more): supplier, client. • Is explicit (written). • Specifies mutual obligations and benefits. • Usually maps obligation for one of the parties into benefit for the other, and conversely. • Has no hidden clauses: obligations are those specified. • Often relies, implicitly or explicitly, on general rules applicable to all contracts (laws, regulations, standard practices).

  14. Contracts for analysis, specification • deferredclassVATinheritTANKfeaturein_valve, out_valve: VALVE fillis-- Fill the vat.requirein_valve.openout_valve.closeddeferredensurein_valve.closedout_valve.closedis_fullendempty, is_full, is_empty, gauge, maximum, ... [Otherfeatures] ...invariantis_full = (gauge >= 0.97 * maximum)  and  (gauge <= 1.03 * maximum)end Precondition i.e. specified but not implemented Postcondition Class invariant

  15. Contracts for analysis OBLIGATIONS BENEFITS fill (Satisfy precondition:) Make sure input valve is open, output valve is closed. (From postcondition:) Get filled-up tank, with both valves closed. Client (Satisfy postcondition:) Fill the tank and close both valves. (From precondition:) Simpler processing thanks to assumption that valves are in the proper initial position. Supplier

  16. So, is it like “assert.h”? • (Source: Reto Kramer) • Design by Contract goes further: • “Assert” does not provide a contract. • Clients cannot see asserts as part of the interface. • Asserts do not have associated semantic specifications. • Not explicit whether an assert represents a precondition, post-conditions or invariant. • Asserts do not support inheritance. • Asserts do not yield automatic documentation.

  17. Correctness in software • Correctness is a relative notion: consistency of implementation vis-à-vis specification. • Basic notation: (P, Q: assertions, i.e. properties of the state of the computation. A: instructions). • {P} A {Q} • “Hoare triple” • What this means (total correctness): • Any execution ofAstarted in a state satisfyingPwill terminate in a state satisfyingQ.

  18. Hoare triples: a simple example • {n > 5}n := n + 9 {n > 13} • Most interesting properties: • Strongestpostcondition (from given precondition). • Weakest precondition (from given postcondition). • “Pis stronger than or equal toQ ” means: • PimpliesQ • QUIZ: What is the strongest possible assertion? The weakest?

  19. Specifying a square root routine • {x >= 0} • ... Square root algorithm to compute y ... • {abs (y ^ 2 – x) <= 2 *epsilon*y } • -- i.e.: y approximates exact square root of x • -- within epsilon

  20. Software correctness • Consider • {P} A {Q} • Take this as a job ad in the classifieds. • Should a lazy employment candidate hope for a weak or strong P?What about Q? • Two special offers: • 1. {False} A {...} • 2. {...} A {True}

  21. A contract (from EiffelBase) • extend (new : G; key : H) -- Assuming there is no item of key,-- insert new with key; setinserted.requirekey_not_present: nothas (key)do-- ...ensureinsertion_done: item (key) = newkey_present: has (key) inserted: insertedone_more: count = oldcount + 1end

  22. OBLIGATIONS BENEFITS Routine The contract Client PRECONDITION POSTCONDITION Supplier POSTCONDITION PRECONDITION

  23. A class without contracts • classACCOUNTfeature-- Accessbalance : INTEGER-- BalanceMinimum_balance: INTEGERis 1000-- Minimum balancefeature {NONE} -- Deposit and withdrawaladd (sum : INTEGER) is-- Add sum to the balance (secretprocedure).dobalance := balance + sumend

  24. A class without contracts • feature-- Deposit and withdrawal operationsdeposit (sum : INTEGER) is-- Deposit sum into the accountdoadd (sum)endwithdraw (sum : INTEGER) is-- Withdraw sum from the accountdoadd (- sum)endmay_withdraw (sum : INTEGER): BOOLEANis-- Is it permitted to withdraw sum -- from the account?doResult := (balance - sum >= Minimum_balance)endend

  25. Introducing contracts • class • ACCOUNT • create • make • feature{NONE }-- Initialization • make (initial_amount: INTEGER ) is-- Set up account withinitial_amount. • require • large_enough: • initial_amount >= Minimum_balance • dobalance := initial_amountensurebalance_set:balance = initial_amount • end

  26. Introducing contracts • feature -- Access • balance : INTEGER-- Balance • Minimum_balance: INTEGERis 1000-- Minimum balance • feature {NONE }-- Implementation of deposit and withdrawaladd(sum: INTEGER)is-- Addsumto thebalance(secret procedure).dobalance:= balance + sum • ensure • increased: balance = oldbalance + sum • end

  27. Introducing contracts • feature-- Deposit and withdrawal operations • deposit (sum: INTEGER)is-- Depositsuminto the account. • require • not_too_small: sum >= 0 • do add (sum)ensure • increased: balance = oldbalance + sum • end

  28. Introducing contracts • withdraw (sum: INTEGER) is-- Withdrawsumfrom the account.require • not_too_small: sum >= 0 • not_too_big: sum <= balance – Minimum_balance • doadd (–sum) • -- i.e.balance := balance – sum • ensure • decreased: balance = oldbalance - sum • end

  29. The contract OBLIGATIONS BENEFITS withdraw (Satisfy precondition:) Make sure sum is neither too small nor too big. (From postcondition:) Get account updated with sum withdrawn. Client (Satisfy postcondition:) Update account for withdrawal of sum. (From precondition:) Simpler processing: may assume sum is within allowable bounds. Supplier

  30. The imperative and the applicative do balance := balance - sum ensure balance = oldbalance - sum PRESCRIPTIVE DESCRIPTIVE How? What? Operational Denotational Implementation Specification Command Query Instruction Expression Imperative Applicative

  31. Introducing contracts • may_withdraw (sum: INTEGER): BOOLEANis-- Is it permitted to withdrawsumfrom • -- account? • doResult:= (balance - sum >= Minimum_balance)end • invariant • not_under_minimum:balance >= Minimum_balance • end

  32. The class invariant • Consistency constraint applicable to all instances of a class. • Must be satisfied: • After creation. • After execution of any feature by any client.(Qualified calls only: x.f (...))

  33. The correctness of a class • For every creation procedure cp: {Precp} docp {INVandPostcp} • For every exported routine r: {INVandPrer} dor {INVandPostr} createx.make (…) S1 x.f (…) S2 x.g (…) S3 x.f (…) S4

  34. Uniform Access • balance = deposits.total – withdrawals.total deposits (A1) withdrawals deposits (A2) withdrawals balance

  35. A slightly more sophisticated version • classACCOUNTcreatemakefeature {NONE} -- Implementationadd (sum : INTEGER) is-- Add sum to the balance (secretprocedure).dobalance := balance + sumensurebalance_increased: balance = oldbalance + sumenddeposits : DEPOSIT_LISTwithdrawals : WITHDRAWAL_LIST

  36. New version • feature{NONE }-- Initialization • make (initial_amount: INTEGER) is-- Set up account with initial_amount. • requirelarge_enough: initial_amount >= Minimum_balancedo • balance := initial_amount • createdeposits.make • createwithdrawals.make • ensure • balance_set: balance = initial_amount • end • feature -- Accessbalance: INTEGER-- BalanceMinimum_balance: INTEGERis1000-- Minimum balance

  37. New version • feature-- Deposit and withdrawal operationsdeposit (sum : INTEGER) is-- Deposit sum into the account.requirenot_too_small: sum >= 0doadd (sum)deposits.extend (create {DEPOSIT}.make (sum))ensure increased: balance = oldbalance + sumone_more: deposits.count = olddeposits.count + 1end

  38. New version • withdraw (sum : INTEGER) is-- Withdraw sum from the account.requirenot_too_small: sum >= 0not_too_big: sum <= balance – Minimum_balancedoadd (– sum)withdrawals.extend (create {WITHDRAWAL}.make (sum))ensure decreased: balance = oldbalance – sumone_more: withdrawals.count = oldwithdrawals.count + 1end

  39. New version • may_withdraw (sum : INTEGER): BOOLEANis-- Is it permitted to withdraw sum from account?doResult := (balance - sum >= Minimum_balance)endinvariantnot_under_minimum: balance >= Minimum_balance consistent: balance = deposits.total – withdrawals.totalend

  40. The correctness of a class • For every creation procedure cp: {Precp}docp {INVandPostcp} • For every exported routine r: {INVandPrer} dor {INVandPostr} createx.make (…) S1 x.f (…) S2 x.g (…) S3 x.f (…) S4

  41. Initial version • feature {NONE} -- Initializationmake (initial_amount : INTEGER) is-- Set up account with initial_amount.requirelarge_enough: initial_amount >= Minimum_balancedobalance := initial_amountcreatedeposits.makecreatewithdrawals.makeensurebalance_set: balance = initial_amountend

  42. Correct version • feature {NONE} -- Initializationmake (initial_amount : INTEGER) is-- Set up account with initial_amount.requirelarge_enough: initial_amount >= Minimum_balancedocreatedeposits.makecreatewithdrawals.makedeposit (initial_amount)ensurebalance_set: balance = initial_amountend

  43. What are contracts good for? • Writing correct software (analysis, design, implementation, maintenance, reengineering). • Documentation (the “contract” form of a class). • Effective reuse. • Controlling inheritance. • Preserving the work of the best developers. • Quality assurance, testing, debugging (especially in connection with the use of libraries) . • Exception handling .

  44. Contracts: run-time effect • Compilation options (per class, in Eiffel): • No assertion checking • Preconditions only • Preconditions and postconditions • Preconditions, postconditions, class invariants • All assertions

  45. A contract violation is not a special case • For special cases (e.g. “if the sum is negative, report an error...”) • use standard control structures (e.g. if ... then ... else...). • A run-time assertion violation is something else: the manifestation of • A DEFECT (“BUG”)

  46. The contract language • Language of boolean expressions (plus old): • No predicate calculus (i.e. no quantifiers, or). • Function calls permitted (e.g. in a STACK class): put (x: G)is -- Pushxon top of stack. require notis_full do … ensure notis_empty end removeis -- Pop top of stack. require notis_empty do … ensure notis_full end

  47. The contract language • First order predicate calculus may be desirable, but not sufficient anyway. • Example: “The graph has no cycles”. • In assertions, use only side-effect-free functions. • Use of iterators provides the equivalent of first-order predicate calculus in connection with a library such as EiffelBase or STL. For example (Eiffel agents, i.e. routine objects):my_integer_list.for_all (agentis_positive (?)) • with • is_positive (x: INTEGER): BOOLEANis • do • Result:= (x > 0) • end

  48. The imperative and the applicative do balance := balance - sum ensure balance = oldbalance - sum PRESCRIPTIVE DESCRIPTIVE How? What? Operational Denotational Implementation Specification Command Query Instruction Expression Imperative Applicative

  49. A contract violation is not a special case • For special cases (e.g. “if the sum is negative, report an error...”), use standard control structures (e.g. if ... then ... else...). • A run-time assertion violation is something else: the manifestation of • A DEFECT (“BUG”)

  50. Contracts and quality assurance • Precondition violation: Bug in the client. • Postcondition violation: Bug in the supplier. • Invariant violation: Bug in the supplier. • {P} A {Q}

More Related