Quick viewing(Text Mode)

Examples of Design by Contract in Java Using Contract, the Design by Contracttm Tool for Javatm

Examples of Design by Contract in Java Using Contract, the Design by Contracttm Tool for Javatm

Object World Berlin ‘99 & Components Berlin, May 17th-20th 1999

Examples of in Java using Contract, the Design by Contracttm Tool for Javatm

Reto Kramer, [email protected]

Java is a registered trademark of Sun Microsystems Inc. Design by Contract is a registered trademark of ISE Inc. Design by Contract - What is it ?

n Classes of a system communicate with one another on the basis of precisely defined benefits and obligations.

[, CACM, Vol. 36, No 9, 1992]

Cambridge Technology Partners © Reto Kramer, [email protected] Example - Class Person

n /** n New comment-tags: * @ age_ > 0 @pre, @post, */ class Person { @invariant protected age_; n All instances of person

/** must have a positive * @post return > 0 age. */ n Clients are promised int getAge() {..} that the age is /** positive provided that: * @pre age > 0 n */ Clients are obligated void setAge( int age ){..} to pass positive ages only. Service will be ...} denied otherwise.

Cambridge Technology Partners © Reto Kramer, [email protected] Meaning of pre, post and invariant

n If are n If any is not obeyed by the violated, it uncovers a client of the class’ problem on the service method, the service provider side. provider will deny its n If any service ! is violated it uncovers a problem on the service provider side. n The problem can be – implementation error – not specific enough preconditions

Cambridge Technology Partners © Reto Kramer, [email protected] Benefits - Obligations

Benefit Obligation

- no need to check output values satisfy pre- - result guaranteed to conditions

Client comply to postcondition 4 1

2 3 - no need to check input values satisfy post- - input guaranteed to conditions comply to

Provider

Cambridge Technology Partners © Reto Kramer, [email protected] So, is it like “assert.h” ?

n Assert statements are a great tool - design by contract even goes one step beyond them: – assert does not provide a contract – clients can not see asserts as part of the interface – does not have a semantic associated with it – not explicit whether they represent pre-, post- conditions or invariants – no OO support (e.g. inheritance), see later – does not lead to “automatic” documentation

Cambridge Technology Partners © Reto Kramer, [email protected] Example - A Simple Interface

n 1: interface Person { 1: class Employee implements Person { 2: 2: 3: /**age always positive 3: protected int age_; 4: * @post return > 0 4: 5: */ 5: public int getAge() { 6: int getAge(); 6: return age_; 7: 7: }; 8: /** age always positive 8: 9: * @pre age > 0 9: public void setAge( int age ) { 10: */ 10: age_ = age; 11: void setAge( int age ); 11: }; 12: } 12: }

Cambridge Technology Partners © Reto Kramer, [email protected] Benefits - General

n failures occur close to the faults (I.e. during integration tests and field use!) n interface documentation always up-to-date, can be trusted! n documentation can be generated automatically (iDoclet) n contract specification serves as a basis for black box testing of classes (test-driver spec)

Cambridge Technology Partners © Reto Kramer, [email protected] Benefits - Abstraction and Precision

Interface A Invariant … Precise Type (class) model with … precise meaning ... Precondition, Postcondition (design by contract)

Type (class) model expections/ effects (pre-, post) inter- Use cases action diagrams Textual requirements business rules description (invariants) Ambiguous

Abstract Terms Specific Terms

Cambridge Technology Partners © Reto Kramer, [email protected] Benefits - Project Phases

API

Scope Analysis Design Subsystem API Subsystem Stub impl. use cases specification requirements functionality business case domain model subsystems Stub APIs APIs

API

Implementation Integration Unit Test against Stubs & Test

Stub APIs APIs

Acceptance Maintenance Rollout Test Extension

Cambridge Technology Partners © Reto Kramer, [email protected] APIs Benefits - Project Roles

n Class user n Project manager – – easier to preserve design guaranteed over a long time – can trust documentation – reduced maintenance n Class provider effort in the long run (failure close to fault) – preconditions guaranteed – enables unambiguous – automatic documentation interface specification n Test manager – lower documentation cost – more accurate test-effort – fearless reuse (enables estimation specification of reusable – black box spec for free classes)

Cambridge Technology Partners © Reto Kramer, [email protected] References

n iContract: http://www.reliable-systems.com n Books: – “Object Oriented ”, 2nd edition, Bertrand Meyer, Prentice Hall, 1997 – “Objects, Components and Frameworks with UML”, .F. D’Souza, A. Cameron Wills, Addison Wesley, 1999 n Eiffel [Interactive Software , ISE] http://www.eiffel.com n UML 1.1 / Object Constraint Language (OCL) http://www.rational.com

Cambridge Technology Partners © Reto Kramer, [email protected] iContract - the Tool

n source code pre-processor n no run-time library required n compatible with OCL – old value, x@pre – return value – quantifiers: forall, exists n supports Java type extension mechanisms (contract propagation)

Cambridge Technology Partners © Reto Kramer, [email protected] Tool Components

Class Instrumentation source-code with @pre, @post and @invariant annotations in comment Instrumentation paragraphs Repository SOURCE-CODE 2

Used for type .class extension class mechanisms __REP_C iContract.Tool

1

javac .java

class

4 3 not .java _I.java instrumented class class C __REP_C javac

instrumented 5 - instrumented source-code which checks pre-, postconditions and .class invariants. class C java

Cambridge Technology Partners © Reto Kramer, [email protected] Performance Tuning

n Check instrumentation n Files can be is done per .java file instrumented with any (public class) combination of checks n Performance critical for: classes can be excluded – pre- from the checks – post-conditions and – invariants

n E.g. if implementation is tested thoroughly, only check preconditions

Cambridge Technology Partners © Reto Kramer, [email protected] Java Language Support

2 Interface I packages implements A Q Interface J 1 extends package

Interface K B R 3 implements Interface M 4 extends Interface L C X

Interface N Innerclass

Cambridge Technology Partners © Reto Kramer, [email protected] Java Language Support (con’t)

n All but private methods n Default constructors are are instrumented with added to classes invariant checks. automatically, if needed n The finalize() method is n In constructors the not instrumented with delegation to this(…) and invariant checks. super(…) is put in front of n Invariant checks are the precondition check “synchronized” (javac demands this). n Recursive invariant checks are avoided automatically

Cambridge Technology Partners © Reto Kramer, [email protected] Specification Language

n Propositional logic with n Scope: quantifiers – as if the invariant were a n Any expression that method of the class, interface may appear in an if(...) – as if the pre- and condition may appear in postcondition were are a pre-, post- and statement of the method invariant expression

Cambridge Technology Partners © Reto Kramer, [email protected] Specification Language (con’t)

n forall Type t in | ->forAll(t | ) n exists Type t in | ->exists(t | ) n implies (same as OCL) – same as OCL

n Differences between iContract and OCL – syntactic & iContract needs to know Type!

Cambridge Technology Partners © Reto Kramer, [email protected] Specification Language (con’t)

n In postconditions references to the following pseudo-variables are allowed:

n return denotes the return value of a method – this is called “result” in OCL

n @pre denotes the value of the expression (e.g. variable) when the method was entered - notation from UML / OCL “old value reference” – same as OCL

Cambridge Technology Partners © Reto Kramer, [email protected] Example

n Office Management System – Manage the rooms available to a company. Provide new hires with office and support employees that move from one office to another.

n Focus on – Initial type model of domain (UML) – Add business constraints and rules (OCL) – Add precise meaning of operations (OCL) – Generate Java (iContract)

Cambridge Technology Partners © Reto Kramer, [email protected] Office Management Example (hire)

1 2

Company void Company:hire(Employee e)

- rooms->isEmpty() implies employees.isEmpty() pre: (e != null) && (!employees->includes(e)) - employees -> forAll (e | rooms -> includes(e.office)) post: - employees->forAll( e1 | - employees->includes(e) employees->forAll( e2 | (e1 != e2) implies (e1.room != e2.room)) - getAvailableRoom()@pre != getAvailableRoom() // hire must call an unspecified method that will // ensure that a new, available room is choosen 0..n Company Room rooms - e.office == getAvailableRoom() // SIDE EFFECT FREE! . boolean roomsAvailable() Room getAvailableRoom() . Room Company:getAvailableRoom() void hire(Employee e) void move(Employee e, Room newRoom) 1 office pre: roomsAvailable() post: 0..n employees - result != null - rooms->includes(result) Employee - !employees->exists(e | e.office == result) . - result == getAvailableRoom() // SIDE EFFECT FREE!

.

boolean Company:roomsAvailable()

pre: TRUE post: result == rooms->exists( room | !employees->exists( e | e.office == room))

Cambridge Technology Partners © Reto Kramer, [email protected] Office Management Example (move)

3 4 0..n void Company:move(Employee e, Room newRoom) Company Room rooms pre: . boolean roomsAvailable() - (e != null) && (newRoom != null) Room getAvailableRoom() isAvailable() - employees->includes(e) void hire(Employee e) - !employee->exists( e | e.office == newRoom ) void move(Employee e, Room newRoom) 1 office // newRoom is not anyones office

post: 0..n employees 0..1 - e.office == newRoom - !employee->exists( other | other.office == e.office@pre ) Employee // the employee’s (e) old office (e.office@pre) is not . owner // used by any other employee . 5 Room.isAvailable() ?? void Company:move(Employee e, Room newRoom)

pre: boolean Room:isAvailable() - (e != null) && (newRoom != null) - employees->includes(e) pre: TRUE - newRoom.isAvailable() post: - result == onwer != null post: - e.office == newRoom - [email protected]() - !newRoom.isAvailable()

Cambridge Technology Partners © Reto Kramer, [email protected] API Specification for Subsystem

n Assume Office n Specification of previous Management System to slides is mapped to Java be a subsystem of a package containing larger, total solution interfaces. n Hence requires proper separation of interface n but what about the from implementation. associations ?

for client n API Serves as a Need to create “get” specification methods for each role realizes in an association ... and provider Impl.

Cambridge Technology Partners © Reto Kramer, [email protected] API Specification for Subsystem

API

Company <> Room Employee boolean roomsAvailable() <> <> Room getAvailableRoom() . . void hire(Employee e) void move(Employee e, Room newRoom) boolean isAvailable() Vector getRooms() Room getOffice() Employee getOwner() Vector getEmployees()

realizes Implementation 0..n Company Room rooms . boolean roomsAvailable() Room getAvailableRoom() isAvailable() void hire(Employee e) void move(Employee e, Room newRoom) 1 office

0..n employees 0..1 Employee owner .

.

Cambridge Technology Partners © Reto Kramer, [email protected] Company iContract - rooms->isEmpty() implies employees.isEmpty() - employees -> forAll (e | rooms -> includes(e.office)) - employees->forAll( e1 | employees->forAll( e2 | (e1 != e2) implies (e1.room != e2.room)) n /** * @invariant getRooms().isEmpty() implies getEmployees.isEmpty() * @invariant forall Employee e in getEmployees().elements() | * getRooms.contains(e.getOffice()) * @invariant forall Employee e1 in getEmployees().elements() | * forall Employee e2 in getEmployees().elements() | * (e1!=e2) implies (e1.getOffice()!=e2.getOffice()) */ interface Company { void Company:move(Employee e, Room newRoom) /** pre: * @pre (e!=null) && (newRoom!=null) - (e != null) && (newRoom != null) - employees->includes(e) * .. - newRoom.isAvailable() * @post e.getOffice()@pre.isAvailable() */ post: - e.office == newRoom void move(Employee e, Room newRoom); - [email protected]() .. - !newRoom.isAvailable() }

iContract propagates API specification into implementing classes !

Cambridge Technology Partners © Reto Kramer, [email protected]