Foundations of Software Engineering Design by Contract
Total Page:16
File Type:pdf, Size:1020Kb
Foundations of Software Engineering Design by Contract Fall 2020 Department of Computer Science Ben-Gurion university Based on slides of: Mira Balaban Department of Computer Science Ben-Gurion university R. Mitchell and J. McKim: Design by Contract by Example Who’s to blame? The components fit but the system does not work. Who’s to blame? The component developer or the system integrator? “Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live” 2 Design by Contract Topics in Software Engineering, Fall 2019 Design by Contract The Design by Contract (DBC) software development technique ensures high quality software by guaranteeing that every component of a system lives up to its expectations. As a developer using DBC, you specify component contracts as part of the component's interface. The contract specifies what that component expects of clients and what clients can expect of it. 3 Design by Contract Topics in Software Engineering, Fall 2019 Design By Contract The term Design by Contract was coined by Bertrand Meyer while designing the Eiffel programming language within Eiffel Software company. Eiffel implements the Design by Contract principles. Bertrand Meyer won the 2006 ACM Software System Award for Eiffel The Eiffel Tower, built in 1887 for the 1889 World Fair, was completed on time and within budget, as will software projects written in Eiffel. 4 Design by Contract Topics in Software Engineering, Fall 2019 Design By Contract DbC is an approach for designing computer software. It prescribes that software designers should define precise verifiable interface specifications for software components based upon the theory of abstract data types and the conceptual metaphor of business contracts DbC is a metaphor on how elements of a software system collaborate with each other, on the basis of mutual obligations and benefits. The metaphor comes from business life: a client and a supplier agree on a contract. the contract defines obligations and benefits. 5 Design by Contract Topics in Software Engineering, Fall 2019 A contract There are two parties A Client - requests a service A Supplier - supplies the service A Contract is the agreement between the client and the supplier Two major characteristics of a contract Each party expects some benefits from the contract and is prepared to incur some obligations to obtain them These benefits and obligations are documented in a contract document Benefit of the client is the obligation of the supplier, and vice versa. 6 Design by Contract Topics in Software Engineering, Fall 2019 DbC – The idea and metaphor Motivation: Organize communication between software elements By organizing mutual obligations and benefits Do it by a metaphor of clients – request services from suppliers suppliers – supply services Client Supplier Obligation Satisfy supplier Guarantee service requirement Benefit Get service Impose requirements 7 Design by Contract Topics in Software Engineering, Fall 2019 DbC – The metaphor realization Obligations and benefits are specified using contracts Write contracts for classes and methods Methods: Preconditions Post-conditions Classes: Invariants Client Supplier Obligation Precondition Post-condition Benefit Post-condition Precondition 8 Design by Contract Topics in Software Engineering, Fall 2019 What happens when a Contract Breaks? If everyone does their job, there is no problem If the precondition is not satisfied – the Customer is wrong! (The client has a bug). If the precondition is satisfied, but the postcondition is not the Service is wrong (The service has a bug). From the Client’s perspective, “true” is the best precondition. In general, weaker preconditions are better. From the Server’s perspective, “false” is the best precondition. In general, stronger preconditions mean an easier job with the implementation. 9 Design by Contract Topics in Software Engineering, Fall 2019 DbC Nature DbC promotes software specification together with or prior to code writing Writing contracts needs some principles and guidelines The DbC principles tell us how to organize a class features (attributes, methods) The contract of a class is its interface 10 Design by Contract Topics in Software Engineering, Fall 2019 Design by Contract, by Example 11 Design by Contract Topics in Software Engineering, Fall 2019 Notations features attributes routines functions procedures creation other COMMANDS 12 Design by Contract Topics in Software Engineering, Fall 2019 Six Principles – the SIMPLE_STACK example Topics in Software Engineering, Fall Design by Contract 13 2019 SIMPLE_STACK example – initial try SIMPLE_STACK is a generic class, with type parameter G: Simple_stack of G. Features: G Queries – functions; No side effect: SIMPLE_STACK count(): Integer is_empty(): Boolean count() Initialization: is_empty() initialize() initialize() push(g:G) Commands: pop() push(g:G)no return value. pop(): out parameter g:G; no return value. 14 Design by Contract Topics in Software Engineering, Fall 2019 Example (1) Writing a contract for push: Takes a parameter g. Places g on the top of the stack. push(g:G) Purpose: Push g onto the top of the stack. ensure: g = pop ??? 15 Design by Contract Topics in Software Engineering, Fall 2019 Example (2) Writing a contract for push: Takes a parameter g. Places g on the top of the stack. push(g:G) Purpose: Push g onto the top of the stack. ensure: g = pop ??? but pop does not return a value. Just removes. Redesign pop: pop(): G purpose: Remove top item and return it. New push contract: push(g:G) Purpose: Push g onto the top of the stack. ensure: g = pop 16 Design by Contract Topics in Software Engineering, Fall 2019 A. Separate commands from queries (1) Serious problem: Evaluation of the post-condition changes the stack! Solution: Split pop into two operations: 1. Query: top(): G purpose: return the item at the top of the stack. 2. Command: delete() purpose: deletes the item at the top of the stack. push contract: push(g:G) purpose: Push g onto the top of the stack. ensure: top = g 17 Design by Contract Topics in Software Engineering, Fall 2019 A. Separate commands from queries (2) Standardize names: Class: SIMPLE_STACK Queries: count(): Integer purpose: No of items on the stack. item(): G purpose: The top item is_empty(): Boolean Boolean queries have purpose: Is the stack empty? names that invite a yes/no Creation commands: question initialize() purpose: Initialize a stack (new or old) to be empty. Operations (other commands): put(g:G) purpose: Push g on top of the stack. A standard name to add remove() /delete item from any purpose: Removes the top item of the stack. container class 18 Design by Contract Topics in Software Engineering, Fall 2019 A. Separate commands from queries Principle 1: Separate commands from queries. Queries: Return a result. No side effects. Pure functions. Commands: Might have side effects. No return value. Some operations are a mixture: pop() – removes the top item and returns it →Separate into two pore primitive command and query of which it is mixed 19 Design by Contract Topics in Software Engineering, Fall 2019 B. Separate basic queries from derived queries (1) is_empty(): Boolean Post-condition of is_empty: purpose: Is the stack empty? ensure: consistent_with_count: Result = (count()=0) Result is a contract built-in variable that holds the result that a function returns to its caller. The effect of is_empty() is defined in terms of the count query. → is_empty() is a derived query: It can be replaced by the test: count() = 0. → Contracts of other features can be defined in terms of basic queries alone. No need to state the status of derived queries – no need to state in the post-condition of put() that is_empty() is false. state: count is increased infer : is_empty=false from the contract of is_empty 20 Design by Contract Topics in Software Engineering, Fall 2019 Separate basic queries from derived queries (2) Principle 2: Separate basic queries from derived queries. Derived queries can be specified in terms of basic queries. Principle 3: For each derived query, write a post-condition that defines the query in terms of basic queries. 21 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (1) Queries provide the interface of an object: all information about an object is obtained by querying it. Derived queries are defined in terms of basic queries (principle3). → The effect of a command on an object should be specified in terms of basic queries. For Simple_stack, define the effects of put() initialize() remove() in terms of the basic queries count() item() 22 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (2) The put command: put() increases count by 1. put() affects the top item. put(g:G) Purpose: Push g onto the top of the stack. ensure: count_increased: count() = count()@pre + 1 g_on_top: item() = g “@pre” is borrowed from OCL (Object Constraint Language) count()@pre refers to the value of the query count() when put() is called. 23 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (3) The initialize() command: Turns count() to 0: → post-condition count() = 0. initialize() purpose: Turns a stack (new or old) to be empty. ensure: stack_is_empty: count() = 0 Following initialization the stack includes no items. Therefore, no top item → The query item() cannot be applied. Implies a pre-condition for the query item: item() : G purpose: The top item on the stack. require: stack_is_not_empty: count() > 0 Together, the 2 contracts, guarantee that applying item after initialize is illegal! 24 Design by Contract Topics in Software Engineering, Fall 2019 Specify how commands affect basic queries (4) The remove() command: Two effects: Reduces the number of items by one. Removes the top item, and uncovers the item pushed before the top one. Pre-condition: Stack is not empty.