Upload
dawson-regis
View
216
Download
1
Tags:
Embed Size (px)
Citation preview
Design By ContractDesign By Contract
Using JMSAssert
Design By ContractDesign By Contract A method of separating the concerns of the
user and implementer of the class, and giving both enough information for their tasks.
Work in this course will be done with Java, offers partial support for those concepts.
Each class and method should be documented in Javadoc style.
Design By ContractDesign By Contract In order to implement the principles of Design-by-
Contract in Java, we will use a free tool from Man Machine Systems names JMSAssert.
It works with Sun’s JDK 1.2 & 1.3 but not 1.4
Design By ContractDesign By Contract A powerful technique for writing reliable
software. Specifying the software purpose with the
implementation. Key elements:
Invariant Preconditions Postconditions
Design By ContractDesign By Contract Precondition – The constraints under
which the routine will function properly. Postconditions – The state of the class after
the routine execution The Contract: If you call routine R() with
the preconditions satisfied, R() will return satisfying the postconditions.
Invariant – Always holds
When are condition checked?When are condition checked?
Event InvariantPre-
conditionPost-
conditionInstance Method Y Y -Constructor N Y -Private Method N Y -Static Method N Y -Instance Method Y - YConstructor Y - YPrivate Method N - YStatic Method N - Y
Method Entry
Method Exit
JMS Syntax - InvariantJMS Syntax - Invariant Invariant - @inv May access all class members or its
direct/indirect bases, including private members
May appear in any JavaDoc comment Preferable in the class comment
JMS Syntax - PreconditionsJMS Syntax - Preconditions Precondition - @pre JavaDoc preceding the respective method May reference class members and
arguments Multiple @pre markers are conjugated
(AND)
JMS Syntax - PostconditionsJMS Syntax - Postconditions Postconditions - @post JavaDoc preceding the respective method May use $prev(expression) to access the
value at the method entry. May use $ret to denote method’s return
value Multiple @post markers are conjugated
(AND)
ExampleExample
/** * @pre !isEmpty() * @post (top == $prev(top- 1)) * @post $ret == elems[top] * @post !isFull*/public synchronized Object pop() {
return elems[--top];}
Precondition
Postconditions
ExampleExample
/** * @pre !isEmpty() * @post (top == $prev(top- 1)) * @post $ret == elems[top] * @post !isFull*/public synchronized Object pop() {
return elems[--top];}
Precondition
Postconditions
What is wrong in the example ?
JMS Syntax - GeneralJMS Syntax - General Order has no meaning @macro – for complicated conditions Recursion – as expected, on every call Inner classes can access outer classes’
members Anonymous classes – specify invariant in
one of its methods
Downloads & InstallationsDownloads & Installations Download Java J2SE SDK 1.3.1 from
http://java.sun.com/downloads (~41MB)Install into C:\Program Files\jdk1.3.1_07
Download JMSAssert 1.02 from http://www.mmsindia.com (~1.2MB)Run the jmssetup-1.02.exe installation fileInstall into C:\Program Files\AMSAssert1.0
JMSAssert InstallationJMSAssert Installation The following lines are added to the path:REM Next two lines are added by JMSAssert
SET CLASSPATH=%CLASSPATH%;C:\PROGRA~1\JMSASS~1.0\
bin\mmsclasses.jar;
SET PATH=%PATH%;C:\PROGRA~1\JMSASS~1.0\bin;
Copy the “classic” directory from “C:\Program Files\jdk1.3.1_07\jre\bin\” to the directory:“C:\Program Files\JavaSoft\JRE\1.3.1_07\bin\”
Setup Setup (cont.)(cont.)
Your JavaSoft directory should look like:
JMSAssert – how does it workJMSAssert – how does it work Annotate source code with assertions Compile your code using javac (as usual) Preprocess the code using jmsassert: creates
contract files (*.jms) and a Startup.jms file. *.jms files contain java code for the assertions. Execute using: jmsjava Startup <filename>to check assertions.
jmsjava makes sure method assertions are called before/after the method invocation.
JMS ExecutionJMS Execution “jmsassert” – generates help text “jmsassert –s <filename.java>” – generate
assertions for a class file “jmsassert –r –s .” – generate assertions for
all class files in the directory and sub-dirs. (use for packages)
“javac <filename.java>” – compile “jmsjava Startup <main>” - execute and check
assertions
Annotate source with assertions
MyStack.java
Stack Demo Stack Demo filesfiles
Execution Execution processprocess
Annotate source with assertions
Preprocess to generate assertion
filesjmsassert –s <file.java>
MyStack.java
Startup.jms
default_MyStack.jmsdefault_MyStack_StackEnum.jms
Stack Demo Stack Demo filesfiles
Execution Execution processprocess
Annotate source with assertions
Preprocess to generate assertion
filesjmsassert –s <file.java>
Compile Java file
javac <file.java<
MyStack.java
Startup.jms
default_MyStack.jmsdefault_MyStack_StackEnum.jms
MyStack.classMyStack$StackEnum.classMyStack$StackEnum.classStackTest.class
Stack Demo Stack Demo filesfiles
Execution Execution processprocess
Annotate source with assertions
Preprocess to generate assertion
filesjmsassert –s <file.java>
Compile Java file
javac <file.java<
Execute using jmsjava
MyStack.java
Startup.jms
default_MyStack.jmsdefault_MyStack_StackEnum.jms
MyStack.classMyStack$StackEnum.classMyStack$StackEnum.classjmsjava Startup <classname> StackTest.class
Stack Demo Stack Demo filesfiles
Execution Execution processprocess
NotesNotes Execute these steps form the command line! Make sure your CLASSPATH environment
variable contains the current directory.Add “CLASSPATH=%CLASSPATH%;.” to autoexec.bat.
An Example (MyStack)An Example (MyStack) A stack with invariants, pre conditions and post
conditions: MyStack.java A main file: StackTest.java Compile all .java files (using javac) Generate JMSAssert triggers by:jmsassert –s MyStack.java
Run and test assertions byjmsjava Startup StackTest
You can always run your test program in byjava StackTest
MyStack.java (#1)MyStack.java (#1)/**
@inv (top >= 0 && top < max)
*/
class MyStack {
private Object[] elems;
private int top, max;
MyStack.java (#2)MyStack.java (#2).
/**
@pre (sz > 0)
@post (max == sz && elems != null)
*/
public MyStack(int sz) {
max = sz;
elems = new Object[sz];
}
MyStack.java (#3)MyStack.java (#3)
/**
@pre !isFull()
@post (top == $prev (top) + 1) && elems[top-1] == obj
*/
public void push(Object obj) {
elems[top++] = obj;
}
MyStack.java (#4)MyStack.java (#4)
/**
@pre !isEmpty()
@post (top == $prev (top) - 1) && $ret == elems[top]
*/
public Object pop() {
return elems[--top];
}
MyStack.java (#5)MyStack.java (#5)
/**
@post ($ret == (top == max))
*/
public boolean isFull()
{
return top == max;
}
MyStack.java (#6)MyStack.java (#6)
/**
@post ($ret == (top == 0))
*/
public boolean isEmpty()
{
return top == 0;
}
} // End MyStack
StackTest.javaStackTest.java
class StackTest {
public static void main(String[] args) {
MyStack s = new MyStack(2); // Can push at most 2 elements
s.push(new Integer(1));
s.push(new Integer(23));
s.push(new Integer(0)); // Precondition violation here!
}
}