8 Specifikation med Logiske Udtryk.

Relaterede dokumenter
26 Programbeviser I. Noter. PS1 -- Programbeviser I. Bevis kontra 'check af assertions' i Eiffel. Betingelser og bevisregler.

Årsagen til fejl. Erkendelse af fejl. Håndtering af fejl.

4 Basal Objekt-orienteret Programmering I.

3 Algebraisk Specifikation af Abstrakte Datatyper.

14 Algoritmeanalyse. Noter. Algoritmebegrebet. Hvad er algoritmeanalyse? Problemstørrelse og køretid. Køretid for forskellige kontrolstrukturer.

22 Hobe. Noter. PS1 -- Hobe. Binære hobe. Minimum-hob og maximum-hob. Den abstrakte datatype minimum-hob. Opbygning af hobe. Operationen siv-ned.

Design by Contract. Design and Programming by Contract. Oversigt. Prædikater

Rename og redefine. Abstrakte klasser. Dynamisk binding.

Design by Contract Bertrand Meyer Design and Programming by Contract. Oversigt. Prædikater

t a l e n t c a m p d k Matematiske Metoder Anders Friis Anne Ryelund 25. oktober 2014 Slide 1/42

Algoritmeskabeloner: Sweep- og søgealgoritmer C#-version

Udvidelse og specialisering. Klassehierarkier. Nedarvningsterminologi. Interfaces. Statiske og dynamiske typer. Polymorfi. Abstrakte klasser.

13 Objekt-orienteret Design.

29 Opsamling af Objekt-orienteret Programmering.

28 Algoritmedesign. Noter. PS1 -- Algoritmedesign

2 Abstrakte datatyper.

30 Objekt-orienteret Programmering i Andre Sprog.

12 Nedarvning III. Noter. Multipel nedarvning. Nedarvning og assertions. PS1 -- Nedarvning III. Kurt Nørmark, Aalborg Universitet, 1994.

Kontraktbaseret Design. Anker Mørk Thomsen

Elementær Matematik. Mængder og udsagn

BOSK F2012, 1. del: Prædikatslogik

5 Basal Objekt-orienteret Programmering II.

Videregående Programmering for Diplom-E Noter

Martin Olsen. DM507 Projekt Del I. 19. marts 2012 FOTO: Colourbox

Forelæsning Uge 4 Mandag

16 Træer. Noter. Definition af et træ. Definitioner i tilknytning til træer. Repræsentation af træer. Binære træer. Den abstrakte datatype.

18 Multivejstræer og B-træer.

Opfølgning på Dygtig Skildpadde (Michael) To algoritmeskabeloner

Bevisteknikker. Bevisteknikker (relevant både ved design og verifikation) Matematisk induktion. Matematisk induktion uformel beskrivelse

Basale forudsætninger. Sortering ved fletning med tre bånd, i to faser.

Noter til Perspektiver i Matematikken

Abstrakte datatyper C#-version

16. december. Resume sidste gang

DM507 Algoritmer og datastrukturer

Software Construction 1 semester (SWC) Spørgsmål 1

Sortering. Eksempel: De n tal i sorteret orden

Brug og Misbrug af logiske tegn

Databasesystemer. Databaser, efterår Troels Andreasen. Efterår 2002

DM507 Algoritmer og datastrukturer

Exceptions i Delphi. Try except

Sortering af information er en fundamental og central opgave.

01017 Diskret Matematik E12 Alle bokse fra logikdelens slides

Åben uddannelse, Efterår 1996, Oversættere og køretidsomgivelser

Sortering. Eksempel: De n tal i sorteret orden

class Time { int hours, min; } } Time t1; // Erklær variabel af type Time class Time1 { public static void main(string[] args) { Time t1; t1.

1 Grundbegreber. Noter. Stilarter i programmering og sprog. Syntaks og semantik. Datatyper. Kontrolstrukturer. Udtryk. Abstraktioner.

Opskriv følgende funktioner efter stigende orden med hensyn til O-notationen (bemærk at log n betegner totals logaritmen): n 2 (log n) 2 2.

P (n): rekursiv beregning af f n kræver f n beregninger af f 1. P (n) er sand for alle n 2.

Matematiske metoder - Opgavesæt

Listen over reserverede ord er meget lang, men de væsentligste vil jeg beskrive her i denne artikel:

Induktive og rekursive definitioner

Skriftlig Eksamen Algoritmer og Datastrukturer (dads)

Forelæsning Uge 4 Torsdag

Studieordning for diplomuddannelsen i informationsteknologi

Sortering af information er en fundamental og central opgave.

OBS! Prøveeksamen med syntaks på tirsdag! Kursusgang 8

Sortering. De n tal i sorteret orden. Eksempel: Kommentarer:

Ugeseddel 4 1. marts - 8. marts

DM507 Algoritmer og datastrukturer

Bevisteknikker (relevant både ved design og verifikation)

Klasser og objekter. (Afsnit i manualen)

Skriftlig eksamen i Datalogi

It og informationssøgning Forelæsning oktober 2006 Jakob Grue Simonsen. Klasser

Algoritmedesign med internetanvendelser ved Keld Helsgaun

Rekursion og dynamisk programmering

Objektorienteret design med arv og polymorfi:

Assignment #5 Toolbox Contract

Algoritmer og Datastrukturer 1. Gerth Stølting Brodal Aarhus Universitet

Forelæsning Uge 4 Mandag

Skriftlig Eksamen DM507 Algoritmer og Datastrukturer

Forelæsning Uge 4 Torsdag

vil jeg blive mindet om det af VBA allerede mens jeg skriver koden, da der er tale om en såkaldt kompileringsfejl:

Rekursion C#-version

Sproget Rascal (v. 2)

Introduktion til Funktionsorienteret Programmering.

DM517:Supplerende noter om uafgørlighedsbeviser:

De rigtige reelle tal

Sammenhængskomponenter i grafer

AAU, Programmering i Java Intern skriftlig prøve 18. maj 2007

15 Arrays og Lister samt Stakke og Køer.

Skriftlig eksamen i Datalogi

[FUNKTIONER] Hvornår kan vi kalde en sammenhæng en funktion, og hvilke egenskaber har disse i givet fald. Vers. 2.0

Rolf Fagerberg. Forår 2012

DM507 Algoritmer og datastrukturer

Lær Python dag 1 - modul 1

Skriftlig eksamen, Programmer som Data Onsdag 6. januar Spørgsmål 1 (20 %): Regulære udtryk og automater

16. marts P NP. Essentielle spørgsmål: NP P? Et problem Q kaldes NP -fuldstændigt 1 Q NP 2 R NP : R pol Q. Resume sidste gang

Grafer og graf-gennemløb

Databasesystemer, forår 2005 IT Universitetet i København. Forelæsning 3: E-R modellering. 17. februar Forelæser: Rasmus Pagh

Algoritmer og Datastrukturer 1. Gerth Stølting Brodal

Forelæsning Uge 2 Mandag

Algoritmer og Datastrukturer 1. Gerth Stølting Brodal

Noter til C# Programmering Iteration

Klasser og Objekter i Python. Uge 46 Learning Python: kap 15-16,

Kontrol-strukturer i PHP

16/04/12 50% 50% Waveform Chart Waveform Graph XY Graph Indicator Graph 33% 17% 88% 13%

Skriftlig eksamen i Datalogi

Grafer og graf-gennemløb

Grafer og graf-gennemløb

DATALOGISK INSTITUT, AARHUS UNIVERSITET. Det Naturvidenskabelige Fakultet EKSAMEN. Grundkurser i Datalogi

Transkript:

8 Specifikation med Logiske Udtryk. Specifikation kontra program. Specifikation af funktioner. Specifikation af funktions-orienterede ADT-er. Integreret specifikation og program i Eiffel. Korrekthed af Eiffel klasse i forhold til dens specifikation. Overgangen til fejlhåndtering. Notationen til specifikation af funktioner samt en del af eksemplerne i denne forelæsning er taget fra bogen Cliff B. Jones "Software Development -- A Rigorous Approach", Prentice Hall, 1980. 109

Specifikation i forhold til program. Hvad og ikke hvordan En specifikation af en abstrakt datatype udtrykker, hvad operationerne gør, snarere hvordan den gør det. Bevis af korrekthed En specifikation kan benyttes til at bevise, at en implementation af en abstrakt datatype er korrekt i forhold specifikationen. Check af korrekthed En specifikation kan benyttes til at checke en implementation af en abstrakt datatype under programudførelsen. Vi har i en tidligere forelæsning stiftet bektskab med den algebraiske specifikations-teknik. I denne forelæsning vil vi introducere en anden form for specifikationer, baseret på logiske udsagn tilknyttet en abstrakte datatype og dens operationer. Denne slide minder læseren om, at specifikationerne, som vil blive behandlet i denne forelæsning, har samme grundlægge egenskaber og formål som algebraiske specifikationer. Hvorfor indfører vi en ny specifikationsform, når vi allerede har brugt tid og kræfter på at forstå een sådan formalisme (algebraiske specifikationer)? 1. I forbindelse med praktisk, objekt-orienteret programmering ønsker vi at kunne tilknytte specifikationen tæt til selve programmet. Der er ofte for stor afstand mellem elementerne i en algebraisk specifikation af en ADT og implementationen af en klasse, der realiserer typen. Én årsag er, at operationer i en algebraisk specifikation er rene funktioner, mens operationer i klasser ofte har sideeffekter på den af klassen beskrevne tilstand. Specifikation af abstrakte datatyper med logiske udtryk kan således bringes tættere til elementerne i implementationen af typen. 2. Der findes nogle datatyper, som mest hensigtsmæssigt specificeres algebraisk; og omvt. Det betyder, at hvis vi har to forskellige specifikationsformer til vores rådighed, vil vi kunne vælge den mest hensigtsmæssige i en given situation. 110

Specifikation af ADT-er med funktioner. Type Navn Functions Funktions-specifikationer Pre- og postbetingelsessignaturer: pre-f: T1 x T2 x Tn -> Boolean post-f: T1 x T2 x Tn x R -> Boolean Specifikation af en funktion: f: T1 x T2 x Tn -> R pre-f(t1, t2,, tn) = boolsk udtryk post-f(t1, t2,, tn, r) = boolsk udtryk En prebetingelse udtrykker, om det er meningsfuldt at kalde funktionen med de givne parametre. En postbetingelse udtrykker, at funktionen returnerer et bestemt resultat, når denne kaldes med de givne parametre. Vi starter med at introducere specifikation af abstrakte datatyper, hvor alle operationer er funktioner, på samme måde som alle operationer i de algebraiske specifikationer, vi tidligere har set på, er funktioner. Dette betyder, at operationer på datatypen ikke ændrer i objekters tilstand. Hvis vi er igang med at specificere typen T, kan vi have en operation f: T -> T, hvor f(t) er at betragte som en modificeret kopi af det objekt, f blev anvt på. I en praktisk objekt-orienteret programmeringssammenhæng vil vi i stedet for udtrykke os med t.f; operationen f kaldes på objektet t, som er af typen T; f kan have en eller anden effekt på tilstanden af det objekt, t refererer til. Vi vil i denne forelæsning gradvis nærme os en situation, hvor vi kan bruge logiske udsagn til at specificere ADT-er i Eiffel. Dette omfatter også klasser, hvis instanser har tilstand, der muteres. 111

Eksempler på specifikation af funktioner. Subtraktion: sub: Int x Int -> Int pre-sub(x, y) = true post-sub(x, y, r) = ( x = y + r) Kvadratrod: Eksplicit specifikation sqrt: Real -> Real pre-sqrt(r) = (r 0) post-sqrt(r, s) = (s = r) Implicit specifikation sqrt: Real -> Real pre-sqrt(r) = (r 0) post-sqrt(r, s) = (s * s = r) Største fælles divisor: gcd: Nat x Nat -> Nat pre-gcd(x, y) = true post-gcd(x, y, r) = is-common-divisor (x, y, r) and ( e in Nat: ((e > r) and is-common-divisor(x, y, e)) ) I den eksplicitte specifikation af kvadratrodsfunktionen sqrt antager vi, at den matematiske kvadratrodsfunktion er kt og veldefineret. I den implicitte specifikation antager vi "kun", at vi ker mulitiplikationsoperationen Kvantorer i logiske udtryk tilføjer ekstra udtryksfuldhed i specifikationen. Opgave. I specifikationen af gcd er der benyttet en anden funktion is-common-divisor: Nat x Nat x Nat -> Boolean. Intuitivt ønsker vi, at is-common-divisor(x, y, r) udtrykker om r går op i både x og y. Specificer denne funktion. I specifikationen af is-commondivisor benyttes måske en ny funktion, som bør specificeres. Diskuter hvor langt man skal gå med specifikationen af sådanne funktioner. 112

Korrekthedsbevis af funktionsimplementation på basis af specifikation Specifikation af en funktion: f: T1 x T2 x Tn -> R pref-f(t1, t2,, tn) = post-f(t1, t2,, tn, r) = Implementation af funktionen f(p1: T1; p2: T2; pn: Tn): R is --declarations --body Relativ til implementation af f skal det vises at: t1 in T1, t2 in T2, tn in Tn: pre-f(t1, t2,, tn) => post(t1, t2,., tn, f(t1, t2, tn)) For at kunne bevise dette formelt kræves, at der er formuleret bevisregler for alle de typer af konstruktioner, der benyttes i kroppen af f. Formålet med denne slide er at gøre klart, hvad det vil sige at bevise korrektheden af implementationen af en funktion ud fra en specifikation af funktionen. Implikationen, som er kriteriet for, at funktionen er korrekt, udtrykker, at hvis prebetingelsen er sand så skal postbetingelsen være opfyldt på parametrene og det resultat, som funktions-implementationen returnerer. For at gennemføre et sådant bevis minutiøst og overbevise kræves, at man ker den præcise betydning af de kommaner og udtryk, der indgår i funktionsdefinitionen. På nuvære tidspunkt har vi ikke defineret semantikken af de enkelte Eiffel kommander på en formel matematisk måde. Derfor kan vi ikke for nærvære udføre beviser af korrektheden af en funktion. Vi ver imidlertid tilbage til bevisregler for udvalgte kommaner senere på kurset. Næste slide konkretiserer indholdet af denne slide i den situation, at vi vil vise, at en bestemt implementation af Fibonacci funktionen myfib er korrekt i forhold til specifikationen. 113

Eksempel på specifikation, implementation og krav til korrekthedsbevis for en funktion. Givet funktionen fib: fib(0) = 0 fib(1) = 1 fib(n) = fib(n-1) + fib(n-2), n 2 Specifikation af myfib: myfib: Nat0 -> Nat0 pre-myfib(n) = true post-myfib(n, r) = (r = fib(n)) Implementation af myfib myfib(n: integer): integer is local a: integer; b: integer; count: integer; br: integer from a := 1; b := 0; count := n; until count = 0 loop br := b; b:= a; a := a + br; count := count - 1 ; result := b ; -- myfib For at bevise, at implementationen af myfib er korrekt, skal man vise, at result = fib(n), når myfib terminerer. Specifikationen af myfib, og det vil i et og alt sige den rekursive defintion af fib, udgør grundlaget for et bevis for, at Eiffel implementationen af myfib er korrekt. Som omtalt har vi nu ikke introduceret bevisreglerne for assignment og loop kommanerne i Eiffel, så vi kan nu ikke bevise korrektheden af funktionen. I en senere forelæsning vil vi beskrive semantikken af udvalgte Eiffel kommaner. Vi vil ve tilbage til netop dette eksempel og gennemføre beviset for korrektheden af myfib i forhold til dens specifikation. Opgave: Find en variant og en invariant af løkken i funktionen myfib. Løsningen findes i noterne til sidste slide i denne forelæsning. (Det anbefales, at man prøver på at formulere varianten og invarianten, inden man kigger). 114

Assertions i Eiffelprogrammer. Et Eiffel program kan tilknytte en række logiske udtryk, som vi vil benævne assertions. Assertions udgør en programspecifikation. En specifikation udtrykker betingelserne for, at programmet er korrekt. Assertions udgør også højniveau kumentation af klasse i Eiffel understøttelse af lokalisering af årsagen til fejl (debugging) grundlaget for håndtering af undtagelsessituationer (exceptions). et redskab for definition af ansvarsfordeling mellem klasser. Denne slide udtrykker nogle overordnede kvaliteter ved anvelsen af assertions i et Eiffel program. 115

Pre- og postbetingelser og klasseinvarianter i Eiffel. class C feature op1() is require pre-op1 ensure post-op1 ; --op1 Formuleret Prebetingelse Formuleret Postbetingelse Eiffel assertions. op2() is require pre-op2 ensure post-op2 Formuleret Klasseinvariant invariant class-c-invariant ; --class C Vi går nu over til at studere specifikation af Eiffel programmer. Prebetingelserne ovenfor, såsom pre-op1, kaldes de formulerede prebetingelser. Den egentlige prebetingelse, som skal gælde for op1 dannes ud fra den formulerede prebetingelse og invarianten. Vi ver tilbage til dette senere i kapitlet. Ganske tilsvare forhold gælder for postbetingelserne. Vi taler altså også om den formulerede postbetingelse. Vi kalder invarianten, som angives nederst i en klasse-definition, for den formulerede klasseinvariant. 116

Klasseinvarianter i Eiffel. En klasseinvariant er et assertion, som udtrykker nogle generelle betingelser som alle objekter af klassen skal opfylde på bestemte tidspunkter i objeternes levetid. Hvornår skal invarianten være opfyldt: Efter instantiering og initialisering (efter udførelsen af Create). Efter (og før) udførelse af en eksporteret operation, som overholder sin pre-betingelse. Typisk brug af klasseinvarianter: En klasseinvariant udtrykker typisk betingelser for konsistens mellem attributværdier og funktionsværdier i en instans af klassen. Invarianten skal altså være opfyldt efter instantiering/initialisering samt efter hver ekstern operation på typen. Man kan spørge om dette implicerer, at invarianten er opfyldt før hver operation på typen. Dette er tilfældet i simple situationer. Der kan g laves invarianter, som kan ændres udefra, uden at der bliver kaldt en operation på typen. Det er tilfældet, hvis invarianten involverer udtryk, som kan påvirkes fra andre klasser. 7.11.3 i OOSC handler om dette. Vi vil derfor også kræve, at invarianten er opfyldt, inden en operation udføres. Invarianter kes også fra vores ikke-tekniske hverdag. Det er f.eks. en regel, at kanden på afdelingens kaffemaskiner altid skal indeholde mindst een krus kaffe. Alle transaktioner på kaffemaskinen skal overholde denne invariant. Bemærk at handlingerne, der beståer i at tømme kaffekanden samt at lave ny kaffe er at betragte som én transaktion i denne model. På et tidspunkt er kanden tom, men da dette tidspunkt ikke forekommer mellem to (eksterne) transaktioner på maskinen, bryder vi ikke invarianten. Ved forelæsningen vil vi se på en klasse 'Kunde', som indeholder navne og adresseattributter, og vi vil diskuterer forskellige konsistensforhold i objekter af denne klasse. 117

Eksempel på klasseinvariant. class BANK_ACCOUNT creation create feature balance, interest_rate : REAL; interest_rate: real; create(initial_amount: REAL) is transactions.create(100); balance := initial_amount; transactions.put(initial_amount) ; deposit(amount: real) is ; withdraw(amount: real) is ; add_interest(days: integer) is ; feature {NONE} transactions: TRANSACTION_HISTORY; add(amount: real) is transactions.put(amount); balance := balance + amount invariant balance = transactions.add_together; ; -- class BANK_ACCOUNT Eksemplet viser den velkte klasse BANK_ACCOUNT med en transaktionshistoie. Invarianten udtrykker en vigtig konsistensbetingelse mellem attributten balance og den lagrede transaktionshistorie. 118

Eksempel på klasseinvariant (fortsat). Class TRANSACTION_HISTORY creation create feature{none} history: ARRAY[TRANSACTION]; next_free, high_index: INTEGER; feature create(max: INTGER) is high_index := max; history.create(1,max); next_free := 1; ; put(amount: REAL) is require not full local tr: TRANSACTION tr.create(amount); history.put(tr, next_free); next_free := next_free + 1 ; get(i: integer): TRANSACTION is require i < next_free; i >= 1 result := history.item(i) ; full: BOOLEAN is result := next_free > high_index ; add_together: REAL is ; -- class TRANSACTION_HISTORY Denne slide viser en skitse af klassen TRANSACTION_HISTORY, som blev anvt i eksemplet på forrige side. 119

Kontrakt mellem en klasse og dens klienter. class supplier feature op_supplier() is require pre ensure post class client feature x: supplier op_client() is x.op_supplier() Nydelse: Jeg ved, at prebetingelsen er opfyldt Ydelse: Jeg skal opfylde postbetingelsen Ydelse: Jeg skal opfylde prebetingelsen Nydelse: Jeg ved, at postbetingelsen er opfyldt. På denne slide (og nedenfor) betegner prebetingelsen den effektive prebetingelse. Ditto med postbetingelsen. De effektive pre- og postbetingelser udgør en kontrakt mellem en klasse og dens klienter. En operation i klassen lover at opfylde post-betingelsen såfremt klienten kalder operationen med opfyldt prebetingelse. Kontrakten er udtryk for en klar ansvarsfordeling mellem klient og leverandøren. Det er klientens ansvar at undersøge, om prebetingelsen af supplier-operationen er opfyldt. Hvis dette ikke er tilfældet, bliver supplier-operationen ikke kaldt, og der opstår en fejlsituation i klienten. Det er således ikke nødvig i kroppen af en operation i leverandør-klassen at teste, om operationens pre-betingelse er opfyldt. Den skal være opfyldt. Hvis supplier-operationen ikke opfylder sin post-betingelse opstår der en fejlsituation i supplier klassen. Denne klare ansvarsfordeling, og deraf følge minimal, eksplicit programmet test af betingelser forud for udførelsen af en operation, står i skarp kontrast til en programmeringsteknik, som kaldes defensiv programmering. I defensiv programmering går man både med livrem og seler i den forstand, at man gerne udfører samme test (f.eks. af prebetingelsen) to forskellige steder i programmet, for at forhindre misforståelser om ansvarsfordelingen. I og med at opfyldelse af prebetingelsen er klientens ansvar, skal alle dele af en prebetingelse være tilgængelig for klienterne. Dette betyder, at der ikke må indgår hemmelige (private/usynlige) deltryk i en prebetingelse. Hvis der var dele af en prebetingelse, der var hemmelige, ville man kun vanskeligt kunne laste klienten, at en prebetingelse ikke kunne opfyldes (Klienten kunne sige: Det er meget godt, men jeg har ikke en chance for at ke til de detaljer, som prebetingelsen udtaler sig om ). I en postbetingelse må der derimod godt indgår private aspekter fra en klasse. Når postbetingelsen annonceres til klienter i kumentationsøjemed (af værktøjet short), ser man bort fra de dele af en postbetingelse, der indeholder private elementer. 120

Formen af assertions i Eiffel. Assertion: en konjunktion ( and then -ing) af enkelt-assertions. Enkelt-assertion: navngiven eller unavngiven assertion-klausul Assertion-klausul: Boolsk udtryk eller Uformel assertion. Eksempel: min_betingelse: i 0; max_betingelse: i < max; -- for alle i mellem 0 og max gælder p(i) Post-betingelser: Assertion som beskrevet ovenfor med følge udvidelser exp beregnet med hensyn til objektets old exp tilstand før kald af operationen. equal(strip (), old strip ()) Sand hvis og kun hvis objektets tilstand er uforandret ift. før kaldet. I eksemplet midt på denne slide vises der en konjunktion af tre enkelt-assertions, hvoraf de to første er navngivne, og det sidste er uformelt angivet (som en kommentar: -- ). Navnene på del-assertions er uden betydning for det samlede assertion, og de har ingen betydning for semantikken af programmet. Navnene tjener til fornuftig kommunikation mellem køretidssystemet (når det opdager en fejl under programudførelse) og testkøreren. Assertions der består af kommentarer spiller udelukke en rolle som kumentation. Bemærk at old expr kun må forekomme i en postbetingelse. Det noget mystiske udtryk equal(strip(), old strip()) anver et primitiv strip(a, b, ) som vi nu ikke har set på. Kort fortalt returnerer det et array af alle felter i det nuvære objekt, pånær felterne med navnene a, b, etc. Specielt returnerer strip() et array af alle felter (i en eller anden bestemt rækkefølge) af det nuvære objekt. Ovenståe udtryk siger dermed, at objektets tilstand er uforandret af den operation, hvoraf vi nu studerer postbetingelsen. Strip er et generelt tilgængelig primitv, som g klart snævert er designet mod ovenståe anvelse. Strip er beskrevet i afsnit 23.21 og 9.10 af Eiffel the Language. 121

Specifikation af klasser i Eiffel. Sammrag Prebetingeler, postbetingelser og invarianter. Eiffel understøtter pre- og postbetingelser på operationer samt invarianter i klasser. Mutation af programtilstand. Nogle operationer i en ADT i Eiffel muterer (ændrer) tilstanden af programmet. Ikke alle operationer er funktioner. Check af assertions. Assertions i Eiffel skal kunne verificeres under programudførelsen, uden massiv påvirkning af udførelsestiden af programmet. Dette udelukker udsagn med eksistens- og alkvantorer. Uformelle assertions. Pre- og postbetingelser er ikke nødvigvis formelle. Man kan skrive uformelle pre- og postbetingelser, som naturligvis ikke kan verificeres under programudførelse. 122

Korrekthedskriterium for Eiffel-klasser. class C creation create feature create() is require pre-create krop-create ; --create op() is require pre-op krop-op ensure post-op invariant INV ; --class C {pre-create } krop-create {INV} For alle eksporterede operationer: {INV and pre-op } krop-op {INV and post-op} Korrekthedskriteriet udtrykker betingelserne for, at implementationen af klassen opfylder den givne specifikation. Notationen {assertion1} kommaner {assertion2} er en såkaldt Hoare-sætning, som udtrykker: Hvis assertion1 er opfyldt før udførelsen af kommaner, og hvis kommaner terminerer, da skal assertion2 være opfyldt efter udførelsen af kommaner. I forbindelse med programbeviser i del 2 af noterne vil vi stifte nærmere bektskab med denne notation. Korrekthedskriteriet for Create læses: Hvis Create's prebetingelse er opfyldt, så skal klasseinvarianten INV være opfyldt, efter at kroppen af Create er udført. Man kunne godt vælge at styrk prebetingelsen med et udsagn der udtrykker default initialiseringen af felter, som foretages af Eiffel. Man kunne også godt vælge at medtage en eksplict postbetingele af creation proceduren, som dermed ville kunne styrke INV. Tilsvare for korrekthedskriteriet for andre operationer Create: Hvis invarianten og prebetingelsen er opfyldt inden udførelsen af operationen, da skal postbetingelsen og invarianten være opfyldt efter udførelse af operationen. Konjunktionerne af de formulerede pre/postbetingelser og klasseinvarianten udgør det vi kalder de effektive pre/postbetingelser. (ne fortsættes på flg. sides noteark). 123

Hvis assertions ikke overholdes Hvis en assertion brydes: Programmet kommer i en undtagelsestilstand. Programmet får chancen for at håndtere tilstanden: Undtagelsestilstanden afblæses, og programmet fortsætter eller Programmet terminerer, og undtagelsessituationen beskrives. Det er relevant at spørge, om invarianten skal checkes i følge situation: class C feature op1() is ; op2(); ; op2() is invariant INV ; --class C Løsning til opgave Løsning til opgave på slide: "Eksempel på specifikation, implementation og krav til korrekthedsbevis for en funktion": Varianten kan være count, idet denne variabel tælles ned for hvert gennemløb, og den bliver aldrig negativ. Invarianten kan være a = fib(n - count + 1); b = fib(n - count); count 0; count Š n Vi antager at op1 kaldes fra en klient af klassen C. Spørgsmålet er hvorvidt invarianten skal checkes når op1 kalder op2 på current object. Det fremgår, at når op2 kaldes fra op1 kan op2 opfattes som en intern operation, som sammen med de øvrige handlinger i op1 skal tilfredsstille invarianten; det er ikke nødvigt at op2 i denne situation selv tilfredsstiller invarianten. Det er ikke let at finde nogen kumentation af denne situation i Eiffel manualerne, og man kan blive i tvivl om præcist hvornår invarianten skal checkes. En testkørsel afslører, at vores installation ikke checker invarianten, når op2 kaldes fra op1 (Eiffel 2.3 resultat). Bemærk, at invarianten er opfyldt før udførelsen af løkken, idet count her har værdien n, a er 1, b er 0, samt fib(1) = 1 og fib(0) = 0, jf. definitionen af fib. Bemærk også, at ved termineringen af løkken er count = 0, hvilket vil sige, at b = fib(n). Sidstnævnte er i alt væsentlighed postbetingelsen af myfib. 124