Semla Design Method for use in Skywalker A

  • Slides: 29
Download presentation
Semla Design Method for use in Skywalker A Design Method with a Focus on

Semla Design Method for use in Skywalker A Design Method with a Focus on Semantic Descriptions Karlstad University Ericsson Infotech AB NUTEK Karlstad University Dept. of Computer Science 9/15/2020 Improved software quality through semantic descriptions (Skutt)

Overview • Data abstractions • Weak and strong contracts • Invariants Karlstad University Dept.

Overview • Data abstractions • Weak and strong contracts • Invariants Karlstad University Dept. of Computer Science Semla 2 page 2

An example: A web connection The other side Web. Connection the World Wide Web

An example: A web connection The other side Web. Connection the World Wide Web user. Name • String* other. User We want to model a possible connection across a network – The other side may or may not be connected – If connected, the other side has a defined user name which is copied across to our program Karlstad University Dept. of Computer Science Semla 2 page 3

Data abstractions • This is one possible model of a Web connection • I

Data abstractions • This is one possible model of a Web connection • I want to expose the property other. User • There is a difference between – an empty user name, means "user name not known" – no user name, means "there is no other party" • Suggest a class interface Karlstad University Dept. of Computer Science Semla 2 page 4 Web. Connection String* other. User

First attempt • Class interface – String* get. Other. User(); • What is the

First attempt • Class interface – String* get. Other. User(); • What is the mental process? – Return whatever is stored in the object – The user of the object needs to be aware of the storage conventions Karlstad University Dept. of Computer Science Web. Connection Semla 2 page 5 String* other. User String* get. Other. User();

Contract for the first attempt • • Precondition: Web. Connection – true Postcondition: String*

Contract for the first attempt • • Precondition: Web. Connection – true Postcondition: String* other. User – result = the value of the other. User variable What is gained in abstraction? String* get. Other. User(); – Nothing, possibly R/O – You might as well access the data directly Calling style the. Other = connection->get. Other. User(); if (the. Other != NULL) do. Something. With(the. Other); else handle. The. No. User. Case(); Karlstad University Dept. of Computer Science Semla 2 page 6

Second attempt • • Class interface – bool has. Other. User(); – String* get.

Second attempt • • Class interface – bool has. Other. User(); – String* get. Other. User(); Web. Connection What is the mental process? – Define the other user as a concept • Eithere is one or there is not – The user of this object does not need to be aware of the storage conventions • He works with the concept of ”another user" rather than with a stored value Karlstad University Dept. of Computer Science Semla 2 page 7 (attributes not disclosed) bool has. Other. User(); String* get. Other. User();

Contract for the second attempt • Precondition for has. Other. User: – true •

Contract for the second attempt • Precondition for has. Other. User: – true • Postcondition for has. Other. User: – result = true if there is another user defined, else false • What is the gain in abstraction? – The fact that there may or may not be an "other user" becomes a property of the class, not a value of a variable – No knowledge of the variable is needed to get the answer – The answer may in fact be evaluated Karlstad University Dept. of Computer Science Semla 2 page 8 Web. Connection bool has. Other. User(); String* get. Other. User();

Consequences of the second attempt • Possible calling style if (connection->has. Other. User()) {

Consequences of the second attempt • Possible calling style if (connection->has. Other. User()) { the. Other = connection->get. Other. User(); do. Something. With(the. Other); } else handle. The. No. User. Case(); Karlstad University Dept. of Computer Science Semla 2 page 9 Web. Connection bool has. Other. User(); String* get. Other. User();

What is the difference? • Your module may be exposed to clients that are

What is the difference? • Your module may be exposed to clients that are – yourself – trusted friends – colleagues within the same project – colleagues from other projects – external customers – API programmers – end users, through a user interface • Who do you trust? – To whom do you expose a strong or a weak contract? • A correct call is always your client’s responsibility – Even weak contracts fall back on the client – Error messages or exceptions must be caught by the client or user. Karlstad University Dept. of Computer Science Semla 2 page 10

The implication of a contract Precondition Postcondition • A precondition is a Boolean expression

The implication of a contract Precondition Postcondition • A precondition is a Boolean expression that must be true when an operation is called. • • A precondition is not a guard condition; it is a condition that must be true, not a way to optionally execute an operation. The condition is supposed to be true, and anything else is a programming error. It can be useful to test the precondition at the beginning of the operation for reliability, but this is in the nature of debugging a program. • • • Karlstad University Dept. of Computer Science • • A postcondition is a Boolean expression that must be true after the execution of an operation completes. It is an assertion, not an executable statement. The condition is supposed to be true, and anything else is a programming error. It can be useful to test the postcondition after the operation, but this is in the nature of debugging a program. Semla 2 page 11

The implication of a contract (cont’d) Precondition Postcondition • • • It is the

The implication of a contract (cont’d) Precondition Postcondition • • • It is the responsibility of the caller to satisfy the condition. It is not a condition that the receiver should have to check. If the condition is not satisfied, no statement can be made about the integrity of the operation of the system. It is liable to utter failure. A postcondition imposes a constraint on the implementor of an operation. Source: Rumbaugh, J. , Jacobson, I. , Booch, G. , The UML Reference Manual, Addison Wesley 1999. Parts of the descriptions have been rearranged to highlight similarities and differences. Karlstad University Dept. of Computer Science Semla 2 page 12

When to use strong contracts? • • Strong contracts is the default mode Use

When to use strong contracts? • • Strong contracts is the default mode Use strong contracts when • the client is yourself, whom you trust to write good code • the client is a programmer. – That is, whenever the client is a programmer, she/he can be trusted. Karlstad University Dept. of Computer Science Semla 2 page 13

When to use weak contracts? • • Weak contracts are the exception Use weak

When to use weak contracts? • • Weak contracts are the exception Use weak contracts for – end user communication (end users) • cases where the end user may interfere • user interfaces – unforeseeable internal problems • hardware problems • communications problems – very costly preconditions • matrix inversion • checking the precondition = doing the job – concurrent processing • another thread may break the precondition after the check Karlstad University Dept. of Computer Science Semla 2 page 14

Example Array • A class Array is an abstraction of a C int array

Example Array • A class Array is an abstraction of a C int array – an Array instance has a fixed lower index: 0 – an Array instance has a fixed number of elements defined at creation time • Constructor: – Array() • Precondition: true • Postcondition: number of elements = 0 – Array(int n) • Precondition: n >= 0 • Postcondition: number of elements = n, all elements = 0 Karlstad University Dept. of Computer Science Semla 2 page 15

Example Array • • • (*) Properties for Array a – int size() •

Example Array • • • (*) Properties for Array a – int size() • Precondition: true(*) • Postcondition: the number of elements in the array is returned Data access and assignment for Array a – a[i] • Precondition: i >= 0 and i < a. size() • Postcondition: a reference to the element at index ’i’ has been returned Usage of data access and assignment of Array a – Data access • n = a[i] – Data assignment • a[i] = n The precondition true will not be written out. No precondition = true Karlstad University Dept. of Computer Science Semla 2 page 16

Implementation details for Array • • • Assume the data storage is through a

Implementation details for Array • • • Assume the data storage is through a pointer – int *_data; Constructor Array(int n) { // assign storage for i elements of int _data = new int[n]; // initialize the elements to zero for (int i = 0; i < n; i++) _data[i] = 0; } No promises are given for illegal values of n – Let the program crash if it wants. It is the client’s problem. – Make the program crash if you want. Constructor Array(int n) { ASSERT (n >= 0) // validate the precondition // the rest of the constructor Karlstad University Dept. of Computer Science Semla 2 page 17

More implementation details for Array • • Data access int &operator[](int i) { return

More implementation details for Array • • Data access int &operator[](int i) { return _data[i]; } No promises are given for illegal values of i – Let the program crash if it wants. It is the client’s problem – Make the program crash if you want int &operator[](int i) { ASSERT ( (i >= 0) && (i < size()) ) return _data[i]; } – Any function called in the ASSERT must be side effect free Karlstad University Dept. of Computer Science Semla 2 page 18

Invariants Karlstad University Dept. of Computer Science 9/15/2020 Improved software quality through semantic descriptions

Invariants Karlstad University Dept. of Computer Science 9/15/2020 Improved software quality through semantic descriptions (Skutt)

An invariant is ”always” true • Established at creation • Maintained by all functions

An invariant is ”always” true • Established at creation • Maintained by all functions • • <<create>> Establish invariant Every function implementation can always assume that the invariant is true Every function implementation should always restore the invariant operation() {I} Maintain invariant {I} operation() Maintain • {I} means that the invariant is valid here invariant {I} Karlstad University Dept. of Computer Science Semla 2 page 20

Invariant example • Document invariants as comments class Web. Connection { String *other. User.

Invariant example • Document invariants as comments class Web. Connection { String *other. User. Name; // NULL if no user, else his name } • Complicated invariants are documented separately class Web. Connection { String *other. User. Name; // Invariant: // other. User. Name == NULL if no "other user" is defined // *other. User. Name == "" means "user exists but not known" } Karlstad University Dept. of Computer Science Semla 2 page 21

Invariants often document implementation issues • The exact interpretation of and conventions for other.

Invariants often document implementation issues • The exact interpretation of and conventions for other. User. Name is a private concern – special values should not be known to the environment – the “no user” case should be conveyed to the client through an abstraction • boolean has. User() Karlstad University Dept. of Computer Science Semla 2 page 22

Are the invariants visible from the outside? • • • The external aspects should

Are the invariants visible from the outside? • • • The external aspects should be limited to those that are meaningful to the concept described and not tied to the implementation But sometimes there are invariant conditions that are given by the concept defined and independent of the implementation The size of an array is always >= 0 – So the size in the constructor must be >= 0 to establish the invariant – Does not depend on the implementation The size of a list is always >= 0 – So the size must be >= 1 before a removal not to break the invariant • Since a removal reduces the size by one • which would make a negative size if not >= 1 before The implementation may add more invariants not visible outside – size == 0 <=> _first == NULL Karlstad University Dept. of Computer Science Semla 2 page 23

External and internal invariants • • External invariant client – Type invariant – Abstraction

External and internal invariants • • External invariant client – Type invariant – Abstraction invariant – Relates to the abstraction itself, regardless of implementation – Visible from outside – Documented with the external documentation (API) Internal invariant – Implementation invariant – Tied to the specific implementation – Not visible from outside – Documented in the code only Karlstad University Dept. of Computer Science Linked. List _first add(element) find(element). . . 0. . 1 Linked. Node 0. . 1 External invariant: size() > 0 Semla 2 page 24 Internal invariant: _first == NULL <=> the list is empty _first != NULL => _first points to the first element in the list

An implementation invariant: linked list implementation • • • Linked. List client A linked

An implementation invariant: linked list implementation • • • Linked. List client A linked list head Invariant _first add(element) 0. . 1 – _first == NULL or _first points to the find(element) Linked. Node first element in the list. . . – _first == NULL <=> the list is empty 0. . 1 Implementation – constructor: establish invariant Linked. List() {_first = NULL; } // an empty list – add: assume invariant at entry, restore invariant before exit add(element) { Linked. Node new. Node = new Linked. Node(element); if (_first == NULL) _first = new. Node; else append. At. End(new. Node); } Karlstad University Dept. of Computer Science Semla 2 page 25

Another implementation invariant: array implementation • • • client Data declaration – int *_data;

Another implementation invariant: array implementation • • • client Data declaration – int *_data; – int _size; Invariant: – _data != NULL – more? Constructor Array(int n) – _data = new int[n]; Array int _size Array(int) operator[](int). . . Possible alternative invariant – if _size > 0 then _data != NULL else _data == NULL Consequences for the constructor Array(int n) – if (n == 0) _data = NULL; else _data = new int[n]; Consequences for the indexing operator[](int i) – none, the precondition assures a correct call Karlstad University Dept. of Computer Science Semla 2 page 26 _data 1 int

Relations between invariants and pre- and postcontidions • As a main rule, the invariant

Relations between invariants and pre- and postcontidions • As a main rule, the invariant is always part of all preconditions and all postconditions – follows from the definitions • Part of the invariant is normally implementation oriented and the preand postconditions client oriented – There is one set of pre- and postcondition of interest to the client – There is another set of pre- and postcondition of interest for the implementation – the precondition for the implementation = the precondition exported to the clients + the (external) invariant for the abstraction + the (internal) invariant for the implementation – Similarly for the postcondition Karlstad University Dept. of Computer Science Semla 2 page 27

Implement a queue using an array • • Data declaration Stack client – int

Implement a queue using an array • • Data declaration Stack client – int *_data; _data int _size – int _size; int Array(int) 1 Invariant operator[](int). . . – _data != NULL – _size = number of used elements – the first element is at _data[0] Consequence – Positions 0 through size()-1 hold data Removal: remove() – Precondition: size() > 0 – Implementation {for (int i = 1; i < _size; i++) _data[i-1] = _data[i]; // maintains implementation invariant _size = _size - 1; } Karlstad University Dept. of Computer Science Semla 2 page 28

Are invariants useful? • An invariant should be stated explicitly • Useful for the

Are invariants useful? • An invariant should be stated explicitly • Useful for the design – Forces you to think over what you really want, since you should write it down Useful to maintain consistency over time – Documents your decisions – Helps you not change your mind halfway through Useful to support the implementation – Tells you what you can rely on and what you need to accomplish in addition to the public preconditions and postconditions Useful for error detection – Tests may be activated on the invariants to detect when : -) they are broken • • • Karlstad University Dept. of Computer Science Semla 2 page 29