VDM-SL Case Study Learning Outcomes At the end of this lecture you should be able to: Analyse and...

Post on 01-Jan-2016

214 views 0 download

Transcript of VDM-SL Case Study Learning Outcomes At the end of this lecture you should be able to: Analyse and...

VDM-SL Case Study

Learning Outcomes

At the end of this lecture you should be able to:

• Analyse and informally specify a complete system using UML class diagrams;

• Develop a formal VDM specification from an informal UML specification.

• Rigorously interrogate a formal specification

The Requirements Definition

The software is expected to be able to do the following:

• create a new account;

• remove an existing account;

• record a deposit transaction;

• record a withdrawal transaction;

• update the personal details (name, address and so on) of a customer's account;

• change the overdraft limit associated with an account;

• produce a statement of transactions associated with an account;

• display the balance of an account;

• display the personal details of an account.

The UML specification

AccountSys

accounts : Account [*]

addAccount (AccNum, Details, Real)removeAccount (AccNum)deposit(AccNum, Date, Real)withdraw(AccNum, Date, Real)changeDetails(AccNum, Details)changeLimit(AccNum, Real)getAllTransactions(AccNum) : Transaction [*]getBalance(AccNum): RealgetAccount(AccNum) : AccountgetDetails(AccNum) : Details getLimit(AccNum): RealgetAllAccounts() : Account [*] contains(AccNum) : BooleanisEmpty() : BooleangetTotal() : Integer

Additional types: The Account type

Account

number: AccNumdetails : Detailsbalance: Reallimit : Realtransactions: Transaction [*]

Additional types: The Transaction type

Transaction

date: Datetype: TransactionTypeamount: Real

Additional types: The TransactionType type

<<enumeration>>TransactionType

withdrawaldeposit

Formally specifying the types in VDM-SL:

types

AccNum = TOKEN

Date = TOKEN

Details = TOKEN

TransactonType = < withdrawal >|< deposit >

Formally specifying the types in VDM-SL:

Transaction :: date : Date

amount : transactionType : TransactionType

inv mk-Transaction(-,a,-) a > 0

Formally specifying the types in VDM-SL:

Account :: number : AccNumdetails : Detailsbalance : limit : transactions : Transaction*

inv mk-Account(-,-,b,l,t) l ≥ 0

b ≥ -l

balanceOf(t) = b

limit is non-negative

balance within limit

balance matches transactions

Formally specifying the state in VDM-SL

state AccountSys of

accounts : m

inv mk-AccountSys(a) account numbers in domain also in range

AccountAccNum

init mk-AccountSys(a) a = { }

end

num dom a num = a(num).number

Auxiliary functions: balanceOf

balanceOf( transIn : Transactions* ) total :

pre true

post let dep = [ transIn(i).amount | i inds transIn

transIn(i).transactionType = <deposit> ]

in let withd = [ transIn(i).amount | i inds transIn

transIn(i).transactionType = <withdrawal> ]

in total = sum(dep) - sum(withd)

??

?

??

?

?

? ?

true

Auxiliary functions: sum

sum : *

sum(seqIn) if seqIn = [ ]

then 0

else hd seqIn + sum(tl seqIn)

Operation specifications: addAccount

addAccount( )

ext

pre

post

numberIn : AccNum, detailsIn : Details, limitIn :

m AccountAccNumwr

{numberIn mk-Account(numberIn, detailsIn, 0, limitIn, []}

accounts = accounts

numberIn dom accounts limitIn 0

accounts:

Operation specifications: removeAccount

removeAccount( )

ext

pre

post

numberIn : AccNum

m AccountAccNumwr

accounts = {numberIn } accounts

numberIn dom accounts

accounts:

Operation specifications: deposit

deposit( )

ext

pre

post

numberIn : AccNum, dateIn : Date, amountIn :

m AccountAccNumwr

let bal = ( (numberIn)).balance accounts

in let trans = ( (numberIn)).transactions accountsin let newTrans = mk-Transaction(dateIn, amountIn,< deposit>)

in accounts = † {numberIn accounts

accounts( (numberIn),

balance bal + amountIn, transactions trans ^ [newTrans])}

numberIn dom accounts amountIn > 0

accounts:

Operation specifications: withdraw

withdraw( )

ext

pre

post

numberIn : AccNum, dateIn : Date, amountIn :

m AccountAccNumwr

let bal = ( (numberIn)).balance accounts

in let trans = ( (numberIn)).transactions accountsin let newTrans = mk-Transaction(dateIn, amountIn,< withdrawal>)

in accounts = † {numberIn accounts

accounts( (numberIn),

balance bal - amountIn, transactions trans ^ [newTrans])}

numberIn dom accounts amountIn > 0

(accounts(numberIn)).balance - amountIn ≥ - (accounts(numberIn)).limit

accounts:

Operation specifications: changeDetails

changeDetails( )

ext

pre

post

numberIn : AccNum, detailsIn : Details

m AccountAccNumwr

accounts = † {numberIn

( (numberIn), details detailsIn)}

accounts

accounts

numberIn dom accounts

accounts:

Operation specifications: changeLimit

changeLimit( )

ext

pre

post

numberIn : AccNum, limitIn :

m AccountAccNumwr

accounts = † {numberIn

( (numberIn), limit limitIn)}

accounts

accounts

numberIn dom accounts limitIn 0

accounts(numberIn).balance - limitIn

accounts:

Operation specifications: getDetails

getDetails( )

ext

pre

post

numberIn : AccNum detailsOut : Details

m AccountAccNumrd

detailsOut = (accounts(numberIn)).details

numberIn dom accounts

accounts:

Operation specifications: getBalance

getBalance( )

ext

pre

post

numberIn : AccNum balanceOut :

m AccountAccNumrd

balanceOut = (accounts(numberIn)).balance

numberIn dom accounts

accounts:

Operation specifications: getLimit

getLimit( )

ext

pre

post

numberIn : AccNum limitOut :

m AccountAccNumrd

limitOut = (accounts(numberIn)).limit

numberIn dom accounts

accounts:

Operation specifications: getAllTransactions

getAllTransactions( )

ext

pre

post

numberIn : AccNum transactionsOut : Transaction*

m AccountAccNumrd

transactionsOut = (accounts(numberIn)).transactions

numberIn dom accounts

accounts:

Operation specifications: contains

contains( )

ext

pre

post

numberIn : AccNum query :

m AccountAccNumrd

query numberIn dom accounts

TRUE

accounts:

Operation specifications: isEmpty

isEmpty( )

ext

pre

post

query : m AccountAccNumrd

query accounts = { }

TRUE

accounts:

Operation specifications: getTotal

getTotal( )

ext

pre

post

totalOut :

m AccountAccNumrd

totalOut = card dom accounts

TRUE

accounts:

Rigorously checking specifications

One of the advantages of formal specifications is that they can ‘tested’ before an implementation is developed.

Informal Specification

Formal Specification

CODE CODETest

Test

“If I create a new account with an overdraft limit of £200, I will not be allowed to withdraw £300 until after more money has been deposited.”

Example

addAccount (AccNum, Details, Real)removeAccount (AccNum)deposit(AccNum, Date, Real)withdraw(AccNum, Date, Real)changeDetails(AccNum, Details)changeLimit(AccNum, Real)getAllTransactions(AccNum) : Transaction [*]getBalance(AccNum): RealgetAccount(AccNum) : AccountgetDetails(AccNum) : Details getLimit(AccNum): RealgetAllAccounts() : Account [*] contains(AccNum) : BooleanisEmpty() : BooleangetTotal() : Integer

“If I create a new account with an overdraft limit of £200, I will not be allowed to withdraw £300 until after more money has been deposited.”

Example

addAccount ( AccNum, Details , Real ) ;

withdraw( AccNum , Date , Real );

001 200

001 300

addAccount( )

ext

pre

post

numberIn : AccNum, detailsIn : Details, limitIn :

m AccountAccNumwr

{ numberIn mk-Account( numberIn , detailsIn , 0, limitIn , []}

accounts = accounts

numberIn dom accounts limitIn 0

accounts:

withdraw( )

ext

pre

numberIn : AccNum, dateIn : Date, amountIn :

m AccountAccNumwr

numberIn dom accounts amountIn > 0

(accounts(numberIn)).balance - amountIn ≥ - (accounts(numberIn)).limit

accounts:

001

001 001 200

001

001 001

300

300

200