Kontraktbaseret Design. Anker Mørk Thomsen



Relaterede dokumenter
Kontraktbaseret Design. Anker Mørk Thomsen

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

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

Ugeseddel 4 1. marts - 8. marts

Kontraktbaseret Programmering Anker Mørk Thomsen 1. udgave ISBN:

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

Abstrakte datatyper C#-version

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

DM507 Algoritmer og datastrukturer

Skriftlig eksamen i Datalogi

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

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

Jan B. Larsen HTX Næstved Computational Thinking Albena Nielsen N. Zahles Gymnasium 2018/2019

Programmering, algoritmik og matematik en nødvendig sammenblanding?

DM507 Algoritmer og datastrukturer

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

Klasser og objekter. (Afsnit i manualen)

Sproget Rascal (v. 2)

4 Basal Objekt-orienteret Programmering I.

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

DM507 Algoritmer og datastrukturer

Sproget Six. Til brug i rapportopgaven på kurset Oversættere. Vinter Abstract

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

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

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

DM507 Algoritmer og datastrukturer

Introduktion til funktioner, moduler og scopes i Python

1 Opsumering fra tidligere. 2 Dagsorden 3 BIMS. 4 Programtilstande. Statements/kommandoer (Stm) i bims. 3.1 Abstrakt syntaks for bims

Forelæsning Uge 4 Mandag

Skriftlig Eksamen DM507 Algoritmer og Datastrukturer

Objektorienteret design med arv og polymorfi:

Opgaver hørende til undervisningsmateriale om Herons formel

DM507 Algoritmer og datastrukturer

DM507 Algoritmer og datastrukturer

4 Oversigt over kapitel 4

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

Forelæsning Uge 5 Mandag

13 Objekt-orienteret Design.

JavaScript. nedarvning.

Programmering i C. Lektion september 2009

Skriftlig Eksamen Algoritmer og Datastrukturer (dads)

Objektorientering. Programkvalitet

Eksempel: Skat i år 2000

Grundlæggende Algoritmer og Datastrukturer

Udarbejdet af CFU Absalon

8 Specifikation med Logiske Udtryk.

Programming Language Design and Analysis motivated by Hardware Evolution

Dokumentation af programmering i Python 2.75

Programmering 2. dprog2 E

Undervisningsbeskrivelse

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

Kapitel 3 Betinget logik i C#

Rekursion C#-version

Forelæsning Uge 4 Mandag

Tal og algebra. I kapitlet arbejdes med følgende centrale matematiske begreber: algebra variable. Huskeliste: Tændstikker (til side 146) FRA FAGHÆFTET

Udsagnslogik. Anker Mørk Thomsen. 6. december 2013

DM507 Algoritmer og datastrukturer

Undervisningsbeskrivelse

Rolf Fagerberg. Forår 2013

3 Algebra. Faglige mål. Variable og brøker. Den distributive lov. Potenser og rødder

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

Undervisningsbeskrivelse

Hvem er vi? Kursus Introduktion. Kursuslærerne. Agenda for i dag

Lær Python dag 1 - modul 1

Datalogi OB, Efterår 2002 OH er, forelæsning 10/ Klasser og nedarvning

Forelæsning Uge 4 Torsdag

Objects First with Java A Practical Introduction Using BlueJ

Programmering 2. dprog2 E

Introduktion til DM507

Undervisningsbeskrivelse

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

Forelæsning Uge 2 Torsdag

Læseplan for valgfaget teknologiforståelse. (forsøg)

Noter til C# Programmering Selektion

16. december. Resume sidste gang

Forelæsning Uge 6 Mandag

Datalogi OB, Efterår 2002 OH er, forelæsning 3/ forstå datastrukturer og algoritmer (teoretisk forståelse og intuition)

Studieordning for diplomuddannelsen i informationsteknologi

Programmering 1999 KVL Side 5-4. Klassen Time: metoder. Metoder i objektet giver mulighed for at ændre tilstanden, eller kigge på tilstanden.

Undervisningsbeskrivelse

Exceptions i Delphi. Try except

Forelæsning Uge 4 Torsdag

Kursus i OOP og Java. Kursus i Objektorienteret programmering i Java

Projekt arbejde til kurset Advanced Models and Programs, SASP-AMP 2008 Poul Brønnum, IT Universitetet i København, Maj Indholdsfortegnelse

Undervisningsbeskrivelse

Polymorfi. Arv (inheritance) Abstrakte klasser, substitutionsprincippet, overriding, statisk og dynamisk type. Coercion

Læseplan for valgfaget teknologiforståelse

Sproget Limba. Til brug i G1 og K1. Dat1E 2003

DM507 Algoritmer og datastrukturer

Undervisningsbeskrivelse

Dat 2/F6S: Syntaks og semantik 2005 Centrale emner og eksamenspensum

Skriftlig eksamen i Datalogi

BOSK F2012, 1. del: Prædikatslogik

Rolf Fagerberg. Forår 2015

Noter til Perspektiver i Matematikken

Kreativ programmering

Forelæsning Uge 1 Torsdag

Studiepraktik. Thomas Bøgholm Mikkel Hansen Jacob Elefsen

Skriftlig eksamen i Datalogi

Nye testteknikker fra ISTQB - direkte fra hylderne. Ole Chr. Hansen

Transkript:

Kontraktbaseret Design Anker Mørk Thomsen 5. marts 2014

-2 Kontraktbaseret Design Anker Mørk Thomsen 1. udgave ISBN: 9788740491500

Forord Bogen er blevet til gennem undervisning i faget Kontraktbaseret Udvikling på bacheloruddannelsen i Softwareudvikling. Emnet har jeg opdelt i to dele. Den første del omfatter konstruktion og udvikling af algoritmer ved anvendelse af formelle metoder. Denne første del indeholder også den diskrete matematik, som danner grundlag for at kunne arbejde med de formelle metoder. Kontraktbaseret Design omhandler design af programmodulerne i et objektorienteret sprog og er inspireret af Design by Contract by example, se Mitchell and McKim [2002]. Januar 2014 Anker Mørk Thomsen -1

Indhold 1 Kontraktbaseret Design 3 1.1 Specifikationer....................................... 4 1.2 Spillet NIM......................................... 5 1.3 Kontrakter......................................... 9 1.4 Introduktion til JML................................... 10 1.4.1 Kontrakt for en procedure............................ 11 1.4.2 Uformelle prædikater i specifikationer..................... 12 1.4.3 Øvelser....................................... 13 1.4.4 Kontrakt for en funktion............................. 13 1.5 Motivation for brug af kontrakter............................ 14 1.6 Interface Clock....................................... 16 1.6.1 Øvelser....................................... 17 1.7 Klassen Medlemsregister................................. 17 1.8 Grundlæggende regler for kontrakter på klasser................... 19 1.9 Kontrakt for interface Personregister.......................... 20 1.10 Øvelser........................................... 24 2 Datatypen Stack 25 2.1 Kontrakt for interface Stack<T>........................... 29 2.1.1 Proceduren Push................................. 29 2.1.2 Den begrebsmæssige model........................... 30 2.1.3 Specifikationen for proceduren push().................... 33 2.1.4 Funktionen top.................................. 33 2.1.5 Proceduren remove................................ 34 2.1.6 Samlet kontrakt for class Stack<T>...................... 34 I

INDHOLD II 2.1.7 Kildekoden til interface Stack<T>...................... 35 2.1.8 Kontrakter for interface-moduler........................ 36 2.2 Den begrebsmæssige model............................... 37 2.3 Øvelser........................................... 38 3 Uforanderlige sekvenser 39 3.1 Sekvenser......................................... 39 3.2 Repræsentation af sekvenser............................... 42 3.3 Basisfunktionerne..................................... 45 3.3.1 Funktionen Head................................. 45 3.3.2 Funtionen Tail................................... 45 3.3.3 Funktionen isempty().............................. 45 3.4 De afledede funktioner.................................. 46 3.4.1 Funktionen getcount()............................. 46 3.4.2 Funktionen precededby()............................ 46 3.4.3 Funktionen elemat()............................... 47 3.4.4 Funktionen concat()............................... 47 3.4.5 Funktionen equals()............................... 47 3.4.6 Funktionen subsequence()........................... 48 3.5 Afsluttende bemærkninger............................... 48 3.6 Øvelser........................................... 50 4 Datatypen Queue<T> 51 4.1 Kontrakt for proceduren insert()........................... 53 4.2 Kontrakt for proceduren Remove()........................... 54 4.3 Hvad skal vi kontrollere?................................. 54 4.3.1 Statisk check.................................... 55 4.3.2 Dynamisk check................................. 55 4.4 Kontrakt for funktionen getfirst().......................... 55 4.5 Kontrakt for funktionen isempty()........................... 56 4.6 Det endelige design af interface Queue........................ 56 4.7 Kildetekst til interface Queue<T>........................... 58 4.8 Øvelser........................................... 59

INDHOLD III 5 Datatypen Mapping<K,V> 61 5.1 interface Mapping<K,V>................................. 62 5.2 Procedurerne insert(k,v) og remove(k)......................... 63 5.3 Kildeteksten til interface Mapping<K,V>....................... 64 5.4 Øvelser........................................... 65 6 Uforanderlige mængder 66 6.1 Datatypen Set....................................... 66 6.2 Kontrakt for funktionen has().............................. 67 6.3 Kontrakt for plus().................................... 68 6.4 Kildetekst til interface Set<T>.............................. 68 6.5 Øvelser........................................... 69 7 Kontrakter for Subtyper 70 7.1 Open-closed principle (OCP).............................. 70 7.2 Liskovs substitutionsprincip (LSP)........................... 72 7.3 Et gammelt eksempel på brud på LSP......................... 74 7.4 Rektangel og Kvadrat................................... 75 7.5 Kildekode til programmet LiskovTest......................... 81 8 Kontrakter for Systemer 84 8.1 Et rammesystem for designmønstret Observer.................... 84 8.2 Kontrakt for observer-systemet............................. 85 8.2.1 Proceduren Attach................................ 86 8.2.2 Proceduren detach(observer obs)...................... 86 8.2.3 Kontrakt for interface Observer....................... 86 8.3 Kildetekst til et observer-system............................ 88 8.4 Øvelser........................................... 91 9 Løsninger til udvalgte øvelser 92

Introduktion Bogen er beregnet til brug som lærebog på kurset Kontraktbaseret Udvikling på erhvervsakademiernes bacheloruddannelse i Software Udvikling. Bogen indeholder pensum til den del af kurset, som omhandler design af programmoduler baseret på specifikationer. Indholdet er inspireret af Michell og McKims Design by Contract by Example Mitchell and McKim [2002]. Design by Contract er et varemærke, som ejes af Bertrand Meyer, som konstruerede programmeringssproget Eiffel. I Design by Contract by Example anvender Mitchell og McKim programmeringssproget Eiffel, hvor man kan skrive specifikationer direkte i koden. Eiffel udmærker sig ved, at specifikationssproget er simpelt og let forståeligt. I Kontraktbaseret Programmering Thomsen [2014] anvendte jeg en programnotation, som blev introduceret af E. W. Dijkstra blandt andet i bogen A Dicipline of Programming Dijkstra [1976] Dijkstra kaldte notationen Q. I denne notation anvendes operatoren := som tilordningsoperator og ikke = som i Java, C #, C og C ++. Anvendelse af = som tilordningsoperator giver det indtryk, at der er tale om lighed og ikke om en aktivitet. Sætningen int k=7 i Java skal ikke læses k er lig med 7 men k sættes til 7. Brugen af = som tilordningsoperator har konsekvensen, at logisk ækvivalens i boolske udtryk kræver en operator, der ikke kan forveksles med =. Sprogene Java, C #, C og C ++ anvender == til sammenligning af simple værdier og referencer. I notationen Q anvendes := som tilordningsoperator og = til sammenligninger. I Java betyder sætningen boolean p = (x==y); at variablen p får tildelt værdien af x = y. I Q skrives dette boolean p:= (x=y) Notationen i Q er bedre end notationen i Java og de andre ovennævnte sprog. Jeg har derfor overvejet at anvende Q, men indtil videre vil jeg bruge Java. Derved er det muligt at afprøve bogens eksempler uden at skulle oversætte dem fra Q til Java. Specifikationerne (kontrakterne) skrives i specifikationssproget JML. Referencemanualen til JML Leavens and et. al. [2002] er på 196 sider. Et skræmmende omfangsrigt og kompliceret dokument til beskrivelse af specifikationssproget. Det er vigtig, at et specifikationssprog er simpelt, og at beskrivelsen af syntaks og semantik kun fylder få sider. JML s kompleksitet afspejler også, at det er lykkedes at udvide Java, så også Java er blevet en programteknisk Jumbo Jet. 1

INDHOLD 2 De fleste af bogens eksempler anvender generiske typer. Anvendelse af exception er undgået. Specifikationerne skrives i en simpel delmængde af JML, hvor kun følgende nøglebegreber anvendes: pre Q; post R; assignable x; invariant C; JML indholder muligheden for at skrive specifikationer på flere niveauer, kaldet letvægts- og sværvægtsspecifikationer. Desuden kan man i JML specificere normal behaviour og exceptional behaviour. Vi anvender kun letvægtsspecifikationer, idet de er fuldt dækkende for en komplet specifikation. Bogens eksempler benytter ikke kald af exceptions undtagen i de tilfælde, hvor der er tale om en programmeringsfejl, eller hvor Java tvinger programmøren til at bruge exceptions (try-catch), f. eks. ved input/output. Anvendelse af exceptions anser jeg for at være en form for goto-programmering og kan kun medvirke til skrivning af programmer, som er vanskelige at gennemskue. Første kapitel indeholder en præsentation af, hvorledes man udformer og udvikler specifikationer for et spil-program samt at par almindeligt anvendte typer af moduler, der repræsenterer registre (objektsamlinger). Kapitlerne 2 til og med 6 behandler kontrakter for en række abstrakte datatyper. Derefter følger et kapitel, hvor bogen behandler kontrakter for sybtyper. I kapitlet om subtyper gennemgås Liskovs subsitutionsprincip. Bogens sidste kapitel behandler kontrakter for et rammesystem, der realiserer designmønstret Observer. Bogen er udformet, så den kan læses uafhængigt af bogen Kontraktbaseret Programmering.

Kapitel 1 Kontraktbaseret Design På engelsk kaldes emnet for Design by Contract. Begrebet er introduceret af Bertrand Meyer allerede i 1986 i programmeringssproget Eiffel. Sproget Eiffel blev beskrevet i en række artikler og senere i bogen Object Oriented Software Construction. I 2009 udgav Springer Verlag Bertrand Meyers nye bog Touch of Class med undertitlen Learning to Program Well with Object and Contracts. Her finder man en grundig indføring i objektorienteret programmering i Eiffel med brug af specifikationer og løkkeinvarianter, se Thomsen [2014]. Kontraktbaseret Design (KD) er idag et omfattende forskningsområde, og teknikken er begyndt at finde anvendelse i erhvervslivet især på områder, hvor det er af stor betydning at kunne skrive korrekte programmer. Et korrekt program overholder de krav, der stilles til programmets udførelse 1. Disse krav opdeles ofte i flere typer af krav. Det kan være krav til udførelsestid, krav til pladsforbrug under udførelsen og ikke mindst krav til funktionalitet. I KD koncentrerer vi os om de funktionelle krav. Vi beskæftiger os ikke generelt med krav til programmernes effektivitet, dvs. programmernes tids- og pladsforbrug. Alligevel vil vi undertiden skele til effektiviteten, dvs. tids- og pladskompleksiteten. De funktionelle krav vil i den udstrækning, det er muligt og hensigtsmæssigt, blive formuleret som formelle specifikationer. Der findes to måder, hvorpå man kan kontrollere, om et program overholder specifikationerne. Man kan udføre programmet med forskellige input og så kontrollere, at programmets resultater svarer til kravene i specifikationerne. Dette svarer til at udføre test. Hvis specifikationerne er formulerede i et formelt sprog, kan run-time-systemet foretage en automatisk kontrol af programudførelsens resultater. Dette kaldes dynamisk prøvning eller test af programmet. Den anden måde består i at analysere programteksten (kildekoden), og gennemføre et bevis for, at programmet overholder specifikationerne. Denne kontrol kaldes en statisk prøvning, og den kræver ikke, at programmet udføres. En statisk prøvning kan afgøre, om et program er korrekt, dvs. at programmet giver korrekte resultater uanset input. Den dynamiske prøvning kan derimod ikke afgøre korrektheden af et program men blot sandsynliggøre, at programmet ikke indeholder fejl. En test af et program kan kun vise tilstedeværelsen af fejl. En test kan ikke vise fravær af fejl. I bogen Thomsen [2014] gennemgås nogle fremgangsmåder til at konstruere korrekte algoritmer. 1 Det har god mening at definere, hvad der forstås ved et korrekt program. Næsten alle større programmer indeholder fejl, som bevirker, at programmerne ikke er korrekte. De udfører ikke i alle tilfælde den ønskede beregning. 3

KAPITEL 1. KONTRAKTBASERET DESIGN 4 Vi er interesseret i at kunne skrive kontrakter for programsystemer. Hvordan skal sådanne kontrakter udformes? Kan vi skrive en kontrakt, der omfatter et helt program endsige et system af programmer? Svaret er både ja og nej. Det vil være en uoverkommelig og meget kompliceret opgave at formalisere alle funktionelle specifikationer for et system af programmer. Vi kan dog indfange mange væsentlige dele af programmernes funktion gennem formelle specifikationer. 1.1 Specifikationer En specifikation for en algoritme består af tre prædikater (betingelser): en præbetingelse, en postbetingelse og en angivelse af, hvilke variabler, der må ændres af algoritmen (assignable). En specifikation for en procedure har følgende opbygning /*@ pre Q; @ assignable x; @ post R; @*/ void <navn>(<param>); Nøgleordet void angiver i Java, at metoden er en procedure. <navn> er procedurens navn og <param> er listen af parametre. Procedurens krop indeholder den algoritme, som specifikationen vedrører. Metodesignaturen er også en del af specikationen, idet den definerer input til metoden. I java er alle metoder medlemmer i en klasse, og metoderne kan tilgå klassens variabler og i mange tilfælde også variabler i andre klasser. Metoden kan derfor operere på globale variabler. Selv om det er tilladt i Java, er det dårlig programmeringsskik at anvende globale variabler uden for den klasse, hvor metoden er medlem. Nøgleordet pre efterfølges af præbetingelsen i form af prædikatet Q. Præbetingelsen beskriver de programtilstande, i hvilke det er tilladt at kalde proceduren. Programmets variabler skal have værdier, der opfylder Q, hvis man vil kalde proceduren <navn>. Er Q ikke opfyldt, kan kalderen ikke stille krav til funktionens resultat. Procedurens parametre er input til proceduren. Nøgleordet assignable efterfølges af en liste af de variabler, som må ændres af proceduren. Det er underforstået, at ingen andre variabler må ændres af proceduren. I Java anvendes callby-value, hvilket indebærer, at argumenterne til et procedurekald kopieres til lokale variabler i proceduren. Hvis parametrenes værdier ændres af proceduren, ændrer dette ikke på argumenternes værdier. Der er derfor ingen grund til at nævne parametrene i en assignable-sætning. En ændring af parametrene i procedurens krop har ingen virkning på procedurens omgivelser og specielt ikke på objekttilstanden. Man skal altid nævne de globale variabler, der ændres af proceduren, i assignable-sætningen. Nøgleordet post efterfølges af et prædikat, der beskriver procedurens resultat. Proceduren skal, såfremt den er kaldt på legal vis, terminere i en tilstand, hvor postbetingelsen er opfyldt. Det fordres altså, at proceduren faktisk terminerer. Der må ikke være nogen uendelig løkke i procedurens krop. En algoritme er korrekt, hvis og kun hvis følgende er opfyldt:

KAPITEL 1. KONTRAKTBASERET DESIGN 5 Hvis man begynder udførelsen af algoritmen i en tilstand, hvor præbetingelsen er sand, så skal algoritmen terminere i en tilstand, hvor postbetingelsen er sand. Algoritmen må kun ændre værdierne for de variabler, der er nævnt i assignable-listen. Eksempel 1.1. Proceduren /*@ pre x>=0; @ assignable t; @ post t == \old(t)+x; @*/ void inc(int x) Her er x en global variabel, f. eks. en instansvariabel i den klasse, hvor proceduren inc er defineret. En specifikation af en funktion har denne opbygning /*@ pre Q; @ post R; @*/ <returtype> <navn>(<param>); <returtype> er angiver typen af den værdi, som funktionen returnerer. Normalt vil der ikke være nogen assignable i specifikationen, da vi normalt ikke tillader, at funktioner påvirker deres omgivelser. Dette indbærer, at globale variabler kun aflæses. Eksempel 1.2. Specifikation for en funktion: /*@ pre 0<=k && k<b.length; @ post \result == (b[k]%x==0); @*/ boolean gåropi(int[] b, int k, int x); Funktionen undersøger, om x går op i b[k]. Funktionen må kun kaldes, hvis k er et gyldigt indeks i b. 1.2 Spillet NIM Eksemplet nedenfor viser en funktionel specifikation af et spil mellem to spillere. Den ene spiller er en person. Den anden spiller er computeren.

KAPITEL 1. KONTRAKTBASERET DESIGN 6 Eksempel 1.3. Spillet NIM. Spillet NIM er et tændstikspil med to spillere A og B. Spillet består i, at der lægges nogle rækker med tændstikker, f. eks. fire rækker med henholdsvis (3, 6, 5, 8) tændstikker. Man trækker lod om, hvem der skal starte. På skift må hver af spillerne nu fjerne én eller flere tændstikker fra én række efter eget valg. Den spiller, som tager den sidste tændstik, har vundet. En specifikation for et program, der kan spille NIM mod en person, kan udvikles skridt for skridt. I første omgang beskrives programmets startbetingelse og slutbetingelse. Startbetingelsen skal beskrive, at der er n rækker, der hver indeholder en eller flere tændstikker. Dette modellerer vi med en liste, hvor hvert element i listen angiver antallet af tændstikker i den pågældende række. Lad os kalde listen tr. Udtrykket tr(i) angiver da antallet af tændstikker i række nummer i. Der skal være mindst én række tændstikker, når spillet begynder. Dette kan vi beskrive med betingelsen n > 0. At alle rækker skal indeholde mindst én tændstik, kan vi beskrive med: For alle hele tal i, hvor 0 i < n, skal tr(i) > 0. I matematisk notation skriver vi denne betingelse med prædikatet ( i : 0 i < n : tr(i) > 0) Udtrykket person() angiver, hvem der er i trækket. Hvis person() true er det personens tur til at trække tændstikker. Hvis person() f alse er det computerens (programmets) tur til at trække. Vi kan vælge at trække lod om, hvem der skal begynde spillet. I så fald er startbetingelsen for spillet true. Altså at det er uden betydning, hvilken værdi person() har, når spillet begynder. Læg mærke til, at vi anvender en boolsk funktion person() til at markere, hvem der skal trække. Hvis vi havde brugt en variabel, så ville det kræve, at denne variabel var tilgængelig i implementeringen af spillet. Ved at anvende en funktion overlades det til programmøren, hvorledes hvem skal trække skal implementeres. Spillet skal ende i en tilstand, hvor der ikke er flere tændstikker tilbage. Dette kan vi udtrykke ved at skrive, at summen af alle tallene i tr skal være 0. Specifikationen bliver i JML-notation: /*@ pre (\forall int i; 0<=i && i<n; tr(i)>0) && n>0; @ post (\sum int i; 0<=i && i<n; tr(i)==0); @*/ { glovar int n; Program } Præbetingelsen fordrer, at programmet begynder i en tilstand, hvor alle rækker indeholder tændstikker. Postbetingelsen kræver, at det korrekte program ender i en tilstand, hvor alle tændstikker er fjernet. Det er slutværdien af person(), der afgør, hvem der har vundet spillet. Programmet skal ændre på resultatet af funktionen tr() og på resultatet af funktionen person().