Abstraheren van modellen
Geert Delanote 7 maart 2005
[email protected]
Software Development Methodology
1
Inhoudstafel _ _
Motivatie Denkpistes
Software Development Methodology
2
Motivatie _
Verslag vorige vergadering _
_
Discussiepunt “Belang van verbanden tussen verschillende modellen op eenzelfde (hoog) abstractieniveau; problemen met uitdrukking hiervan (UML volstaat niet).”
Vertrekpunt _
Observatie dat PIM-modellen te complex worden - UML is niet expressief genoeg
_
_
Transformatie naar PSM-modellen (semi-)automatisch?
Onderzoek _
Niet afgerond!
Software Development Methodology
3
Motivatie _
Denkpistes : _ _
Reïficatie van methodes Verbanden tussen methodes - Reïficatie van toestanden
_
_
Complexe hiërarchieën
Financial case study
Software Development Methodology
4
Inhoudstafel _ _
Motivatie Denkpistes _ _
Reïficatie van methodes Verbanden tussen methodes - Reïficatie van toestanden
_
Complexe hiërarchieën
Software Development Methodology
5
Case 1 : Reïficatie van methodes _
Gegeven : _ _
een klasse van boeken met een event om boeken uit te lenen Book +loan(period:DURATION):void
_
met een query om het aantal uitleningen op te vragen Book 1 +loan(period:DURATION):void +nbLoans():NATURAL
_
*
Loan - period : DURATION
en met queries om het tijdstip van de laatste uitlening en de gemiddelde uitleenperiode op te vragen
Software Development Methodology
6
Case 1 : Reïficatie van methodes _
Doel : _ _
De klasse “Book” op PIM niveau voorstellen en specificeren De specificatie transformeren naar PSM niveau Book +loan(period:DURATION):void +nbLoans():NATURAL +latestLoan():DATE +avgLoanPeriod():DURATION
_
We voeren de # - operator in obj#event() _
Deze expressie geeft de verzameling van alle voorkomens op het object obj van de event event() terug
Software Development Methodology
7
Case 1 : Reïficatie van methodes Context Book :: nbLoans() Post: result = card(this#loan()) Context Book :: latestLoan() Pre: not(this#loan()->isEmpty) --- alternatief : Pre: nbLoans() > 0 Post: result = max((this#loan())->ExecutionTime) Context Book Inv: latestLoan() <= now Context Book :: avgLoanPeriod() Post: result = avg((this#loan())->period) Context Book Constraint: for each loan1, loan2 in this#loan() : if (loan1 ≠ loan2) then (loan1->ExecutionTime + loan1->period) <= loan2->ExcecutionTime || (loan2->ExecutionTime + loan2->period) <= loan1->ExcecutionTime Software Development Methodology
8
Case 1 : Reïficatie van methodes _
Transformatie PIM -> PSM _ _ _
_
PSM 1 : Reïficatie van de event “loan” PSM 2 : Niet-reïficatie van de event “loan” PSM 3 : …
Automatisch?
Software Development Methodology
9
PSM 1 : Reïficatie van de event “loan”
_
Method class _ _
_
cfr. Assocation class Elke instantiatie van de method class is een uitvoering van de event “loan()” (en omgekeerd)
Elke karakteristiek van een event is ook een karakteristiek van objecten van de klasse - bv. ExecutionTime -> CreationTime
_
Elke parameter van de event is een property van de klasse
Software Development Methodology
10
PSM 1 : Reïficatie van de event “loan” Context Book :: nbLoans() Post: result = card(this->Loan) Context Book :: latestLoan() Pre: not(this->Loan->isEmpty) Post: result = max((this->Loan)->CreationTime) Context Book Inv: latestLoan() <= now Context Book :: avgLoanPeriod() Post: result = avg((this->Loan)->period) Context Book Constraint: for each loan1, loan2 in this->Loan : if (loan1 ≠ loan2) then (loan1->CreationTime + loan1->period) <= loan2->CreationTime || (loan2->CreationTime + loan2->period) <= loan1->CreationTime Software Development Methodology
11
PSM 1 : Reïficatie van de event “loan” _
Vaststellingen _ _
De transformatie kan automatisch gebeuren Dit PSM is tegelijk een PIM - NATURAL : verschillende transformaties naar een programmeertaal mogelijk - Verschillend bereik mogelijk : long, int, … - Taalafhankelijke verschillen : ulong in C# vs long in Java
- CreationTime
Software Development Methodology
12
PSM 2 : Niet-reïficatie van de event “loan”
_ _ _
Invoeren properties Notatie : (obj#event())@current Twee gevallen : 1. Het resultaat van de query kan bepaald worden op basis van het vorige resultaat en het effect van deze event 2. Het resultaat van de query kan niet bepaald worden zoals in geval 1
Software Development Methodology
13
Transformatie van “nbLoans()” Gegeven : (Geval 1) Context Book :: nbLoans() Post: result = card(this#loan()) Context Book : loan() Pre: Post: -
Stap1: - Zet de query om in een property - Maak van de resultclause een postconditie bij “loan()” - Geef de property een initiële waarde (card(empty set) == 0) Context Book :: property NATURAL nbLoans Initial value : 0 Semantics : card(this#loan()) Context Book : loan() Pre: Post: this.nbLoans = card(this#loan()) Software Development Methodology
14
Transformatie van “nbLoans()” Stap2: Zonder de huidige uitvoering van de methode “loan()” af Context Book : loan() Pre: Post: this.nbLoans = card( (this#loan())@pre union {(this#loan())@current} )
Stap3: card(X union Y) == card(X) + card(Y) Context Book : loan() Pre: Post: this.nbLoans = card( (this#loan())@pre ) + card( {(this#loan())@current} )
Stap4: - Cardinaliteit van een set met 1 element is 1 - Cardinaliteit van de alle uitvoeringen behalve de huidige = de waarde van de instantievariabele voor de uitvoering van de methode Context Book : loan() Pre: Post: this.nbLoans = this.nbLoans@pre + 1
Software Development Methodology
15
Transformatie van “latestLoan()” Gegeven : (Geval 1) Context Book :: latestLoan() Pre: this#loan()->notEmpty Post: result = max((this#loan())->ExecutionTime) Context Book : loan() Pre: Post: -
Stap1: Zet de preconditie om in een booleaanse property Context Book :: property BOOLEAN loanIsExecuted Initial value : false Semantics : this#loan()->notEmpty Context Book :: latestLoan() Pre: loanIsExecuted Post: result = max((this#loan())->ExecutionTime)
Software Development Methodology
16
Transformatie van “latestLoan()” Stap2: - Zet de query om in een property - Maak van de resultclause een postconditie bij “loan()” - Geef de property een initiële waarde (max(empty set) == undefined) Context Book :: property DATE latestLoan Initial value: undefined Pre: loanIsExecuted Semantics: max((this#loan())->ExecutionTime) Context Book : loan() Pre: Post: this.latestLoans = max((this#loan())->ExecutionTime)
Stap3: Zonder de huidige uitvoering van de methode “loan()” af Context Book : loan() Pre: Post: this.latestLoans = max( ((this#loan())@pre)->ExecutionTime union {((this#loan())@current)->ExecutionTime} )
Software Development Methodology
17
Transformatie van “latestLoan()” Stap4:
if (X->isEmpty) then max(X union Y) == max(Y) else max(X union Y) == max{max(X), max(Y)} Context Book : loan() Pre: Post: this.latestLoan = if ((((this#loan())@pre)->ExecutionTime)->isEmpty) then max({((this#loan())@current)->ExecutionTime }) else max{ max(((this#loan())@pre)->ExecutionTime) , max({((this#loan())@current)->ExecutionTime }) }
Stap5:
- Maximum van een set met 1 element is dat element - Maximum van alle uitvoeringen behalve de huidige = de waarde van de instantievariabele voor de uitvoering van de methode - Vervang de booleaanse expressie door de property Context Book : loan() Pre: Post: this.latestLoan = if (not(this.loanIsExecuted@pre)) then ((this#loan())@current)->ExecutionTime else max{this.latestLoan@pre , ((this#loan())@current)->ExecutionTime}
Software Development Methodology
18
Transformatie van “latestLoan()” Stap6: De opgevraagde karakteristieken van de methode worden ingevuld Context Book : loan() Pre: Post: this.latestLoan =
if (not(this.loanIsExecuted@pre)) then now else max{ this.latestLoan@pre , now}
Stap7*: Vereenvoudig de postconditie verder. (latestLoan@pre < now) Context Book : loan() Pre: Post: this.latestLoan =
if nbLoans()@pre = 0 then now else now
en dus: Context Book : loan() Pre: Post: this.latestLoan = now
Software Development Methodology
19
Transformatie van “avgLoanPeriod()” Gegeven : (Geval 2) Context Book :: avgLoanPeriod() Post: result = avg((this#loan())->period) Context Book : loan() Pre: Post: -
Stap1: Herschrijf de functie in een samenstelling van functies om zo tot een ‘Geval 1’ te komen. Context Book :: avgLoanPeriod() Post: result = if this#loan()->isEmpty() (of : card(this#loan()) = 0) then 0 else sum((this#loan())->period) / card(this#loan()) Software Development Methodology
20
Transformatie van “avgLoanPeriod()” Stap2:
- Zet de query om in properties - Maak voor iedere property een postconditie bij “loan()” - Geef de properties een initiële waarde(card(empty set)= 0; sum(empty set)= 0) Context Book :: property NATURAL nbLoans Initial value: 0 Semantics: card(this#loan()) Context Book :: property DURATION totalLoanPeriod Initial value: 0 Semantics: sum((this#loan())->period) Context Book :: avgLoanPeriod() Post: result = if nbLoans = 0 then 0 else totalLoanPeriod / nbLoans Context Book : loan() Pre: Post: this.nbLoans = card(this#loan()) Post: this.totalLoanPeriod = sum((this#loan())->period)
Software Development Methodology
21
Transformatie van “avgLoanPeriod()” Stap3: Ga verder met “Stap2” uit het algoritme met gegeven “Geval1”voor iedere postconditie. Context Book : loan() Pre: Post: this.nbLoans = this.nbLoans@pre +1 Post: this.totalLoanPeriod = this.totalLoanPeriod@pre + period
Software Development Methodology
22
“Algoritme” Stap 1: Herhaal voor elke query : Zet de precondities om in booleaanse properties Stap 2: Herhaal voor elke query : Als het resultaat van de query niet kan bepaald worden op basis van het vorige resultaat en de huidige uitvoering, dan wordt de operatie zo opgesplitst in deeloperaties zodat het resultaat van elk van de deeloperaties wel kan bepaald worden op basis van het vorige resultaat en de huidige uitvoering Stap 3: -
-
Maak de nodige properties aan (zonder dubbels, i.e. properties met dezelfde semantische betekenis, aan te maken!) Laat de query het resultaat in functie van die properties teruggeven
Stap 4: (?) Reduceer het aantal properties. Software Development Methodology
23
“Algoritme” Stap 5: Maak voor iedere property een postconditie bij elke event die voorkomt in de semanticsclause Stap 6: Herhaal voor elke property : Als er een (semantisch) zinvolle waarde kan gegeven worden, dan initialiseer de property, anders is de property initieel undefined Als de property niet altijd defined is dan wordt er een preconditie, die definieert wanneer de property undefined is, aan de property toegevoegd. Stap 7: Herhaal voor elke postconditie : Zonder het huidige voorkomen van de event af Stap 8: Vervang de huidige postconditie f( {vroegere voorkomens} union {huidige voorkomen} ) door g( f( {vroegere voorkomens} ) , f( {huidige voorkomen} ) ) Stap 9: f({huidige voorkomen}) is triviaal f({vroegere voorkomens}) = f@pre = property@pre Stap 10: Vereenvoudig de postconditie - Vul karakteristieken in (vb. ((this#event())@current)->ExecutiontTime = now) - Vereenvoudig expressies (vb. max(0,1) = 1)
Software Development Methodology
24
Inhoudstafel _ _
Motivatie Denkpistes _ _
Reïficatie van methodes Verbanden tussen methodes - Reïficatie van toestanden
_
Complexe hiërarchieën
Software Development Methodology
25
Case 2 : Verbanden tussen methodes (1) _
Gegeven _ _
een klasse van boeken met dezelfde events en queries Een extra event “return()” - Een boek kan pas teruggebracht worden als het uitgeleend was - Een uitgeleend boek kan niet uitgeleend worden
Software Development Methodology
26
Case 2 : Verbanden tussen methodes (1)
Software Development Methodology
27
Case 2 : Verbanden tussen methodes (1)
Software Development Methodology
28
Case 2 : Verbanden tussen methodes (1) Context Book :: nbLoans() Post: result = card(this#loan()) Context Book :: latestLoan() Pre: not(this#loan()->isEmpty) Post: result = max((this#loan())->ExecutionTime) Context Book Inv: latestLoan() <= now Context Book :: avgLoanPeriod() Post: let returnedLoans = {loan ∈ this#loan()| loan.return()->notEmpty} in result = avg({{period in DURATION | loan ∈ returnedLoans : loan.return()->ExecutionTime – loan->ExecutionTime}}) Context Book Constraint: for each loan in this#loan() : {l ∈ this#loan()| l->ExecutionTime < loan->ExecutionTime and if (l.return()->notEmpty) then loan->ExecutionTime
ExecutionTime else true }->isEmpty Software Development Methodology
29
Case 2 : Verbanden tussen methodes (1) _
PSM 1 : Reïficatie van de events
_
PSM 2 : Niet-reïficatie van de events _
uit te werken…
Software Development Methodology
30
Case 2 : Verbanden tussen methodes (2) _
Gegeven _ _
een klasse van bankrekeningen events om geld te storten, af te halen, over te schrijven Account + transfer(amount:MONEYAMOUNT,dest:Account):void + deposit(amount:MONEYAMOUNT):void + withdraw(amount:MONEYAMOUNT):void
_
Abstracte methode Account + transaction(amount:MONEYAMOUNT):void + transfer(dest:Account):void + deposit():void + withdraw():void
Software Development Methodology
31
Inhoudstafel _ _
Motivatie Denkpistes _ _
Reïficatie van methodes Verbanden tussen methodes - Reïficatie van toestanden
_
Complexe hiërarchieën
Software Development Methodology
32
Hiërachieën
Software Development Methodology
33
Property + constraint Context Account :: property MONEYAMOUNT balance Initial value: 0 Semantics: sum( (this#deposit())->amount union (-1)*(this#withdraw())->amount) ) Context Book Inv: balance > 0
_
Programmeren : hoe dwingen we de constraint af? _ _ _ _
Nominaal (precondities) Totaal Defensief (uitzonderingen) Op database niveau
Software Development Methodology
34