Zach Tatlock / Winter 2016 CSE 331 Software Design and Implementation Lecture 6 Representation Invariants.

Slides:



Advertisements
Similar presentations
CSE 331 SOFTWARE DESIGN & IMPLEMENTATION DEBUGGING Autumn 2011 Bug-Date: Sept 9, 1947.
Advertisements

Composition CMSC 202. Code Reuse Effective software development relies on reusing existing code. Code reuse must be more than just copying code and changing.
David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 6: Reasoning about Data Abstractions.
Data Abstraction II SWE 619 Software Construction Last Modified, Spring 2009 Paul Ammann.
Object Oriented Design An object combines data and operations on that data (object is an instance of class) data: class variables operations: methods Three.
CSE 331 SOFTWARE DESIGN & IMPLEMENTATION ABSTRACT DATA TYPES II Autumn 2011.
Specifications Liskov Chapter 9 SWE 619 Last Updated Fall 2008.
CSE 331 Software Design & Implementation Dan Grossman Fall 2014 Data Abstraction: Abstract Data Types (ADTs) (Based on slides by Mike Ernst, David Notkin,
Slides by Vinod Rathnam with material from Alex Mariakakis Kellen Donohue, David Mailhot, and Hal Perkins Midterm Review.
Computer Science 340 Software Design & Testing Design By Contract.
Procedure specifications CSE 331. Outline Satisfying a specification; substitutability Stronger and weaker specifications - Comparing by hand - Comparing.
Cs2220: Engineering Software Class 8: Implementing Data Abstractions Fall 2010 University of Virginia David Evans.
1 Abstraction  Identify important aspects and ignore the details  Permeates software development programming languages are abstractions built on hardware.
Data Abstraction CS 201j: Engineering Software University of Virginia Computer Science Nathanael Paul
Cs205: engineering software university of virginia fall 2006 Data Abstraction David Evans
23-Oct-15 Abstract Data Types. 2 Data types A data type is characterized by: a set of values a data representation, which is common to all these values,
13-1 Sets, Bags, and Tables Exam 1 due Friday, March 16 Wellesley College CS230 Lecture 13 Thursday, March 15 Handout #23.
Reasoning about programs March CSE 403, Winter 2011, Brun.
(c) University of Washington15-1 CSC 143 Java List Implementation via Arrays Reading: 13.
Data Abstractions EECE 310: Software Engineering.
CSE 331 Software Design & Implementation Hal Perkins Autumn 2012 Abstract Data Types – Examples / Summary (Based on slides by Mike Ernst and David Notkin)
ANU COMP2110 Software Design in 2003 Lecture 10Slide 1 COMP2110 Software Design in 2004 Lecture 12 Documenting Detailed Design How to write down detailed.
SWE 4743 Abstract Data Types Richard Gesick. SWE Abstract Data Types Object-oriented design is based on the theory of abstract data types Domain.
Understanding ADTs CSE 331 University of Washington.
Representation invariants and abstraction functions CSE 331 UW CSE.
PROGRAMMING PRE- AND POSTCONDITIONS, INVARIANTS AND METHOD CONTRACTS B MODULE 2: SOFTWARE SYSTEMS 13 NOVEMBER 2013.
CSE 331 Software Design & Implementation Dan Grossman Fall 2014 Abstraction Functions (Based on slides by Mike Ernst, David Notkin, Hal Perkins)
CSE 331 Software Design & Implementation Hal Perkins Winter 2015 Data Abstraction: Abstract Data Types (ADTs) (Based on slides by Mike Ernst, Dan Grossman,
CSE 331 SOFTWARE DESIGN & IMPLEMENTATION ABSTRACT DATA TYPES Autumn 2011.
Defensive Programming. Good programming practices that protect you from your own programming mistakes, as well as those of others – Assertions – Parameter.
David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 7: A Tale of Two Graphs (and.
CSC 243 – Java Programming, Spring, 2014 Week 4, Interfaces, Derived Classes, and Abstract Classes.
CPSC 252 ADTs and C++ Classes Page 1 Abstract data types (ADTs) An abstract data type is a user-defined data type that has: private data hidden inside.
David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 5: Implementing Data Abstractions.
Representation Invariants and Abstraction Functions.
Reasoning and Design (and Assertions). How to Design Your Code The hard way: Just start coding. When something doesn’t work, code some more! The easier.
© Bertrand Meyer and Yishai Feldman Notice Some of the material is taken from Object-Oriented Software Construction, 2nd edition, by Bertrand Meyer (Prentice.
CSC 243 – Java Programming, Fall, 2008 Tuesday, September 30, end of week 5, Interfaces, Derived Classes, and Abstract Classes.
Slides by Alex Mariakakis Section 5: Midterm Review.
CSE 331 Software Design & Implementation Hal Perkins Autumn 2012 Data Abstraction: Abstract Data Types (ADTs) (Based on slides by Mike Ernst and David.
CSE 374 Programming Concepts & Tools Hal Perkins Fall 2015 Lecture 17 – Specifications, error checking & assert.
EECE 310: Software Engineering
CSE 331 Software Design & Implementation
CSE 331 Software Design & Implementation
CSE 374 Programming Concepts & Tools
CSE 331 Software Design and Implementation
Specifications Liskov Chapter 9
Design by Contract Fall 2016 Version.
CSE 331 Software Design and Implementation
CSE 331 Software Design and Implementation
CSE373: Data Structures & Algorithms Lecture 25: Software-Design Interlude – Preserving Abstractions Catie Baker Spring 2015.
CSE 331 Software Design & Implementation
CSE 331 Software Design and Implementation
CSE 331 Software Design and Implementation
Data Abstraction David Evans cs205: engineering software
SWE 619 Software Construction Last Modified, Fall 2015 Paul Ammann
CSE373: Data Structures & Algorithms Lecture 16: Software-Design Interlude – Preserving Abstractions Dan Grossman Fall 2013.
Lecture 7: A Tale of Two Graphs CS201j: Engineering Software
Lecture 4: Data Abstraction CS201j: Engineering Software
CSE 303 Concepts and Tools for Software Development
CSE 331 Software Design & Implementation
CSE 331 Software Design and Implementation
CSE 331 Software Design & Implementation
CSE 331 Software Design & Implementation
Assertions References: internet notes; Bertrand Meyer, Object-Oriented Software Construction; 4/25/2019.
CSE 331 Software Design & Implementation
Computer Science 340 Software Design & Testing
slides created by Ethan Apter and Marty Stepp
Software Specifications
slides created by Marty Stepp and Hélène Martin
Presentation transcript:

Zach Tatlock / Winter 2016 CSE 331 Software Design and Implementation Lecture 6 Representation Invariants

ADTs are defined by a specification Abstract state + collection of procedural abstractions –Not a collection of procedures Together, these procedural abstractions provide some set of values All the ways of directly using that set of values –Creating –Manipulating –Observing Creators and producers: make new values Mutators: change the value (but don’t affect == ) Observers: allow one to distinguish different values

ADTs and specs Abs Values ADT Values - from producers - from value in ADT + operation

ADTs and specifications So far, we have only specified ADTs –Specification makes no reference to the implementation Of course, we need [guidelines for how] to implement ADTs Of course, we need [guidelines for how] to ensure our implementations satisfy our specifications Two intellectual tools are really helpful…

Connecting implementations to specs Representation Invariant: maps Object → boolean –Indicates if an instance is well-formed –Defines the set of valid concrete values –Only values in the valid set make sense as implementations of an abstract value –For implementors/debuggers/maintainers of the abstraction: no object should ever violate the rep invariant Such an object has no useful meaning Abstraction Function: maps Object → abstract value –What the data structure means as an abstract value –How the data structure is to be interpreted –Only defined on objects meeting the rep invariant –For implementors/debuggers/maintainers of the abstraction: Each procedure should meet its spec (abstract values) by “doing the right thing” with the concrete representation

Implementing a Data Abstraction (ADT) To implement a data abstraction: –Select the representation of instances, “the rep” In Java, typically instances of some class you define –Implement operations in terms of that rep Choose a representation so that: –It is possible to implement required operations –The most frequently used operations are efficient But which will these be? Abstraction allows the rep to change later

Example: CharSet Abstraction // Overview: A CharSet is a finite mutable set of Characters creates a fresh, empty CharSet public CharSet() {…} this this post = this pre + {c} public void insert(Character c) {…} this this post = this pre - {c} public void delete(Character c) {…} (c  this) public boolean member(Character c) {…} cardinality of this public int size() {…}

An implementation: Is it right? class CharSet { private List elts = new ArrayList (); public void insert(Character c) { elts.add(c); } public void delete(Character c) { elts.remove(c); } public boolean member(Character c) { return elts.contains(c); } public int size() { return elts.size(); } CharSet s = new CharSet(); Character a = new Character('a'); s.insert(a); s.delete(a); if (s.member(a)) System.out.print("wrong"); else System.out.print("right"); Where is the error?

Where Is the Error? If you can answer this, then you know what to fix Perhaps delete is wrong –Should remove all occurrences? Perhaps insert is wrong –Should not insert a character that is already there? How can we know? –The representation invariant tells us –If it’s “our code”, this is how we document our choice for “the right answer”

The representation invariant Defines data structure well-formedness Must hold before and after every CharSet operation Operations (methods) may depend on it Write it like this: class CharSet { // Rep invariant: // elts has no nulls and no duplicates private List elts = … … Or, more formally (if you prefer):  indices i of elts. elts.elementAt(i) ≠ null  indices i, j of elts. elts.elementAt(i).equals(elts.elementAt(j))  i = j

Now we can locate the error // Rep invariant: // elts has no nulls and no duplicates public void insert(Character c) { elts.add(c); } public void delete(Character c) { elts.remove(c); }

Another example class Account { private int balance; // history of all transactions private List transactions; … } Real-world constraints: Balance ≥ 0 Balance = Σ i transactions.get(i).amount Implementation-related constraints: Transactions ≠ null No nulls in transactions

Checking rep invariants Should code check that the rep invariant holds? –Yes, if it’s inexpensive [depends on the invariant] –Yes, for debugging [even when it’s expensive] –Often hard to justify turning the checking off –Some private methods need not check (Why?) A great debugging technique: Design your code to catch bugs by implementing and using rep-invariant checking

Checking the rep invariant Rule of thumb: check on entry and on exit (why?) public void delete(Character c) { checkRep(); elts.remove(c); // Is this guaranteed to get called? // (could guarantee it with a finally block) checkRep(); } … /** Verify that elts contains no duplicates. */ private void checkRep() { for (int i = 0; i < elts.size(); i++) { assert elts.indexOf(elts.elementAt(i)) == i; }

Practice defensive programming Assume that you will make mistakes Write and incorporate code designed to catch them –On entry: Check rep invariant Check preconditions –On exit: Check rep invariant Check postconditions Checking the rep invariant helps you discover errors Reasoning about the rep invariant helps you avoid errors

Listing the elements of a CharSet Consider adding the following method to CharSet // returns: a List containing the members of this public List getElts(); Consider this implementation: // Rep invariant: elts has no nulls and no dups public List getElts() { return elts; } Does the implementation of getElts preserve the rep invariant? Kind of, sort of, not really….

Representation exposure Consider this client code (outside the CharSet implementation): CharSet s = new CharSet(); Character a = new Character(’a’); s.insert(a); s.getElts().add(a); s.delete(a); if (s.member(a)) … Representation exposure is external access to the rep Representation exposure is almost always evil A big deal, a common bug, you now have a name for it! If you do it, document why and how –And feel guilty about it!

Avoiding representation exposure Understand what representation exposure is Design ADT implementations to make sure it doesn’t happen Treat rep exposure as a bug: fix your bugs Test for it with adversarial clients: –Pass values to methods and then mutate them –Mutate values returned from methods

private is not enough Making fields private does not suffice to prevent rep exposure –See our example –Issue is aliasing of mutable data inside and outside the abstraction So private is a hint to you: no aliases outside abstraction to references to mutable data reachable from private fields Two general ways to avoid representation exposure…

Avoiding rep exposure (way #1) One way to avoid rep exposure is to make copies of all data that cross the abstraction barrier –Copy in [parameters that become part of the implementation] –Copy out [results that are part of the implementation] Examples of copying (assume Point is a mutable ADT): class Line { private Point s, e; public Line(Point s, Point e) { this.s = new Point(s.x,s.y); this.e = new Point(e.x,e.y); } public Point getStart() { return new Point(this.s.x,this.s.y); } …

Need deep copying “Shallow” copying is not enough –Prevent any aliasing to mutable data inside/outside abstraction What’s the bug (assuming Point is a mutable ADT)? class PointSet { private List points = … public List getElts() { return new ArrayList (points); } Not in example: Also need deep copying on “copy in”

Avoiding rep exposure (way #2) One way to avoid rep exposure is to exploit the immutability of (other) ADTs the implementation uses –Aliasing is no problem if nobody can change data Have to mutate the rep to break the rep invariant Examples (assuming Point is an immutable ADT): class Line { private Point s, e; public Line(Point s, Point e) { this.s = s; this.e = e; } public Point getStart() { return this.s; } …

Why [not] immutability? Several advantages of immutability –Aliasing does not matter –No need to make copies with identical contents –Rep invariants cannot be broken –See CSE341 for more! Does require different designs (e.g., if Point immutable) void raiseLine(double deltaY) { this.s = new Point(s.x, s.y+deltaY); this.e = new Point(e.x, e.y+deltaY); } Immutable classes in Java libraries include String, Character, Integer, …

Deepness, redux An immutable ADT must be immutable “all the way down” –No references reachable to data that may be mutated So combining our two ways to avoid rep exposure: –Must copy-in, copy-out “all the way down” to immutable parts

Back to getElts Recall our initial rep-exposure example: class CharSet { // Rep invariant: elts has no nulls and no dups private List elts = …; // returns: elts currently in the set public List getElts() { return new ArrayList (elts); //copy out! } … }

An alternative // returns: elts currently in the set public List getElts() { // version 1 return new ArrayList (elts);//copy out! } public List getElts() { // version 2 return Collections.unmodifiableList (elts); } From the JavaDoc for Collections.unmodifiableList : Returns an unmodifiable view of the specified list. This method allows modules to provide users with "read-only" access to internal lists. Query operations on the returned list "read through" to the specified list, and attempts to modify the returned list… result in an UnsupportedOperationException.

The good news public List getElts() { // version 2 return Collections.unmodifiableList (elts); } Clients cannot modify (mutate) the rep So they cannot break the rep invariant (For long lists,) more efficient than copy out Uses standard libraries

The bad news public List getElts() { // version 1 return new ArrayList (elts);//copy out! } public List getElts() { // version 2 return Collections.unmodifiableList (elts); } The two implementations do not do the same thing! –Both avoid allowing clients to break the rep invariant –Both return a list containing the elements But consider: xs = s.getElts(); s.insert('a'); xs.contains('a'); Version 2 is observing an exposed rep, leading to different behavior

Different specifications Ambiguity of “returns a list containing the current set elements” “returns a fresh mutable list containing the elements in the set at the time of the call” versus “returns read-only access to a list that the ADT continues to update to hold the current elements in the set” A third spec weaker than both [but less simple and useful!] “returns a list containing the current set elements. Behavior is unspecified (!) if client attempts to mutate the list or to access the list after the set’s elements are changed” Also note: Version 2’s spec also makes changing the rep later harder –Only “simple” to implement with rep as a List