Thuis
Contacten

    Hoofdpagina


Hoofdstuk 11. Validatie van programma's

Dovnload 41.11 Kb.

Hoofdstuk 11. Validatie van programma's



Datum13.04.2019
Grootte41.11 Kb.

Dovnload 41.11 Kb.

Hoofdstuk 11.
Validatie van programma's.

In het eerste hoofdstuk van dit deel werd besproken hoe men een programma kan ontwerpen. In de negen volgende hoofdstukken werd getoond hoe men met behulp van de taal Modula 2 een programma ontwerp kan omzetten naar een uitvoerbaar programma. In dit hoofdstuk worden de technieken aangeleerd om de betrouwbaarheid van de programma's te verzekeren.


11.1. Fouten.
Men spreekt van een "computerfout" wanneer het gedrag van een computergestuurd systeem afwijkt van het gewenste. Deze afwijking kan uiteenlopende oorzaken hebben:

  • ten eerste, en dat is zelfs de meest voorkomende situatie, kunnen de specificaties van het systeem foutief of onvolledig zijn.

  • dan is het natuurlijk ook mogelijk dat de hardware van het systeem permanent of, en dat is veel storender, intermitterend defect is.

  • tenslotte kunnen er fouten in de software bestaan. Deze fouten kunnen programmatiefouten in de toepassing zijn of communicatiestoornissen tussen de toepassing en het besturingssysteem of de hardware. Dergelijke communicatiestoornissen zijn vaak het gevolg van kleine verschillen tussen de hardware van verschillende computers of tussen de opeenvolgende versies van besturingssystemen.

In dit hoofdstuk zullen enkel software fouten besproken worden.
Een software fout kan drie verschillende gevolgen hebben:

  • bij syntax fouten in de tekst van het programma zal de compiler weigeren het programa te vertalen en foutmeldingen geven. Dergelijke fouten, die door studenten als bijzonder onaangenaam ervaren worden, zijn, in feite, schadeloos. Het volstaat systematisch de fouten te verbeteren tot de compiler aanvaardt het programma te vertalen.

  • bij uitvoeringsfouten zal de uitvoering van het programma onderbroken worden. Dit kan bv. het geval zijn wanneer er door 0 gedeeld wordt of wanneer er aan een variabele een waarde moet toegekend worden, die niet tot het type van deze variabele behoort. De gevolgen van uitvoeringsfouten hangen sterk af van de context. In een kantooromgeving zal een uitvoeringsfout leiden tot irritatie van de gebruiker, terwijl in bv. een automatische piloot, een uitvoeringsfout zou kunnen leiden tot een catastrofe. De opvang van uitvoeringsfouten dient dan ook aangepast te worden aan de omgeving: foutmelding in een kantooromgeving, doorschuiven van controle naar een andere, onafhankelijke, sturing, daar waar de computer externe processen stuurt.

  • tenslotte kan het programma zich schijnbaar normaal gedragen, maar verkeerde resultaten geven. Dit is ongetwijfeld de gevaarlijkste vorm van fout, vermits de gebruiker, a priori, vertrouwen zal hebben in het systeem.

Moderne software engineerings technieken proberen zoveel mogelijk fouten naar voor te duwen in bovenstaande lijst. Door de programmeur bijvoorbeeld te verplichten alle variabelen te declareren alvorens ze te gebruiken zullen tikfouten in namen van variabelen door de compiler ontdekt worden, eerder dan uitvoeringsfouten of verkeerde resultaten te veroorzaken. Door het gebruik van subrange types zal de toekenning van een verkeerde waarde aan een variabele meestal resulteren in een uitvoeringsfout eerder dan in een verkeerd resultaat.


11.2. Betrouwbaarheid van programma's.
Elke betrouwbare software moet "geschikt" en "robuust" zijn. "Geschikt" betekent dat de software in staat moet zijn alle taken, waarvoor het ontworpen was, aan te kunnen en "robuust" betekent dat het moet kunnen overleven in geval van niet gespecifieerde input. Vooraleer een programma in gebruik wordt genomen, moeten deze twee eigenschappen nagegaan worden. Dit kan gedaan worden ofwel statisch op de tekst van het programma, zonder het uit te voeren, ofwel dynamisch gedurende de uitvoering.

Aangezien programma's meestal zeer complex zijn, is het vrij moeilijk de betrouwbaarheid van volledige programma's in een keer na te gaan en moet men, zoals bij het ontwerpen van een programma, gebruik maken van top-down en bottom-up opsplitsings technieken.


11.2.1. Levens cyclus kwaliteits controle.
Om betrouwbare software te bekomen volstaat het zeker niet enkel een a-posteriori zoektocht naar fouten te doen. De kwaliteit van de software moet gedurende de volledige levens cyclus van een programma vooropgesteld worden, te beginnen vanaf de specificatie fase. Aangezien de technieken om software betrouwbaar te maken reeds vroeger behandeld werden, zullen hier enkel de punten die verband houden met verificatie van bestaande software besproken worden (wat uiteraard niet betekent dat de andere aspekten minder belangrijk zijn).
11.2.2. Statische versus Dynamische validatie technieken.
Over het algemeen wordt de betrouwbaarheid verzekerd door testen, maar het is geweten dat het testen slechts een beperkt vermogen heeft om de betrouwbaarheid van programma's te staven. Inderdaad, voor de meeste programma's zou een uitgebreide test, dwz een test op alle mogelijke combinaties van invoer gegevens, eeuwen duren.

Het testen van programma's kan gebruikt worden om aan te tonen dat er fouten in het programma zijn, maar nooit om te bewijzen dat er geen zijn. Het is dan ook niet verrassend dat reeds vele inspanningen geleverd werden en nog steeds geleverd worden om een alternatief te vinden voor het testen van programma's. Terwijl het testen duidelijk een dynamische techniek is, die het uitvoeren van het programma impliceert, wordt een alternatieve methode voor het testen vooral gezocht langs de kant van het bestuderen van de programma tekst en is daardoor hoofdzakelijk statisch. Het idee om de nadruk te leggen op de statische aspecten vindt waarschijnlijk zijn oorsprong in het standpunt van vele theoretici: Zij aanzien een programma als een mathematische funktie, die uitgaande van de invoer gegevens de overeenstemmende uitvoer gegevens oplevert, en zij wensen geen aandacht te besteden aan de mechanismen van de daarbij betrokken funktie evaluatie.


Een eerste vorm van statische funktie evaluatie kan teruggevonden worden in assemblers en in compilers die syntax fouten detecteren alvorens object code te genereren. Door het niveau van redundantie te verhogen en een nauwkeurig intypen op te leggen, laten moderne hogere talen toe vele fouten tijdens de compilatie te detecteren en beperken alzo de taak van verdere, statische of dynamische, validatie operaties.
11.2.3. Top-down versus Bottom-up validatie.
Het is virtueel onmogelijk de geschiktheid en de robuuustheid van grote programma's te testen, met gelijk welke methode, in een enkele operatie. Ontledingstechnieken zijn vereist om subprogramma's te bekomen die voldoende klein zijn om volledig verstaanbaar te zijn voor de personen die de opdracht hebben de programma's te testen, of, in het geval automatische technieken gebruikt worden (zie verder), om op redelijke tijd behandeld te kunnen worden door de verificatie software.
Een eerste benadering - de bottom-up benadering - bestaat erin eerst de correctheid na te gaan van de subprogramma's die de kleinste details op het laagste niveau behandelen. Daarna moeten deze correcte "bouwstenen" bijeen gebracht worden in grotere programma's, die opnieuw op goed gedrag moeten gecontroleerd worden, enz... tot het gehele programma terug opgebouwd en gecontroleerd is.

Deze benadering is intuïtief zeer aantrekkelijk, aangezien ze bestaat uit het opbouwen van een programma vertrekkend van betrouwbare "bouwstenen"; wanneer het gebruikt wordt voor testen, is de ontwikkeling van speciale testprogramma's, die gebruik maken van de subprogramma's noodzakelijk.

De bottom-up validatie methode heeft één groot nadeel: detail fouten, eenvoudig om te verbeteren, zijn vlug gevonden, maar grotere fouten, zoals deze die het gevolg zijn van misverstanden tussen de auteurs van de verschillende delen van het programma (of zelfs misverstanden tussen de verschillende deelprogramma's van eenzelfde auteur!), en die over het algemeen wijziging van een groot deel van de code inhouden, worden vrij laat ontdekt, zodat veel van het werk dat reeds gedaan werd op lager niveau nutteloos wordt.
De andere benadering - de top-down benadering - bestaat erin eerst het geheel van het programma te controleren, onderstellend dat de subprogramma's correct werken, en zo verder te evolueren naar meer gedetailleerde niveau's tot alles gecontroleerd is. Testen impliceert de ontwikkeling van "peukjes" ter vervanging van subprogramma's, die de argumenten van de subprogramma's testen en die resultaten geven nuttig voor het verder uittesten van de omliggende software.

Niettegenstaande het feit dat deze methode minder intuïtief is en soms meer inspanningen vergt, blijkt de top-down benadering veiliger te zijn, aangezien grote gebreken in de design vrij vlug ontdekt worden op een ogenblik dat het verbeteren ervan nog vrij eenvoudig is.


11.3. Technieken die gebruikt worden voor het valideren van programma's.
Om de semantische correctheid van programma's na te gaan kunnen verschillende, dikwijls complementaire, technieken gebruikt worden. Deze gaan van een min of meer informele lektuur van de programma tekst tot de uitvoering van het programma in een speciale test omgeving.
11.3.1. Manuele controle van de code.
Bureau controle - het programma overlopen zittend aan een bureau - is de meest traditionele manier om een programma te analyseren en vormt de basis voor de meer gedisciplineerde technieken van doorwandelen en controle. Aangezien een auteur van een programma meestal zijn eigen fouten niet vindt, wordt bureau controle bij voorkeur door een andere persoon uitgevoerd. Dit kan leiden tot een informele overeenkomst tussen twee programmeurs die elkaars programma's lezen, of, op een meer formele wijze, voorzien binnen de organisatie van het programmeer team.

Zowel het doorlopen als de controle vereist een formele bijeenkomst van een team van ongeveer vijf mensen, die in staat zijn de software te onderzoeken. In geval van controle zal de auteur van het programma zijn code stap voor stap uitleggen en alle beslissingen staven.

Zijn collega's zullen nagaan of voldaan is aan een vooraf opgestelde lijst van software kwaliteits criteria en aan de software specificaties.

Bij het doorlopen zal het team manueel de uitvoering van het programma simuleren, door gebruik te maken van eenvoudige invoergegevens en door de tussenresultaten op een bord te schrijven. Het is duidelijk dat zulke manuele controles regelmatig moeten gedaan worden gedurende de ontwikkeling van de software, maar het is eveneens duidelijk dat ze niet voldoende zijn om een hoog vertrouwen te verzekeren in de betrouwbaarheid van de software, aangezien het succes van deze manuele methodes vooral afhangt van de goede wil en de bekwaamheid van diegenen die deze methode toepassen.


11.3.2. Data-flow analyse.
In een data-flow analyse wordt elke variabele gemodelleerd door een georiënteerde graf (zie paragraaf 1.3.1), waarin de belangrijke programma modules voorgesteld worden door knooppunten, en de volgorde van gebeurtenissen, gekoppeld aan de uitvoering, door bogen. Een fout wordt ontdekt wanneer een veranderlijke blijkt aangesproken te worden vooraleer er een waarde aan toegekend werd. Een zinloos statement wordt ontdekt wanneer de data-flow grafiek toont dat een waarde toekenning gebeurt, zonder dat die veranderlijke ooit daarna gebruikt wordt. Een data-flow analyse kan manueel uitgevoerd worden, maar er bestaan goede automatische technieken, aangezien deze essentieel zijn bij code optimisatie door compilers. Data-flow analyse is een zeer nuttige techniek voor het controleren van programma's, aangezien het bijdraagt tot de eliminatie van niet-geïnitialiseerde veranderlijken, wat de grootste bron is van wangedrag van programma's, maar dit ook volstaat zeker niet voor het controleren van de betrouwbaarheid van een programma.
11.3.3. Correctheid bewijzen.
Een techniek om formeel te bewijzen dat een programma exact voldoet aan de specificaties, zou uiteraard heel waardevol zijn voor de hele gegevensverwerkende gemeenschap.

De principes van dergelijke techniek werden uitgedacht heel vroeg in de geschiedenis van de computer, door John Von Neumann zelf. Ze worden samengevat door Elspas et al. als volgt: "... een bewijs van de correctheid van programma's kan bekomen worden, ten minste in principe, als de programmeur een beschrijving van de toestandsvector van programma veranderlijken kan leveren of bevestigen na elke stap, of mogelijk enkel na geselecteerde stappen van het programma. Deze toestand, die kan beschouwd worden als een relatie tussen programma veranderlijken op een gegeven ogenblik, kan dan gebruikt worden om het programma te controleren. Het doel van het verificatie proces is te bepalen of de (verwachte) toestand na de eerste stap bevat zit in de initiële toestand en de transformatie uitgevoerd bij de eerste stap, of de toestand na de tweede stap bevat zit in de toestand na de eerste en tweede stap samen enz... en uiteindelijk, of de toestand na alle PRINT of ander output statements bevat zit in de vorige toestand.

Conventionele algebraïsche manipulatie technieken volstaan gewoonlijk om de implicaties bij elke stap te verzekeren. Een inconsistentie op gelijk welk ogenblik duidt aan dat de vorige programma stap fout is of dat de toestand verkeerd was opgevat door de programmeur; in elk geval is de programmeur gewaarschuwd voor een eventuele fout in dat stuk programma."

Deze benadering heeft geleid tot een formele analogie tussen theorema's en programma's, aangezien programma verificatie beschouwd wordt als analoog aan theorema bewijzen, wat logischer wijze resulteert in het geloof dat de correctheid van programma's kan bewezen worden en software betrouwbaarheids problemen kunnen uitgeroeid worden.


Dit geloof is sterk tegengesproken door De Millo et al. die beweren dat formele correctheidsbewijzen het vertrouwen in systemen gebaseerd op grote programma's niet verhogen. Hun argumenten zijn vooral gebaseerd op de onderstelling dat de complexiteit van elk bewijs minstens even groot is als de complexiteit van het programma, met als gevolg dat het bewijzen van de correctheid tot meer fouten kan leiden dan het programmeren zelf. Om deze moeilijkheid te omzeilen werd het gebruik van automatische theorema bewijzers voorgesteld, maar de mogelijkheden van zulke programma's zijn nog steeds grootte-ordes achter op wat nodig is om de correctheid van gelijk welk realistisch groot programma te bewijzen. Bovendien beweren ze dat, aangezien een correctheids bewijs zou moeten bewijzen dat een programma voldoet aan zijn specificaties, elke wijziging aan deze specificaties, zelfs de allerkleinste, de herhaling van de hele bewijs procedure zou vereisen. Aangezien over het algemeen specificaties continu veranderen tijdens de ontwikkeling van software, zou, zelfs indien de automatische theorema-bewijs benadering mogelijk wordt, ze niet erg praktisch zijn, aangezien het bewijzen van theorema's enorme hoeveelheden computertijd vereisen. Als besluit kan men stellen dat in de nabije toekomst de toepasbaarheid van correctheids bewijzen zich zal beperken tot specifieke, relatief kleine, subprogramma's.

Ze kunnen van grote waarde zijn als ingewikkelde algoritmen voor nauwkeurig gedefinieerde problemen moeten gecontroleerd worden, maar ze zullen de last niet verlichten van diegenen die de betrouwbaarheid van systemen, gebaseerd op grote programma's, moeten controleren.


11.3.4. Symbolische uitvoering.
Halverwege tussen statische en dynamische technieken bevindt zich de symbolische uitvoering waarbij de uitvoering gebeurt met symbolische uitdrukkingen ipv met gegevens. Dit vereist uiteraard een speciale interpreter. Aangezien geen gegevenswaarden gekend zijn gedurende de uitvoering, zal elke voorwaardelijke sprong resulteren in twee uitvoeringswegen die moeten gevolgd worden, en willekeurige keuzes zullen moeten gemaakt worden om te beslissen hoeveel iteraties moeten uitgevoerd worden.

Het resultaat van een symbolische uitvoering is een op een boom gelijkende verzameling van symbolische uitdrukkingen, die een verband leggen tussen de verschillende toestanden van het programma en hun invoer voor elke mogelijke weg door de controle structuur van het programma. Symbolische uitvoering wordt vooral gebruikt om alle mogelijke wegen doorheen relatief kleine subprogramma's te ontdekken, wat zeer nuttig kan zijn bij het voorbereiden van gegevens voor test sessies, maar is niet aan te raden voor lange programma's wegens de exponentiële groei van de uitvoer met het aantal voorwaardelijke sprongen.


11.3.5. De testfase.
Aangezien geen enkele techniek beschreven in voorgaande paragrafen voldoende schijnt te zijn om de betrouwbaarheid van programma's te verzekeren, moeten ze steeds aangevuld worden met de intuïtief voor de hand liggende techniek: het testen.
Het testen van een programma houdt in het voorzien van een verzameling van gegevens, het uitvoeren van het programma en het bekijken van de resultaten. De gegevens moeten behoren tot de verzameling van toegelaten gegevens als de test bestemd is om de geschiktheid te controleren, en moeten buiten die verzameling liggen als de robuustheid moet gecontroleerd worden. Als het niet mogelijk is iets betekenisvol te observeren buiten de normale uitvoer resultaten, wordt de procedure over het algemeen bestempeld als "black-box" test, terwijl de "white-box" benaming gebruikt wordt wanneer het mogelijk is de interne toestand van het programma tijdens de uitvoering te volgen. Een white-box test is meer doeltreffend dan een black-box test, aangezien de informatie over het interne van het programma kan helpen bij de keuze van testgegevens, en aangezien het volgen van de uitvoering een beter inzicht kan geven in het gedrag van het programma gedurende de test dan door gewoonweg de normale resultaten te bekijken. Black-box testen vindt men gewoonlijk bij aanvaardbaarheidstesten voor software geleverd in object vorm.

Het belangrijkste probleem bij het testen is de keuze van de gegevens.

Het is duidelijk nutteloos om een uitgebreide test te willen doen, bv testen met alle mogelijke invoer gegevens, toegelaten of niet, en daarom is het nodig een gepaste deelverzameling van invoergegevens te vinden, waarvan de kans groot is dat ze fouten aan het licht brengen. Wanneer de enige beschikbare informatie over het programma de specificaties zijn (slechtste geval van black-box test), kan enkel giswerk over de interne werking van het programma leiden tot een keuze van testgegevens. Als daarentegen de broncode van het programma beschikbaar is, kan de kennis van de organisatie van het programma leiden tot testgegevens. Een minimale vereiste voor testgegevens is dat elk statement van het programma minstens eenmaal moet uitgevoerd worden. In het geval van een white-box test kan dit eenvoudig nagegaan worden, maar bij black-box testen onderstelt dit een goed inzicht in de verschillende methodes die zouden kunnen gebruikt worden in het programma gedurende de testfase.
Voorbeeld:
Wanneer een black-box test moet gedaan worden op een programma dat een tweede graads vergelijking oplost van de vorm ax2+bx+c=0, kan men onderstellen dat er drie mogelijke wegen doorheen het programma zijn: één in geval van positieve discriminant, één voor negatieve discriminant en één voor het geval dat de discriminant 0 is. Aangezien het ontaard geval a=0 zou leiden naar een positieve discriminant en een deling door 0, kan men normaal gezien hopen dat het programma een test doet op a=0. Vier groepen van waarden voor a, b en c, zoals bijvoorbeeld (1,3,2), (1,2,1), (1,1,1) en (0,1,1) schijnen daarom een minimum te zijn om het programma te testen.
11.4. Volgen van een uitvoering.
Het testen van een programma door het volgen van een uitvoering wordt niet enkel gebruikt om de correcte werking van een programma te controleren, maar is eveneens zeer nuttig in het geval de juiste oorzaak van een verkeerde werking moet opgespoord worden, wanneer de interne details moeten verstaanbaar worden voor iemand die nog niet vertrouwd is met het programma, of wanneer software geoptimiseerd moet worden ten einde de uitvoeringssnelheid te verhogen.
11.4.1. De toestands-ruimte.
De uitvoering van een sequentieel programma - een proces - kan best gemodelleerd worden door een baan van een punt doorheen de toestands-ruimte van het proces. De coördinaten van een punt in de toestands-ruimte kunnen onderverdeeld worden in twee groepen: de gegevens groep, die de waarde van alle veranderlijken die tot het proces behoren op een welbepaald moment bevat, en de controle groep, die de plaats teller bevat, evenals de terugkeer adressen van alle actieve procedures. Wanneer veranderlijken dynamisch gecreëerd en vernield worden, of wanneer procedures recursief worden aangeroepen, veranderen de dimensies van de toestands-ruimte eveneens.

Het uitzicht van de toestand van een proces zal verschillend zijn naargelang het niveau van de object code of van de bron code beschouwd wordt.


Op het object of register-transfert niveau, wordt de toestand volledig beschreven door de inhoud van alle geheugen woorden verbonden met het proces. Aangezien in Von Neumann computers de geheugen woorden anonieme bitpatronen bevatten, waarvan de betekenis hoofdzakelijk afhankelijk is van de context, en aangezien er over het algemeen geen eenvoudige relatie bestaat tussen de hardware adressen en de statements in de bron code, zal een programmeur heel wat ontcijferwerk en deducties moeten doen, vooraleer zij/hij een verband zal kunnen leggen tussen wat in de toestands-ruimte te zien is en haar/zijn kennis van het programma.
Op source niveau wordt de toestand weergegeven door de waarden van de programma veranderlijken, door een controle wijzer analoog met de laag niveau programma teller, en door een stack, die de geschiedenis van de procedure activaties bevat. In dit hoog-niveau overzicht van de toestand worden de waarden van de veranderlijken uitgedrukt volgens hun type, komt de waarde van de controle wijzer overeen met een lijnnummer in de broncode, en bevat de procedure activatie stack de namen van de procedures. Er komen geen anonieme bitpatronen noch hardware adressen voor in deze toestands beschrijvingen.
11.4.2. Het volgen van een proces.
Het volgen van een proces is het bekijken van de weg die een proces aflegt doorheen de toestands-ruimte, en eventuele interferenties met dat traject. De opname van een vermoedelijk zeer belangrijke deelverzameling van de toestand bij elke stap van de uitvoering, wordt een trace genoemd. Wanneer het punt, dat een uitvoerings proces aanduidt, een vooraf gedefinieerd domein van de toestand-ruimte binnenkomt, kunnen ofwel enkele elementen van de toestand opgenomen worden, zonder te interfereren met de uitvoering - het vooraf gedefinieerd domein wordt in dit geval een "controlepunt" genoemd -, ofwel kan het proces gestopt worden, - in dit geval zal het woord "breekpunt" gebruikt worden -. Wanneer een proces gestopt wordt aan een breekpunt, kan zijn toestand onderzocht en mogelijk gewijzigd worden, en de uitvoering kan verder gezet worden. Traces en breekpunten blijken zeer doeltreffende gereedschappen te zijn bij het debuggen van programma's, aangezien de programmeur bij het ontwikkelen van het programma een intuïtief zicht heeft op de evolutie van de toestand, of tenminste van een belangrijke deelverzameling van de toestand, en elke afwijking tussen de verwachte en de zichtbare toestanden is een bijzonder goede aanwijzing voor het vinden van fouten.
Het volgen van een uitvoering speelt eveneens een belangrijke rol bij de optimisatie van de software performantie, omdat tijdsbepaalde traces en controlepunten nuttige informatie kunnen geven over de tijd die een processor nodig heeft in verschillende delen van een programma. Zulke informatie kan leiden tot manuele optimisatie en zelfs tot het herschrijven in assembler van kleine maar dikwijls gebruikte delen van een programma.
De toestandsruimte kan gevolgd worden door het invoegen van "write" statements in een programma om na te gaan of zekere delen van het programma worden uitgevoerd of niet, of om de waarde van een gegeven veranderlijke, die verdacht wordt van foutief te zijn, te controleren.
Gebruik makend van debuggers kunnen controle punten en breekpunten in programma's ingelast worden, en kunnen traces bekomen worden, zonder dat er "write" statements manueel moeten ingevoegd worden. Laag niveau debuggers bieden de mogelijkheid de laag niveau toestand van een programma te bekijken, en ermee te interageren, terwijl hoog niveau debuggers toegang geven tot de hoog niveau toestand, die uiteraard meer informatie bevat voor de programmeur.
11.5. Bibliografie.
Philip Gilbert, Software design and development, Science Research Associates, 1983.

ISBN 0-574-21430-5

Software Engineering, J.C.van Vliet, H.E,Stenfert Kroese, 1984

ISBN 90-207-1298-5



J.Tiberghien - Informatica - Afgedrukt op: 10/04/2019 -

Deel 2, Hoofdstuk 11, pag.




  • 11.1. Fouten.
  • 11.2. Betrouwbaarheid van programmas.
  • 11.3. Technieken die gebruikt worden voor het valideren van programmas.
  • 11.4. Volgen van een uitvoering.
  • 11.5. Bibliografie.

  • Dovnload 41.11 Kb.