270 likes | 390 Views
Abstract Data Types Operation contracts. CSE432. Abstract Data Types. What does ‘ abstract ’ mean? From Latin: to ‘ pull out ’— the essentials To defer or hide the details Abstraction emphasizes essentials and defers the details, making engineering artifacts easier to use
E N D
Abstract Data Types • What does ‘abstract’ mean? • From Latin: to ‘pull out’—the essentials • To defer or hide the details • Abstraction emphasizes essentials and defers the details, making engineering artifacts easier to use • I don’t need a mechanic’s understanding of what’s under a car’s hood in order to drive it • What’s the car’s interface? • What’s the implementation?
Floating point numbers as ADTs • You don't need to know how much about floating point arithmetic works to use float • Indeed, the details can vary depending on processor, even virtual coprocessor • But the compiler hides all the details from you--some numeric ADTs are built-in • All you need to know is the syntax and meaning of operators, +, -, *, /, etc. • See multimedia: ADT for digits (properties)
ADT = properties + operations • An ADT describes a set of objects sharing the same properties and behaviors • The properties of an ADT are its data (representing the internal state of each object • double d; -- bits representing exponent & mantissa are its data or state • The behaviors of an ADT are its operations or functions (operations on each instance) • sqrt(d) / 2; //operators & functions are its behaviors • Thus, an ADT couples its data and operations • OOP emphasizes data abstraction
Design by contract • ADT is a formal description, not code • Independent of any programming language • Why is code independence a good idea? • Promotes design by contract: • Suppler/client responsibilities specified explicitly • So they can be enforced, if necessary • E.g., a contract for writing a book: • Contract specifies the book that the author will write • Also specifies the royalties the publisher will pay, etc.
Generic Queue ADT • An ADT specification has six parts • First 3 deal with syntax: NAME, SETS and SIGNATURES NAME Queue<I> SETS I set of all items (generic type) Q set of all Queues B set of Boolean (elements T and F) N set of natural numbers, including 0 • NAME specifies an identifier for the type • Generic parameter, <I>, may specify elements of collections • SETS specifies types of all parameters in SIGNATURES
SIGNATURES section (see umprobso—“you are adding”) SIGNATURES Queue() -> Q front(Q) -/-> I isEmpty(Q) -> B enqueue(Q, I) -> Q length(Q) -> N dequeue(Q) -/-> Q • SIGNATURES specifies the operations or services provided by ADT • Notation of mathematical functions, with one or more inputs and producing one result: • isEmpty(Q) -> B: Given a Queue (domain), produces a Boolean (range) • Functions have no side effects at all: • front(Q): given a Q, returns an item (no change) • enqueue(Q, I): returns a NEW Queue • dequeue(Q): returns another Queue • Functional approach may seem inefficient, but facilitates semantics • Implementation should preserve the abstract behavior of ADT • Syntax is relatively easy to specify; semantics is a bit harder….
Full vs. partial functions SIGNATURES Queue() -> Q front(Q) -/-> I isEmpty(Q) -> B enqueue(Q, I) -> Q length(Q) -> N dequeue(Q) -/-> Q • -> denotes a full function over the set Q • Always produces the specified output • ‑/‑> denotes a partial function over the set Q • May not always produce the specified output • Instead, its result may be undefined • When is front undefined? When is enQueue undefined? • Answering these questions about partial functions is semantics • Specifically, the preconditions: • A partial function is undefined if any of its preconditions do not hold
Exercise: Stack ADT syntax • Define the NAME, SETS and SIGNATURES of an ADT for stacks (assume unlimited size) NAME Stack<i> SETS I set of all items S set of all Stacks B set of Boolean SIGNATURES Stack() -> S push(S) --> I isEmpty(S) -> B pop(S) -/> Q top(S) -/-> I
Semantics of ADTs • 3 more sections for semantics of ADTs: variables, preconditions, and postconditions VARIABLES i:I; q, r:Q; n:N; b:B PRECONDITIONS front(q) -> isEmpty (q) = false dequeue(q) -> isEmpty (q) = false • VARIABLES -- declares instances of SETS, needed in PRE- and POST-CONDITIONS • How are the variables used in PRECONDITIONS? • What is the scope of these variables?
Preconditions • Specify constraints on any partial functions, indicating when they fail • front(q) -> isEmpty (q) = false //What does this constraint tell you? • PRECONDITIONs very explicit about the when a partial function fails • Formalizes design by contract: analogous to written business contracts • Inspires confidence between clients and suppliers of products • ADT specifies a contract between the supplier and client of an ADT • Supplier warrants that ADT will produce the specified behavior • so long as client provides the expected inputs • so long as client doesn’t violate the pre-conditions, behaviors will work • if the client violates the contract (any pre-condition), the behavior fails • Yet even the failure is predictable and can be handled predictably • Thus PRECONDITIONS also set up exception handling • Note: no need to include trivial preconditions, e.g., isEmpty(q) -> true.
Exercise: Stack ADT preconditions • Define preconditions (and variables) for Stack ADT NAME Stack<i> SETS I set of all items S set of all Stacks B set of Boolean SIGNATURES Stack() -> S push(I,S) --> S isEmpty(S) -> B pop(S) -/> S top(S) -/-> I VARIABLES s:Stack; i:Item; PRECONDITONS top(s) -> isEmpty(s) = false pop(s) -> isEmpty(s) = false
Postconditions • Define effects of functions, i.e., what they accomplish POSTCONDITIONS Queue() = (qList = List()) isEmpty(q) = null(qList) length(q) = length(qList) front(q) = head(qList) enqueue(q,i) = (qList = append(qList, i)) dequeue(q,i) = (qList = tail(qList, i)) • What are we assuming already exists in these postconditions? • List ADT has already been defined • Why is constructive semantics a good fit for OOP? • Reusing List implies a constructive semantics, building from other ADTs, already defined • What does first postcondition tell you? • What does second postcondition tell you?
Axiomatic semantics • Defines relations between operations strictly in terms of universal axioms (self-evident truths) • Axioms define an ADT independently of other ADTs • Constructive approach builds new ADTs based on knowledge of existing ones • The buck has to stop somewhere: e.g., the List ADT uses an axiomatic semantics
List postconditions (axioms) • null(List()) = true //How is this self-evident? • null(prepend(list1,i)) = null(append(list1,i)) = false //Explain? • length(List()) = 0 • length(append(list1, i)) = length(list1)+1 • tail(append(list1,i)) = if null(list1) then [] else append(tail(list1),i))
Constructive semantics(See umprobso, “Queue of football”) • Explain rest of Queue’s postconditions: front(q) = head(qList) enqueue(q,i) = (qList = append(qList, i)) dequeue(q,i) = (qList = tail(qList, i)) • Why would this be harder with axioms? • (See umprobso, “axiomatic”)
Exercise: Stack ADT postconditions • Define postconditions for Stack ADT NAME Stack<i> SETS I set of all items S set of all Stacks B set of Boolean SIGNATURES Stack() -> S push(S) --> I isEmpty(S) -> B pop(S) -/> S top(S) -/-> I VARIABLES s:Stack; i:Item; POSTCONDITIONS Stack() = (sList = List()) isEmpty(s) = null(sList) top(s) = head(sList) pop(s) = (sList = front(sList)) push(s,i) = (sList = prepend(sList, i))
Inheritance and ADTs • See Employee example • How does inheritance affect name section? • NAME Employee SUPERTYPES Person • How does inheritance affect other sections? • Employee inherits functions for name, address, etc, from Person • Inherits both syntax (SIGNATURES) and semantics • Only redefine functions in Employee if they do something different • Employee just supplies new constructor, GROSS_PAY, TAX_DUE • Semantics can benefit further from reuse implied by inheritance • Constructor for Employee invokes constructor for Person • Could add notation {abstract} to specify abstract functions
Why define ADTs? • Makes contract between designer and programmers explicit • Eliminates vagueness about what functions (operations or methods) do • Eiffel provides assertions to support programming by contract • Assertions have been added to Java • Sets up unit testing
Domain Model and Operation Contracts • A Domain Model is a visual representation of conceptual classes in a domain of interest. • Operation Contracts describe detailed system behavior of operations • In terms of state changes to objects in the Domain Model, after a system event has executed
Example Operation Contract from Larman: enterItem Contract CO2: enterItem Operation: enterItem(itemID : ItemID, quantity : integer) Cross References: Use Cases: Process Sale Preconditions: There is a Sale Underway. Postconditions: -A SalesLineItem instance sli was created (instance creation) -sli was associated with the current Sale (association formed) -sli.quantity became quantity (attribute modification) -sli was associated with a ProductSpecification, based on itemID match (association formed) How does it differ from an ADT spec?
Postconditions • Describe changes in the state of objects in the Domain Model • Include instances created, associations formed or broken, and attributes changed • Postconditions are not actions to perform • Rather, they are declarations about Domain Model objects that are true when the operation has finished
Writing Postconditions: Past Tense • Express postconditions in the past tense, to emphasize they are declarations about a state change in the past. • (better) A SalesLineItem was created. • (worse) Create a SalesLineItem. • Why?
The Spirit of Postconditions: The Stage and Curtain • System and it’s objects are presented on a theatre stage • Before the operation, snapshot of the stage. • Close the curtains on the stage, and apply the system operation • Open curtains and take a second picture • Compare the before and after pictures, and express as postconditions the changes in the state of the stage • (A SalesLineItem was created…).
Writing Contracts Leads to Domain Model Updates • New conceptual classes, attributes, or associations in the Domain Model are often discovered during contract writing • Enhance the Domain Model as you make new discoveries while thinking through the operation contracts
Guidelines: Contracts • To make contracts: • Identify system operations from SSDs • For system operations that are complex and perhaps subtle in their own results, or which are not clear in the use case, construct a contract • To describe the postconditions, use: - instance creation and deletion - attribute modification - associations formed and broken
System Sequence Diagram and ADT assignment • Your assignment (on Blackboard): • Improve your domain analysis • Per my comments • Develop a System Sequence Diagram for the ATM problem • Develop ADT design/Operation contracts for the Fruit problem • Extra credit: design user interface ADTs for either • loosely coupled to problem domain ADT • Due September 30