Download Lecture 5: Specifying Java Programs What is a program specification?

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts
no text concepts found
Transcript
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
What is a program specification?
Lecture 5: Specifying Java Programs
It is a form of “contract” between a software customer and a
software producer:
Aims and Objectives
Pre-conditions
This lecture aims to:
!
Introduce the basic ingredients of a program specification.
!
Show how to map Object-Z specifications into program
specifications
!
Define reasoning rules for
The customer provides
» software requirements
» acceptable conditions
Post-conditions
The software provides
» a program which satisfies the requirements
» “assignment”
» “if-else” statements,
!
Requirements and acceptable conditions of a software can be
derived from more abstract formal specifications (e.g. ObjectZ)
Illustrate the use of a defensive and a non-defensive approach
in programming
Lecture 5: Specifying Java programs
Program
Slide Number 1
Lecture 5: Specifying Java programs
Slide Number 2
A program specification can be seen as a contract between the software customer and the software
producer. A software customer is the person who provides the conditions (if required by the software
developer) under which the software is supposed to run correctly, as well as the requirements. Such
conditions are expressed in a program specification as “pre-conditions”, and they are mainly constraints
on the input parameters that (components of ) a software system is supposed to receive. The
requirements are instead “post-condition”, constraints on the output of the software, i.e. on the results of
(the components of ) the software.
With the previous lecture notes, we have concluded the first topic of this part of the course,
namely object-oriented specifications of system requirements and design. The remaining set of
lecture notes will be focused on a lower level of specification, that of a program specification. and
on reasoning techniques used to verify the correctness of small Java programs.
The main aim of this last part of this course is to introduce basic constructs of an (object-oriented)
program specification, and learn simple reasoning rules for checking the correctness of basic
program statements such as assignment, if-then-else, while loop statements, as well as reasoning
about the correctness of method calls.
The software developer has the task of developing the software and guaranteeing that the requirements
are met. A program specification can therefore be seen as an agreement between these two parties, more
specifically between the customer and the program (developed). The agreement statement is of the form
“Provided that the program is used within the agreed conditions (e.g. on input variables), then the
program performs the required task”. Writing a specification of a program and reasoning with the
specification and the program code, means guaranteeing that such agreement is satisfied.
We will also see how, and to which extend, an Object-Z specification can be mapped “directly”
into a program specification and program skeleton.
We will conclude this lecture illustrating example programs developed using the defensive and the
non-defensive approaches to program design.
We will assume, throughout this last part of the course, that program specifications are written in
classical logic.
We have already seen how to write formal specifications and system requirements, using for instance
Object-Z language. These specifications can “almost automatically” be mapped into program
specifications. We will see in the next few slides examples of such mapping. In doing so we will
gradually introduce basic constructs of a program specification.
Note: My personal thanks to Krysia Broda (examples used in this part of the course are taken from
her lecture notes.)
1
2
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Formalising specifications: convention
Specifying Java Methods (1)
Specification expressions are written:
//pre: none
// post: (result = x ∨ result = y) &
(result<=x & result<=y)
» using basic logical notations;
» within “comments” lines of the (Java) programming language
» using the following prefixes:
» modifies: for ∆-list
» pre: for pre-conditions
» post: for post-conditions
» loop invariant: for loop invariants
» loop variant: for loop variants
» invariant: for class invariants
» using any parameter of the program
Lecture 5: Specifying Java programs
Pre-condition
Post-condition
int IntMin(int x, int y) {
int r;
if (x<=y) r = x; else r = y;
return r;
}
• Pre-conditions are constraints only on the input variables of a method;
• Post-conditions are constraints on the output of a method. They can also refer to
the input variables, and to the class attributes. The variable “result” stands for
the value returned by the method.
• Pre-conditions are checked on entry. Post-conditions are checked on exit.
Slide Number 3
Lecture 5: Specifying Java programs
We will use the following convention to write our program specifications. The examples that we’ll be
using are simple enough to not require very elaborated logical notations. We might, sometime,
complement the logical notation with some English, if necessary.
Slide Number 4
Program specifications aim to check that a program fulfils its purposes. Using just testing, we can
check that given specific values to the input variables of a method, the method behaves correctly.
But we can never be sure that the method will work correctly on all possible input.
The book “Reasoned Programming” gives examples of program specifications with respect to the
functional programming language Miranda and the imperative programming language Modula-2. In
Miranda the comment line is defined by ||, whereas in Modula-2 a comment line starts with a *. We
will adopt instead the notation of Java: so our specifications, if limited to just one line will start with
//, and if longer than a line will be delimited by the comment symbols /*…..*/.
Given a pre-condition and a post-condition to a method definition, we can instead check that for
any possible value of the input variables that satisfies the pre-condition, the code of the method
makes the post-condition true. This is what we mean by checking correctness of a (Java) method.
The main constructs of program specifications that we are going to consider are pre-condition, postconditions, loop invariants, loop variants, and class invariants. Each of these constructs are going to
be identified in our annotated (i.e. specified) program with the key words “pre:”, “post:”, “loop
invariant:”, “loop variant:”, and “invariant”, respectively. The key word “modifies” is instead used to
define the attributes of an object that a given method is supposed to change.
In general, pre-conditions are only conditions on the input variables of a method, which must be
true before a method is executed. Post-conditions are conditions on the output of the method
and/or on the attributes’ values of the object, which must be true after the operation has been
performed, and given that the pre-conditions are also true.
Above is an example of pre- and post-conditions for a simple method, called IntMin, which
returns the minimum of two integer numbers given as input variables.
Note that, post-conditions can also refer to the input, but pre-conditions can refer to only the input.
All but the loop invariant and loop variants are program specification’s constructs that can be derived
from a given Object-Z specification.
Parameters used in the program code can also be used in the program specifications
3
4
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Specifying Java Methods (2)
Specifying Class Invariants
public class TwoNumbers{
int u, v;
//invariant: u ≥ 2 ∧ v ≥ 3;
public class TwoNumbers{
int u, v;
// modifies u, v;
//pre: none
//post: u = v0 ∧ v = u0;
void Swap( ) {
int temp;
temp = u; u = v; v = temp;
}
• Invariants:
» are declared immediately after the attributes declarations in a class;
» express constraints on the values of the attributes of a class;
» behave like post-conditions of the constructor and of each methods in the class.
}
• Post-conditions can also express constraints on the new values of the attributes
of an object. The attribute_name (i.e. u) denotes the value of the attribute after the
execution of the method, attribute_name0 (i.e. u0) denotes the value of the attribute
at the start of the method execution.
e.g.
• The modifies statement declares instead that the method is supposed to change
the values of the attributes u and v.
Lecture 5: Specifying Java programs
Class Invariant
void incrementU(int incr) {
u = u + incr;}
public class TwoNumbers{
int u, v;
//post: u ≥ 2 ∧ v ≥ 3;
void incrementU(int incr) {
u = u + incr;}
}
Lecture 5: Specifying Java programs
Slide Number 5
What is wrong here?
Slide Number 6
Program specifications aim to check that a program fulfils its purposes. Using just testing, we can
check that given specific values to the input variables of a method, the method behaves correctly. But
we can never be sure that the method will work correctly on all possible input.
This is an example of post-condition of a method that expresses constraints on the values of the
attributes of the class, after the method is executed. The notational convention that we adopt here is
to use in the post-condition just the name of the attribute to refer to the new value of that attribute
after the execution of the method, and the name of the attribute with the subscript 0 to refer to the
value of the attribute at the start of the method execution.
Given a pre-condition and a post-condition to a method definition, we can instead check that for any
possible value of the input variables that satisfies the pre-condition, the code of the method makes
the post-condition true. This is what we mean by checking correctness of a (Java) method.
Whenever a method is supposed to change the value of a class attribute, we include before the preconditions the construct “modifies” and the list of the attributes that can be changed by the method.
Above is an example of pre- and post-conditions for a simple method, called IntMin, which returns
the minimum of two integer numbers given as input variables.
In general, pre-conditions are only conditions on the input variables of a method. Post-conditions are
conditions on the output of the method, and/or on the attributes’ values of the object, after the
operation has been performed. Note that, post-conditions can also refer to the input, but preconditions can only refer to the input.
5
6
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Example: Mapping the CreditCard schema
Mapping Object-Z into Java Specifications
CreditCard
General rules for the mapping:
Object-Z
public class CreditCard{
private final init limit = 1000;
private int balance;
//invariant: limit ≥ 0;
//invariant: balance + limit ≥ 0
" (Init, withdraw, deposit, withdrawAvail)
limit: N
Java Specification
limit ∈ {1000, 2000, 5000}
class schema “ClassName”
public class “ClassName”
balance: Z
Constants
final attributes of the class
balance + limit ≥ 0
Attributes
Attributes of the class
Axioms of the state schema
Invariants
withdraw
∆(balance)
amount?:N
N
Initial schema
Constructor of the class
Operation schema
» ∆-list;
» pre-conditions;
» axioms;
Method declaration with
» modifies list;
» pre-conditions;
» post-conditions;
Visibility List
“public” / “static” prefixes.
Lecture 5: Specifying Java programs
Init
balance = 0
public CreditCard( )
{ balance = 0; }
//modifies: balance;
//pre: amount ≤ balance0 + limit;
//post: balance = balance0 – amount;
public void withdraw(int amount)
{……}
amount?<=balance + limit
balance' = balance – amount?
withdrawAvail
∆(balance)
amount!:N
N
//modifies: balance;
//pre: none;
//post: balance = – limit ∧
result = balance0 + limit;
public int withdrawAvail( )
{……}
amount! = balance + limit
balance’ = – limit
Slide Number 7
Lecture 5: Specifying Java programs
}
Slide Number 8
In this slide we give an example of how we could map part of the class schema CreditCard we saw in
Lecture 3 into a Java program and its specification. Few things are interesting to notice.
In this slide we give basic rules for mapping Object-Z specifications into Java program and program
specifications. Refinement of formal specifications into programs and program specifications can be
done in various different ways, depending on the relation between the classes specified in Object-Z and
the Java classes declared in the program. The assumption that we are using here is that the Object-Z
specification provides already the architecture definition of our Java program. This means that each
class schema defined in Object-Z is expected to be implemented by a Java class in our Java program.
This explain the first row of the mapping given in this table.
First of all, the constant “limit” is defined in Object-Z to be a natural number. In Java we don’t have
natural numbers as basic types, so the declaration of the final attribute limit in Java is a refinement of
that given in Object-Z. It is defined as an integer with the addition of an extra invariant that has not
been specified in the Object-Z class schema.
Second, the constant definition in Object-Z declares limit to be of type enumeration by specifying the
possible values that it could assume. In the actual implementation, the engineer will need to make a
decision and define a value for the final attribute limit. Again, this is another example of simple
refinement of the given formal specification.
Attributes defined in a class schema (constants and variables) are mapped into attributes of our Java
class, preserving the same distinction of constants and variables. So all the constants of a class schema
are Java class’s attributes declared as “final”, and all the variables of a state schema are not final
attributes of the Java class. Note that initialisation values given in the axiom part of a constant
definition in Object-Z can be used to initialise the final attributes. This explains the second and third
rows of the mapping given in this table.
Third, the pre-condition of the method “withdraw” is necessary for the class invariant to be satisfied.
In the Object-Z class schema definition, such pre-condition would be redundant. In the actual
implementation, if this method is not declared to throw exceptions, the pre-condition is essential.
We’ll see later how the choice of a defensive vs a non-defensive approach to the implementation
leads to different codes and program specifications.
The axioms of a state schema are mapped into invariants of our Java class.
The Initial schema in Object-Z corresponds to the Java constructor of the Java class.
Operation schemas are mapped into Java method specifications, in the following way. The ∆-list
declared in the operation schema is mapped into a “modifies” construct, the pre-condition axioms are
mapped into pre-conditions, and the remaining axioms of an operation schema are mapped into postconditions of the method. For simplicity we assume that each operation schema in Object-Z can have
only one output variable.
Finally, if the class schema includes a visibility list, then for each feature (attribute and operation)
included in the visibility list, the corresponding Java feature will be declared to be public and the
remaining features declared to be private.
NOTE: For simplicity we restrict ourselves to class schemas whose attributes are of basic types
(natural; numbers, real numbers, seqchar).
7
8
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Reasoning about Programs: notations
Mid-conditions
• Program code includes variable assignments, thus variables change in their
values.
Mid-conditions are specifications (or expressions) that can be included at any
arbitrary point within a program code.
They are supposed to hold whenever the program control passes throughout
the point where they are stated.
• When reasoning about correctness of method codes, we have to be able to refer
to current, previous and intermediate values of variables.
Convention:
» At each point of a method code, “variable_name” denotes the value of the
Example:
variable at that current point of execution of the code (i.e. now);
» A “variable_name0” denotes the value of the variable at the start of a method to
distinguish it from the current value;
» A “variable_namei” ( “i” is a positive number) denotes an intermediate value of
the variable assumed after the start of a method execution up to and excluded the
current point.
Example
MethodA( ){
x =1;
x=x+1;}
Lecture 5: Specifying Java programs
// pre: none
int z;
// y = y0 ∧ x = x0
z = x;
// y = y0 ∧ z = x0
x = y;
// x = y0 ∧ z = x0
y = z;
// y = x0 ∧ x = y0
// post: x = y0 ∧ y = x0
// x0 = value of attribute x at the start
// x = 1; x0 = value of attribute x at the start
// x1 = 1; x = x1+ 1 = 2; x0 = value of x at the start
Slide Number 9
Lecture 5: Specifying Java programs
Pre-conditions = mid-conditions
at the start
Post-conditions = mid-conditions
just before exit
Mid-conditions = used to help
justify code
Slide Number 10
Mid-conditions can be used to reason about programs, for instance to show that the post-conditions of a
methods are met given the code and that the pre-conditions are true. We can reason with mid-conditions
in two different ways: “forward” starting from the initial mid-condition (i.e. the pre-condition) and
following the statements to derive a new mid-condition and so on, until we reach the end of the code.
The last mid-condition so generated is supposed to be equal to post-condition for the post-condition to
be satisfied. Another way for generating mid-conditions is reasoning “backwards” from the last-midcondition (i.e. post-condition). Starting from the end, we can look at the operation in the code and
substitute in the last mid-condition the variables accordingly to simulate backwards what the code is
supposed to do. We discuss here how we can generate the mid-conditions given in the example here by
reasoning forward and by reasoning backwards.
An important feature of imperative or OO programming languages is the operation of assignment.
Variables can change their values within the body of a method. To reason about the correctness of a
method, namely to check whether a post-condition is satisfied at the end of a method, it’s important
to keep truck of the different values that a variable can assume during the execution of the method.
To keep truck of these different values of each variable, we use the following conventions.
Variables at the beginning of a method are denoted by their name with the subscript 0, variables at a
currents point of execution of a method, are denoted with just their name. When we perform
reasoning about a part of a code, each intermediate value assumed by the variable within this code is
denoted with the variable name subscribed with an (incremental) indexing number.
This convention relates to the convention for writing post-conditions that we have defined in slide 5.
If the current point of execution is at the end of the method code, the current value of a variable is the
value at the exit of the method. Hence, the post-condition uses just the variable name to indicate the
variable’s value at the current point that is at the exit of the method.
Reasoning forward: At the start of this piece of code, the variables x and y are equal to some initial
values x0 and y0 respectively. This is our first mid-condition (or pre-condition of our piece of code). To
second mid-condition is generated looking at the code. At the point after the assignment z = x; the
variable z includes the value of x just before the assignment. i.e. z = x0. The variable y is instead left
unchanged. This gives our second mid-condition. We can used a similar reasoning to show how we get
the third mid-condition and then the four mid-condition. Since there is no more code, we want this last
mid-condition to be equal to the post-condition. This is the case, so we can say that our piece of code
satisfies the given post-condition.
We have given here an example of the use of this notation, by commenting each line of the code of
MethodA.
These comments are called “mid-condition”, and define the current value of variables at a certain
point of execution, possibly referring to previous or initial values of the variables. We define in the
next slide what a mid-condition is and why it’s useful.
Backward reasoning: We start from the post-condition. This is also our last mid-condition. We then
look at the last operation and we generate the previous mid-condition by substituting in the last midcondition the variable y with z. And so on, until we reach the first mid-condition. This is what we
initially had as pre-condition, so the piece of code satisfies the post-condition. The backward reasoning
helps us identify those pieces of information about the initial conditions that are necessary for the code
to establish the post-condition. Such (minimal) set of information about the initial conditions are called
“weakest pre-conditions”.
9
10
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Reasoning rules for assignments
Examples
program
mid-cond-before {x = expr} mid-cond-after
………
x = x-3;
………
Meaning:
If the mid-cond-before holds and the assignment x=expr is executed then the
mid-cond-after holds.
mid-condition before
// x > 10;
// x > 5;
x > 8 {x=x-3;} x > 5, which is true;
iii.x > 10 implies x > 8? This is obviously true
mid-condition after
To show it:
program
Replace in mid-cond-after all occurrences of x with expr,
This gives a new mid-condition, called mid-cond-before', so that
mid-cond-before' {x = expr} mid-cond-after is true.
iii. Show that mid-cond-before implies mid-cond-before'
………
x = x-1;
………
// 0 < x < N+1
// 0 ≤ x < N;
mid-condition after
Slide Number 11
Lecture 5: Specifying Java programs
In this slide, we give the general rules for reasoning about assignments. The statement “mid-condbefore{x=expr}mid-cond-after” is called a judgment. This reasoning can be used in two ways: if both
mid-conditions are given, it just shows that assuming the mid-cond-before to be correct, the
assignment operation satisfies the mid-cond-after. If only the mid-cond-after is given together with the
assignment, then it helps identify the minimal mid-cond-before that is needed in order to verify the
correctness of the operation. Note that it is easier in general to work from mid-cond-after to mid-condbefore.
(The weakest pre-condition is x > 8)
mid-condition before
i.
ii.
Lecture 5: Specifying Java programs
i. Substitute x-3 for x in the mid-cond-after;
ii. mid-cond-before' = x-3>5; or x > 8; so we have
i. Substitute x-1 for x in the mid-cond-after:
ii. mid-cond-before' = 0 ≤ x-1 < N, which gives
1 ≤ x < N+1, which is true;
iii.0 < x < N+1 implies 1 ≤ x < N+1.
(The weakest pre-condition is 1 ≤ x < N+1)
Slide Number 12
This slide shows two examples of reasoning with mid-condition before and mid-condition after in the
case of just assignment operations. Both examples have the two mid-conditions specified. The
reasoning on the right-hand-side show that given that the mid-condition before is satisfied then the
mid-condition after is also satisfied after the operation of assignment is performed.
In both cases, the backward reasoning generates a weakest pre-condition which may or may not be
equal to the given first mid-condition. To show that the code is correct, we need to show that the initial
mid-condition does entails the weakest pre-condition.
Reasoning about sequences of statements is based on reasoning about the individual statements in the
way illustrated above. For instance, suppose that we want to reason about the following judgement:
mid-cond-before{statement1; statement2}mid-cond-after
This can be split into the following two judgements:
mid-cond-before{statement1}mid-con-between
mid-cond-between{statement2}mid-cond-after
Both the above judgements are satisfied if and only if the first judgement is satisfied.
This is essentially the mechanism we are going to use to prove that the post-condition of a method is
satisfied whenever the pre-conditions are satisfied. The body of the method is essentially a sequence of
statements, the pre-condition is the first mid-condition before and the post-condition is the last midcondition after with respect to the body of the method. The reasoning should then check the
satisfiability of all the intermediate mid-conditions for all the statements included in the body of the
method.
11
12
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Conditionals
Reasoning rules for conditionals
//pre: none;
//post: (result = x0 ∨ result = y0) ∧ (result ≤ x0 ∧ result ≤ y0)
int intmin(int x, int y) { // x = x0 ∧ y = y0
if (x <= y)
// x0 <= y0;
return x;
// result = x0 & result <= y0;
else
// x0 > y0;
return y;
// result = y0 & result < x0;
}
mid-cond-before {IF test {s1}ELSE {s2}} mid-cond-after
Meaning:
If the mid-cond-before holds and the test is true and {s1} is executed then the
mid-cond-after holds, and if mid-cond-before holds and the test is false and
{s2} is executed then the mid-cond-after also holds.
To show it:
i. Show mid-cond-before & test {s1} mid-cond-after
ii.And show mid-cond-before & ¬test {s2} mid-cond-after
There are two branches of execution, the THEN (when the condition is true)
and the ELSE branch, when the condition is false.
We need to show that the post-condition holds independently from
the branch that is executed.
Lecture 5: Specifying Java programs
Slide Number 13
Lecture 5: Specifying Java programs
We want to show that after each return the post-condition is true. The if-else statement always
requires a case analysis. Take the first branch (or first case). To get on this branch the program must
have passed the if-test. So assuming x0 to be the initial value of x, and y0 to be the initial value of y,
we know that at this point of the execution, x0 <= y0. We can then annotate it as mid-condition of the
program at this particular point of the execution. The program then return x. Therefore result = x0 is
true and so it’s the expression result = x0 ∨ result = y0. Since x0 <= y0, we also know that result <= y0
(this is the next mid-condition). Moreover we also have result <= x0, and thus the second part of the
mid-condition is true. So also the second part of the post-condition is true. The other branch (or
second case) is similar. On entering it we know that x0 > y0. Since the method returns y, we have that
result=y0 is true and so it’s the expression result = x0 ∨ result = y0. Moreover, we also have result <
x0 and thus the second part of the mid-condition is true. This shows at each return point that the postcondition is true.
Slide Number 14
In this slide, we give the general rules for reasoning about if-else statements, or conditionals. A
conditional judgement is equivalent to two judgements of the form:
mid-cond-before & test {S1} mid-cond-after,
mid-cond-before & ¬test {S2} mid-cond-after.
Check that the conditional judgement is satisfied means therefore to check that both the above two
judgements are satisfied. This means showing that whatever execution branch is taken by the
program under the mid-cond-before, it is always possible to establish the truth of the mid-condafter.
To verify each of the above two judgments independently, we make use of the same (backward)
reasoning shown for the assignment statement. Starting from the mid-cond-after, making
appropriate substitutions and getting a new mid-cond-before', which should be implied by the given
mid-cond-before together with the truth or falsity of the if-condition, according to which of the two
judgments we are analysing.
A similar reasoning can be done backwards starting from the post-condition. We want to show
(result=x0 ∨ result=y0) and (result <=x0 ∧ result<=y0). On the if branch, we have as last operation
return x. So we can substitute result for x and get (x=x0 ∨ x=y0) and (x ≤x0 ∧ x≤y0). The first part
(x=x0 ∨ x=y0) is true and the second part is true because the mid-condition before the test would in
this case be x=x0 ∧ y=y0, we have that x<=y0 is true. Analogously for the other branch.
NOTE: in the second type of reasoning the new mid-conditions-before' generated from the postcondition are equivalent to the mid-conditions given in the program.
In the next slide we give the general rules for reasoning about if-else statements.
13
14
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Example
Non-defensive vs Defensive
Approach to Programming
//pre: none;
//post: (result = x0 ∨ result = y0) and (result ≤ x0 ∧ result ≤ y0)
// x = x0 ∧ y = y0;
int intmin( ) {
// x0 <= y0;
IF (x ≤ y)
return x;
// result = x0 ∧ result ≤ y0;
// x0 > y0;
ELSE
// result = y0 ∧ result < x0;
return y;
}
Non-defensive approach:
Pre-conditions are used to specify the “good” values for the
input parameters of a method, for which the method should behave
correctly.
Reasoning:
Defensive approach:
i. Substituting “result” with “x” in the post-condition we get the mid-cond-before':
(x = x0 ∨ x = y0) ∧ (x ≤ x0 ∧ x ≤ y0), which is true, given the (test) and the
initial mid-condition x = x0 and y = y0.
ii.Substituting “result” with “y” in the post-condition we get the mid-condbefore': (y = x0 ∨ y = y0) ∧ (y ≤ x0 ∧ y ≤ y0), which is also true, given (¬test)
and the initial mid-condition x = x0 and y = y0.
Lecture 5: Specifying Java programs
The program does not have any pre-condition on the values of its
input parameters, but its code has to define all the appropriate
output for all possible input values.
Slide Number 15
Lecture 5: Specifying Java programs
Slide Number 16
The choice of a defensive or non-defensive approach to the design of a system affects its
implementation. In the Object-Z specifications we have introduced the concept of pre-condition, as an
axiom to include in an operation schema in order to guarantee correct execution of the operation. This
is what we call non-defensive approach. We haven’t seen, on the other hand, the concept of defensive
approach for the definition of operation schema in a given class schema. This is because in objectoriented specifications, when an error occurs, there is no sense to talk about the new state of a given
object, since the error would make the operation inapplicable.
From the point of view of the implementation, when we refine an Object-Z operation schema included
in a class schema into a method we could still take into consideration whether we are implementing
that method using a defensive or a non-defensive approach. In the first case we would need to add to
the method the necessary pre-conditions that make the operation work correctly. In the second case,
we should declare that the method could throw some exceptions, and its code would have to check for
these exceptions.
This is another example of how the implementation of a given formal specification can be further
refined at the implementation level.
An example is given in the next slide.
15
16
Course: Y302 - Software Engineering
Course: Y302 - Software Engineering
Summary
Non-defensive vs Defensive: example
• Object-Z specifications can be mapped (or refined) into Java programs and
program specifications.
//pre: x ≥ 0;
//post: result^2 = x;
int sqrt(int x) {
return sqroot(x); (suppose this is a mathematical function for
calculating the square root of an integer).
}
• In a post-condition, “result” means the value returned by the method.
• Variables change their values: so specification expressions carry always a
notion of “now”. A undecorated variable always denotes its value “now”.
• For pre- and post-conditions, “now” is, respectively, entry to and return from a
method; for a mid-condition, “now” is just after the related statement has been
executed.
//pre: none
//post: (x<0 ∧ throw exception) or (x ≥ 0 & result = sqrt(x)).
int sqrt(int x) throw exception{
if (x<0)
throw exception
else return sqroot(x); (suppose this is a mathematical function for
calculating the square root of an integer).
}
Lecture 5: Specifying Java programs
• A subscript “0” on a variable denotes its value originally, i.e. on entry to the
method it refers to. Other subscripts like “1” on variables indicate their values at
some intermediate points.
• Variables not mentioned in the specifications are assumed not to change.
• In an IF statement, the test gives pre-conditions for the IF and the ELSE parts.
Slide Number 17
Lecture 5: Specifying Java programs
17
Slide Number 18
18