Sie sind auf Seite 1von 21

Iain McGinniss and Simon Gay

University of Glasgow
Overview
 API design & enforcement
 The mistakes programmers make
 What is typestate?
 What is Hanoi?
 Future work
API Specification
 Designer must be as precise as possible
 What will be provided by an implementation
 What will be expected in return from the client
 ... a contract!
 Implementation and client code must each hold up their
end of the bargain
 What happens when a contract is violated?
The API Police!
Contract constraints
 Legal method calls
 What methods exist? With what parameters?
 Can I pass a null as a parameter?
 Legal sequences of method calls
 Can I call any methods after I call close()?
 What are the consequences if I don’t call close()?
 Aliasing constraints
 Once I pass my reference as a parameter, can I use it
again?
Static type checking
 Wanted: guaranteed safety properties without running
the program
 Types express what is legal, type checking enforces this
 Java types do not convey everything that is important!
 No specification of legal sequences
 No specification of alias restrictions
 No specification of concurrency restrictions
 ... etc.
 So, we must informally document these constraints...
Did you read the fine print?
 Excerpt from the PC Pitstop Software EULA:

SPECIAL CONSIDERATION
A special consideration which may include financial
compensation will be awarded to a limited number of
authorized licensee who read this section of the license
agreement and contact PC Pitstop at
consideration@pcpitstop.com. This offer can be withdrawn
at any time.

 It took 4 months and 3000 downloads for someone to


notice and claim the $1000 prize!
An example with HashSet
MutableInteger a = new MutableInteger(1);
MutableInteger b = new MutableInteger(1);
HashSet set = new HashSet();
set.add(a);
a.changeTo(2); // change internal value
out.println("a is in set: " + set.contains(a));
out.println("b is in set: " + set.contains(b));

What will this program output?


Survey says...
 a is in set: false
b is in set: false
 Why? The fine print! From java.util.Set’s javadoc:

Note: Great care must be exercised if mutable objects


are used as set elements. The behavior of a set is not
specified if the value of an object is changed in a
manner that affects equals comparisons while the
object is an element in the set.
What about sequences?
Iterator it = myList.iterator();
while(it.hasNext()) {
out.println(it.next());
}
it.remove(); // remove the last item

 Is this code safe?


 Not if the list is empty!
 Docs: Throws IllegalStateException - if the next method
has not yet been called
What is Typestate?
"Whereas the type of a data object determines the set
of operations ever permitted on the object, the
typestate determines the subset of these operations
which is permitted in a particular context"
- Strom, Yemini 1986

• Original idea: null reference is a ‘state’ where no


methods are available
• Concept, in principle, extends to more complex, user
defined state machines.
Upgrading our API Police
Focusing on sequences
 Many APIs have state machine like behaviour
 Iterators
 Databases – Connection, ResultSet
 File & Network I/O
 Difficult to document in a concise, human readable,
machine verifiable form
 Hanoi to the rescue!
What is Hanoi?
 Hanoi is a model for defining stateful behaviour in
objects
 Primary design goal: easy to read, easy to write
 Hierarchical state machines
 Make retroactive definition of models possible
 Avoided using annotations – fragmented definitions
are hard to understand
 Models are stored in a separate “.state” file next to the
“.java” file
 Or in a parallel directory structure mirroring the
package, for existing compiled code
Hanoi model for Iterator
NEXT_AVAILABLE {
next() -> CAN_REMOVE
}

CAN_REMOVE {
remove() -> DEFAULT
}

hasNext() :: true -> NEXT_AVAILABLE


hasNext() :: false -> <self>
One slight complication...
 Consider the following code:

while(it.hasNext()) {
Object a = it.next();
if(it.hasNext()) {
// what can we do here?
}
}

 At this point we can call next() AND remove()


 Our model does not allow calling remove() at this point!
Refined model for Iterator
NEXT_AVAILABLE {
NEXT_AVAILABLE_CAN_REMOVE {
remove() -> NEXT_AVAILABLE
}
next() -> CAN_REMOVE
}

CAN_REMOVE {
remove() -> DEFAULT
hasNext() :: true -> NEXT_AVAILABLE_CAN_REMOVE
}

hasNext() :: true -> HAS_NEXT


hasNext() :: false -> <self>
Enforcing the model
 Implemented as dynamic proxy in Java
 Intercepts calls to an interface an object implements
 Checks method call is legal in currently known state
 Uses return value to decide next state
 If illegal method call detected, throw unchecked
exception
 Implementation no longer needs to guard against
illegal usage!
 Alternative: Log the event & stop monitoring
What about aliasing?
 Aliasing causes big problems for static analysis
 Sharing the use of an iterator, even without threads, can
lead to violations of the model
 We need a way for programmers to declare the aliasing
restrictions on their objects
 “cannot be shared”, “can have one writer and many
readers”, etc. Many different forms of alias restriction
 Fractional Permissions (Boyland 2003)
 Dynamic checking is easier however – as long as one
proxy is used!
Future Work
 Static analysis of Hanoi models
 Difficult problem space, active research area
 Include aliasing rules in model
 Parallel state machines
 Partition models into independent parts
 May help with aliasing
 May help with modelling concurrently shared objects
Questions?

The API police are watching!


iainmcg@dcs.gla.ac.uk

Das könnte Ihnen auch gefallen