Download presentation
Presentation is loading. Please wait.
Published byArline Tyler Modified over 9 years ago
1
Component-Based Software Engineering Components and Interfaces Paul Krause
2
Lecture 3 - Interfaces Contents Interfaces as Contracts Future Proofing Non-functional requirements Specifying Pre- and Post-conditions Using assertions to check Conditions
3
Components and Interfaces A B1B2 A requires certain functionality to fulfil its obligations. B1 and/or B2 provide that functionality. An interface mediates between clients and providers.
4
Interfaces as contracts Can view an interface specification as a “contract” between the client and a provider So the interface specification must state: What the client needs to do What the client needs to do What a provider can rely on What a provider can rely on What a provider must promise in return What a provider must promise in return What the client can rely on What the client can rely on
5
Pre- and Post-Conditions Pre-conditions: What the client must establish before calling the operation What the client must establish before calling the operation The provider can rely on this condition being true whenever the operation is called The provider can rely on this condition being true whenever the operation is called Post-conditions: What the provider must establish before returning to the client What the provider must establish before returning to the client The client can rely on this condition being true whenever the call to the operation returns The client can rely on this condition being true whenever the call to the operation returns
6
Example public interface Directory { public void addEntry(String name, File file); // pre name != “” and file != null // post File file = map.get(name) } Associate pre- and post-conditions to every method in the interface
7
Lecture 3 - Interfaces Contents Interfaces as Contracts Future Proofing Non-functional requirements Specifying Pre- and Post-conditions Using assertions to check Conditions
8
Future proofing An interface acts as a contract between client and provider Suppose an interface remains unchanged Is there any scope for revising an implementation without introducing a risk of “breaking” old clients? Ans: The revised implementation may require less and/or provide more
9
Future Proofing public interface Arithmetic { public double processNumbers(double x, double y); // pre x > 5 and y > 5 // post if r = this.processNumbers(x, y) then r > 10 } public double processNumbers(double x, double y) { if ((x < 0) || (y < 0)) throw new IllegalArgumentException(“Args must be >=0”); return x + y + 20.0; }
10
Future Proofing x > 5 and y > 5 implies x >=0 and y >= 0 The new implementation requires less than the interface The implementation “weakens” the pre- conditions return >= 20 implies return > 10 The new implementation provides more than the interface specifies The implementation “strengthens” the post- conditions
11
Lecture 3 - Interfaces Contents Interfaces as Contracts Future Proofing Non-functional requirements Specifying Pre- and Post-conditions Using assertions to check Conditions
12
What else can go wrong? public interface Directory { public void addEntry(String name, File file); // pre name != “” and file != null // post File file = map.get(name) } strictly this is only a guarantee of partial correctness the operation either terminates correctly or does not terminate at all! progress conditions: something guaranteeing the pre-condition will lead to something guaranteeing the post-condition
13
Non-functional requirements We have seen how respecting pre- and post- conditions reduces the risk of a revised implementation “breaking” a client But are changes in the functional behaviour the only way an implementation can break a client? Consider a Maths interface, with methods to support an animation package What about a new implementation that improves accuracy? What about a new implementation that improves accuracy?
14
Specifying the Service Level Now add guarantees for levels of: Availability; Mean time between failures; Mean time to repair; Throughput; Data safety; Capacity.
15
Time and Space Requirements Specifying execution time is platform dependent So what can realistically be included in a contract? Could use complexity bounds E.g. perform an operation on n elements in n log n time, using at most log n additional storage cells E.g. perform an operation on n elements in n log n time, using at most log n additional storage cells A client can then determine the absolute time and space bounds for a given provider on a given platform
16
Lecture 3 - Interfaces Contents Interfaces as Contracts Future Proofing Non-functional requirements Specifying Pre- and Post-conditions Using assertions to check Conditions
17
Back to interfaces? Design Guideline: “When the functionality supported by a class can be implemented in different ways, it is advisable to separate the interface from the implementation” Xiaoping Jia And we can cast an object into its interface type if we only want to access its services
18
List as an example public interface List { public int size( ); public boolean isEmpty( ); public Object element(int i); public Object head( ); public Object last( ); public void insert(Object item, int i); public void insertHead(Object item); public void insertLast(Object item); // more… }
19
Implementations of List We can have several different implementations of the List interface: public class LinkedList implements List { } or: public class DynamicArray implements List { }
20
Interfaces as Contracts Interfaces specify the types of their associated methods, but say nothing about their behaviour We can improve on that!
21
Pre- and Post-Conditions Pre-conditions: What the client must establish before calling the operation What the client must establish before calling the operation The provider can rely on this condition being true whenever the operation is called The provider can rely on this condition being true whenever the operation is called Post-conditions: What the provider must establish before returning to the client What the provider must establish before returning to the client The client can rely on this condition being true whenever the call to the operation returns The client can rely on this condition being true whenever the call to the operation returns
22
Stage 1: Documentation Use “@pre” and “@post” as special tags for preconditions and postconditions: /** *@pre precondition * @post postcondition */ */ public void method1 { // … }
23
A boring example /** * Returns the number of elements in a list * * @pre true * @post @nochange */ public int size( );
24
A more interesting example /** * Returns the i-th element in the list * * @pre i >= 0 && i = 0 && i < size( ) * @post @nochange */ public Object element(int i);
25
Other logical expressions ==>logical implication logical equivalence logical equivalence @forall x : Range @ Expression Universally quantified expression @exists x : Range @ Expression [m … n]Integer range from m to n
26
A nasty example /** * Inserts a new element into a list at the i-th position * * @pre item != null && i >= 0 && i = 0 && i <= size( ) * @post size( ) == size( )@pre + 1 * @post @forall k : [0.. size( ) - 1] @ *(k element(k)@pre == element(k)) && *(k == i ==> item@pre == element(k)) && item@pre *(k > i ==> element(k-1)@pre == element(k) */ public void insert(Object item, int i);
27
An exercise Use this method to specify the interface to a method that inserts a new element to the head of a list
28
Solution /** * Inserts a new element at the head of a list * * @pre item != null * @post size( ) == size( )@pre + 1 * @post item@pre == element(0) item@pre * @ post @forall k : [1.. size( ) - 1] @ element(k-1)@pre == element(k) */ public void insertHead(Object item);
29
How does this help? As this stands, the comments provide guidance only They prescribe what should be done, but are agnostic about whether a specific implementation satisfies them We can, however, provide run-time checks through the use of Assertions
30
Lecture 3 - Interfaces Contents Interfaces as Contracts Future Proofing Non-functional requirements Specifying Pre- and Post-conditions Using assertions to check Conditions
31
Assertions are? Boolean conditions that are inserted into a program at strategic points We expect them to be true when the flow of control reaches each respective point If an assertion is true, it has no effect and the flow of control continues If an assertion is false, then execution stops at that point and an AssertionError is thrown
32
Where do you put them? Assertions on the preconditions of a method should be placed immediately on entry to the method Assertions on postconditions should be placed just prior to the return statement But remember that any references to the pre-state of variables must be instantiated upon entry to the method
33
LinkedList implements List /** * @pre item != null && i >= 0 && i = 0 && i <= size( ) * @post size( ) == size( )@pre + 1 */ public void insert(Object item, int i) { assert item != null && i >= 0 && i = 0 && i <= size( ); int size_pre = size( ); // // // // int size_post = size( ); assert size_post == size_pre + 1; }
34
Extra points to note Need JDK 1.4 or higher, and compile using: javac -source 1.4 Class.java javac -source 1.4 Class.java Execute the class with: java -ea Class java -ea Class In order to fully assert the postconditions, we usually need to clone an instance of a class before we modify it Use of assertions derived from preconditions is known as Defensive Programming Use of assertions derived from postconditions is also valuable in testing and debugging
35
Summary We have discussed the use of interfaces when there may be multiple ways of implementing certain functionality Including statements of pre- and post-conditions in the comment lines for each method declaration makes a richer specification Including the pre- and post-conditions in the implementation of each interface adds a further level of rigour (but has limited support in Java at present)
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.