1 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H12: Ontwikkelingsmodellen en bedrijfsculturen Voor grote projecten hebben we moeten we meer gesofisticeerde modellen gebruiken dan voor kleine projecten. Waarom? - - Een groot project kan uit verschillende delen bestaan, die elk vrij autonoom gerealiseerd kunnen worden eenmaal de koppeling tussen de verschillende delen bepaald is (parallell werken aan verschillende modules is iets waar de eenvoudigere modellen zich niet mee bezig hielden) Het komt bij grote projecten vaker voor dat men tijdens de ontwikkeling van het project terug moet gaan naar voorgaande fasen (goede oplossingen worden dan pas duidelijk, nieuwe problemen komen boven, specificaties veranderen, ...) De vijf fasen van ontwikkeling komen altijd in de modellen voor, hoewel ze niet altijd gescheiden zijn. De verschillende modellen hebben allen hun voor- en nadelen. Welke het meest gepast is hangt af van de aard van het project, en de organisatie waarin het gebruikt gaat worden. Ontwikkelingsmodellen geven aan wat de opeenvolging is van de taken die gedaan moeten worden in het ontwikkelingsproces, en wat het eindresultaat moet zijn van elke taak opdat de volgende taken kunnen worden uitgevoerd. De bedrijfscultuur beschrijft de manier waarop die taken worden uitgevoerd. Dit gaat van de takenverdeling (wie doet wat?) tot de naamgeving van variabelen en de vorm van bepaalde formulieren zoals CRC-kaarten. Er moet wel degelijk nog een zekere flexibiliteit zijn, omdat er nog steeds problemen opduiken die noodzaken van het strikte model af te wijken. Lineaire modellen Het cascademodel Het basisidee is hier dat elke fase volledig afgewerkt moet zijn voor men aan een volgende kan beginnen. Natuurlijk lukt dit niet altijd volledig, op elk moment kan men fouten en onvolledigheden vinden in het resultaat van voorgaande fasen. De stippellijnen geven aan dat er een (ongewenste) terugkoppeling is: men moet een vorige fase gedeeltelijk herdoen. Het cascademodel is geschikt voor kleine projecten waar de verschillende fasen niet verder opgesplitst moeten worden. Voor grotere projecten is er een probleem: de fasen zijn dan zo groot geworden dat ze niet meer overzichtelijk zijn. Bovendien weet men pas dat men een goed resultaat heeft, op het einde van de invoeringsfase. Het spiraalmodel Zeer veel projecten worden nooit afgewerkt. Dit kan komen doordat er een beter pakket op de markt kwam, belangrijke medewerkers die veranderen van werk, doordat men interesse in het project verliest, 2 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) enz. Het is dan ook belangrijk om zo vroeg mogelijk in de ontwikkeling te beseffen dat het project tot niets zal leiden, om welke reden dan ook. Op die manier kan men de schade beperken door het project stop te zetten. Deze overweging heeft geleid tot het spiraalmodel. Elk van de fasen van het cascademodel wordt nu opgesplitst in verschillende deelfasen: - - Eerst worden de doelstellingen voor elke fase opgemaakt: wat moet er gebeuren, en vooral, hoeveel middelen zijn er nodig? Essentieel en nieuw is de risicoanalyse. Men probeert de te verwachten kosten voor de rest van het project af te wegen tegen de baten. Vooral probeert men te voorkomen dat men een verkeerd product aflevert. Vaak maakt men hiervoor prototypes. De eigenlijke uitwerking Als laatste is er de verificatie en het testen. Nagaan in hoeverre de doelstellingen voldaan zijn van deze fase, en de fouten eruit proberen halen. Het spiraalmodel is wel degelijk een lineair model, en dus geschikt voor projecten van dezelfde grootte als die van het cascademodel, zijnde kleine projecten. De risicoanalyse is nuttig in omstandigheden waar het risico groot kan zijn, zoals een snel veranderende bedrijfsomgeving of, bij commerciele producten, een snel veranderende markt. Parallelle modellen Bij grote projecten is elke fase zo omvangrijk dat ze niet in één keer kan worden afgewerkt, en dus moet worden opgesplitst. De oplossingen hiervoor worden meestal opgedeeld in parallelle methodes en iteratieve methodes. Parallelle uitwerking Bij de behoefteanalyse kan nog niet worden opgesplitst, maar wel bij de specificatiefase. Het systeem wordt opgesplitst in verschillende modules en de interfaces tussen deze modules worden duidelijk gespecifieerd. In het meest simpele parallelle model worden deze verschillende modules dan apart ontwikkeld, bij het invoeren worden ze dan samengevoegd. Het grootste nadeel is hier dat het kan voorkomen dat bij de ontwikkeling van een module men de interface met een andere module wilt veranderen (fouten in het ontwerp, veranderde eisen, ..) In de praktijk gaat men dan vaak synchroniseren: de verschillende ontwikkelingsgroepen komen op gezette tijden samen om eventuele wijzingen te bespreken. Iteratieve modellen Hier gaat men verschillende versies van het product maken (=builds). Een eerste model is het zogenaamde Build&Fix. Dit is een model dat per ongeluk gebruikt wordt: men gaat ervan uit alles wel in een keer zal werken, en probeert het product zonder veel planning in elkaar te steken. Dit lukt in de praktijk niet en men moet dan veelvuldig terugkeren naar de (dure) reparatiefase via de stippellijnen. Het is een model dat moet vermeden worden, maar in de praktijk erg populair is. 3 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Een werkelijk iteratief model is het incrementeel model, dat een belangrijk nadeel van lineaire en parallelle modellen opvangt. Bij de vorige modellen kan men een systeem pas aan het werk zetten als het werk volledig gedaan is. Dit heeft als nadelen dat het weinig motiverend is voor de ontwikkelingsploeg, en dat de klant weinig vooruitgang ziet. Men gaat hier echter verschillende versies van het systeem plannen. Elke versie is een uitbreiding van de vorige met meer functies, beter gebruiksgemak, enz. Bij het realiseren van een versie houdt men wel al rekening met de geplande uitbreidingen, zodat het systeem niet van de grond af moet worden opgebouwd bij een volgende versie. Bedrijfsculturen Er zijn een aantal methodes om een of meer van de verschillende fasen van de ontwikkeling vlotter en efficiënter te doen verlopen. De meesten kunnen met eender welk ontwikkelingsmodel gecombineerd worden, maar sommige combinaties zijn minder passend dan anderen. Rapid Prototyping Men gaat reeds in de specificatiefase een (min of meer) werkende versie maken van het product: het snelle prototype. Het voldoet aan geen enkele kwaliteitseis zoals foutafhandeling, herbruikbaarheid enz, maar heeft als functie te laten zien hoe het systeem zou werken. Er hoort in feite ook een handleiding bij, deze zou immers gelijk moeten zijn aan deze voor het uiteindelijke systeem. Het is duidelijk vooral geschikt voor systemen met een uitgebreide interactie tussen gebruiker en systeem. Om te voorkomen dat men vervalt in een Build&Fix model, maakt men vaak het prototype in een andere taal dan het uiteindelijke systeem. Kwaliteitsbeheer In een goed georganiseerd bedrijf probeert men niet alleen om de kwaliteit van het product zo goed mogelijk te maken, maar ook om het productieproces zo efficiënt mogelijk te maken. De twee belangrijkste modellen hiervoor zijn CMM (Capability Maturity Model) en ISO-9000(en verder) Bij CMM zijn er 5 niveau’s waarop een bedrijf kan werken. Op de laagste is er weinig organisatie en worden problemen aangepakt als ze zich voordoen. Planning is niet erg betrouwbaar, budgetten en tijdslimieten worden dikwijls overschreden. Het succes van projecten is erg persoonsgebonden. De meeste bedrijven werken op dit niveau. Op het hoogste niveau is er een grote controle. Door het invoeren van meetmethodes (zoals statistische analyse van limietoverschrijdingen en meting van productiekwaliteit) krijgt men een goed zicht op de werking van het bedrijf. Men leert van het verleden en probeert herhaling van bepaalde problemen te vermijden door de oorzaken op te zoeken en deze weg te werken. Men heeft ook aandacht voor de nodige opleiding van personeel. eXtreme Programming Men gaat ervan uit dat de werknemer zich goed moet voelen om goed werk af te leveren. Zo is een van de regels dat overwerk maar heel uitzonderlijk mag voorkomen, met een maximum van 2 keer per jaar 4 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) gedurende telkens een week. Nog eigenschappen: - - Veel aandacht wordt besteed aan leuke termen voor alles (playing the planning game=analyse, user stories=taken, etc) Communicatie is belangrijk: men werkt altijd per 2, zonder vaste partners De code is eigendom van iedereen en iedereen mag ze veranderen (goede afspreken voor naamgeving ed!). Zo leren alle mensen de code goed kennen zodat personeelsverloop geen nefaste gevolgen meer heeft. Implementatie gebeurt story per story(=>iteratief), waarbij geen rekening mag gehouden worden met later in te brengen stories (oppassen, niet naar Build&Fix gaan!) Testen speelt een zeer belangrijke rol, het hele systeem wordt voortdurend getest De klant moet continu beschikbaar zijn om het reeds ontstande systeem te beoordelen en om aan te geven of de nog niet geïmplementeerde stories moeten veranderd worden. Dit kan allemaal werken, zolang er geen delen zijn waarvoor specialisten nodig zijn. Ook wordt de documentatie soms verwaarloosd, aangezien de meeste informatie mond-aan-mond wordt overgebracht. Hulpmiddelen Er bestaan natuurlijk programma’s om het project te begeleiden. Centraal voor analyse staat het CASEprogramma (Computer Aided System Engineering). CASE CASE is de benaming voor pragrammas die het softwareontwikkelingsproces begeleiden. IDE (Integrated Development Environment) is dit dus niet. Een volledige CASE-suite assisteert bij het realiseren van een project van de eerste tot de laatste fase. Centraal staat het zogenaamde repository, waarin op een gestructureerde manier alle analyseelementen worden opgeslagen. Zo kan een CASE-tool UML diagrammen op twee manieren opslaan: visueel als diagram, en abstract in de vorm van grafen. CASE wordt opgedeeld in upper- en lowercase. De belangrijkste taken van upper zijn: - Het ordenen van analysegegevens bij het ingeven. Het verrichten van bepaalde consistentiecontroles. Het genereren van analyserapporten Het lowercase helpt door het genereren van code, zoals headers van klassedefinities in C++. 5 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Versiebeheer Als verschillende mensen aan een project werken, moeten ze allemaal aan verschillende modules kunnen, al is het maar om er andere te testen. Bijgevolg moeten ze centraal bewaard worden, maar krijgen we te maken met het updatingsprobleem. Hiervoor worden drie technieken gebruikt: - - Voor elke module wordt een verantwoordelijke aangesteld. Vindt een andere het nodig dat er iets wordt aangepast, moet dit gemeld worden aan die verantwoordelijke. Dit is veilig maar in de praktijk erg omslachtig. Voor open-sourceprojecten en voor XP programming is dit niet gewenst. Vergrendeling (locking) wanneer een programmeur een module heeft afgehaald. Als de programmeur de versie niet terugzet zal deze eeuwig locked blijven staan => problemen. Parallelle wijzingen (concurrent versioning). Het basisidee is dat als een programmeur een gewijzigde module terugzet, de huidige versie in het centrale depot vergeleken wordt met de versie die die programmeur had afgehaald. Als er verschillen zijn, heeft iemand anders wijzingen aangebracht, en dienen alle wijzingen samengevoegd te worden. Projectbeheersysteem Bij een grotere informatica-afdeling is met met meerdere projecten tegelijk bezig, en dit met verschillende mensen. Men dient dan bij te houden welk project in welke fase zit, wie aan dat project werkt, hoeveel werkuren er aan dat project besteed zijn, enz. Elke werknemer moet weten welke taken hij heeft toegewezen gekregen, en wat de prioriteit ervan is. Hiervoor wordt, zoals bij andere productieprocessen, een of andere vorm van MIS (Management Information System) gebruikt, dat al deze gegevens bijhoudt. 6 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H13: Aanvullingen bij UML Takendiagram Bij het analyseren van een systeem is het niet altijd duidelijk waar we de grens moeten leggen van het systeem zelf. Vaak hebben we, zeker bij administratieve systemen, twee opvattingen: - Het omvattende model: een administratieve afdeling wordt in zijn geheel als een systeem beschouwd (maximale opvatting). Het informaticasysteem (programmatuur+apparatuur) wordt als systeem beschouwd (minimale opvatting). In de eerste opvatting horen de personeelsleden bij het systeem. In de tweede opvatting zijn zij de voornaamste (en vaak enige) actoren van het systeem. Er zijn verchillende soorten van taken, grosso modo zijn er twee vormen: - Een opdracht aan het systeem: deze gaat uit van een actor. Hij is de initiator van de taak, hij zet ze in gang. Vaak is hij ook de benificient. Een opdracht ten voordele van het systeem. In dit geval is de actor zeker niet de benificiënt, maar eerder het systeem zelf (moest dat mogelijk zijn). Eigenlijk gaat het voordeel naar een andere actor. Het initiatief voor een dergelijke taak kan zowel bij de actor als bij het systeem liggen. Samenvattend van al het gedoe in het boek: - - Als het initiatief voor een taak van buiten het systeem komt wordt alsactor de initiatiefnemer vermeld. Een personeelslid wordt dus in het takendiagram niet vermeld als hij bij de taak betrokken is maar ze niet in gang zet. De taak kan zowel een doel buiten als binnen het systeem hebben. Als het intiatief uitgaat van het systeem wordt steeds het direct betrokken object (of algemener, de module) als actor vermeld. Klassendiagram Associatieklassen Soms heeft een associatie tussen twee klassen zelf een aantal attributen. Deze kunnen dan opgenomen worden in een associatieklasse. Deze wordt aangeduid in het klassenmodel als een rechthoek bij de associatielijn. Het zal meestal van de smaak van de opsteller afhangen of hij gewone klassen dan wel associatieklassen gebruikt. Een associatieklasse kan, bij een goed ontwerp, behalve de get- en setoperaties geen operaties hebben. Immers, een associatie dient om berichten door te sturen, en kan dus zelf geen ebrichten ontvangen en 7 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) het is niet de bedoeling dat ze actief iets gaat uitvoeren. Ze heeft ook geen naam: de naam is die van de associatie waar ze bij hoort. Aggregatie en associatie We spreken van een aggregatie als een object deel uitmaakt van een ander object. Een object kan niet rechtstreeks deel uitmaken van twee andere objecten (strict gezien, indien wel is het beter met een associatie ipv een aggregatie te werken). Wel kan een object dat uit andere objecten bestaat, weer deel uitmaken van een ander object. Het geheel van aggregatierelaties van objecten is dus een boomstructuur (of meerdere bomen: er moet geen allesomvattend object zijn). Alleen op het hoogste niveau is er maar één object: het systeem zelf. Het is niet altijd 100% duidelijk of het gaat om aggregatie. Een belangrijk kenmerk is hier dat wie wijzigingen aanbrengt aan een deel, ook het geheel wijzigt. Maar sluitend is dit niet. Het is best mogelijk dat de ene analist iets ziet als een aggregatie en de andere niet, en dat toch beiden bruikbaar zijn. Implementatie van aggregatie C++: het omvattende object geven we een gegevensveld dat een instantiatie is van de omvattende class. De integriteit van de aggregatie wordt zo beschermd (je kan het deel niet veranderen zonder het geheel te veranderen) Java: Integriteit wordt niet beschermd. C#: een struct gedraagt zich hier als een C++-klasse, een class als een Javaklasse (wat aggregatie betreft) Sequentiediagram Het is niet altijd zo dat een taak bestaat uit een simpele opeenvolging van berichten. Er zijn in UML dan ook een aantal mogelijkheden voorzien om bijzondere gebeurtenissen aan te duiden. Creatie en vernietiging van objecten Creatie wordt aangeduid door de rechthoek van het object niet bovenaan te plaatsen, maar op het moment van creatie. Het vernietigen van een object gebeurt dan door een kruis te zetten op de juiste plaats. Uiteraard loopt dan de gestippelde lijn niet meer verder door. Tijdsafhankelijkheid Vaak is er een maximale tijd waarin een taak moet volbracht worden, of moet een taak uitgevoerd worden op of voor een bepaald tijdstip (vaak bij netwerktoepassingen). Dit wordt aangeduid door letters te plaatsen in het diagram, en een voorwaarde in de marge bij te schrijven. Voorwaarde en opsplitsing De voorwaardelijke verzending van een bericht wordt aangeduid door een wachter. Deze wordt in het diagram aangeduid dooreen voorwaarde bij de pijl, ook nu weer geschreven tussen vierkante haken. Dit soort opsplitsing is niet te verwarrend met parallellisme. Bij parallellisme kunnen er twee of meer objecten tegelijkertijd aan de uitvoering van een deeltaak bezig zijn. 8 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Parallellisme kan optreden in drie gevallen: - Een object stuurt een boodschap naar verschillende objecten. Een actor introduceert een nieuwe lijn. Een object stuurt een asynchrone boodscap. Meervoudige objecten Soms is het nodig om meerdere objecten van eenzelfde klasse aan te spreken (vaak in databanktoepassingen). We lossen dit op door in ons sequentiediagram een multiobject te tekenen: de tweede rechthoek achter de eerste suggereert dat het over meerdere objecten gaat. Men moet dan wel in het woordenboek aangeven welke objecten worden vertegenwoordigd Activiteitsdiagrammen Een activiteitsdiagram geeft aan welke activiteit binnen een object doorgaat en geeft ook de coordinatie tussen verschillende taken aan. De verschillende elementen zijn: - - - De activiteiten van een bepaald object, worden geplaatst in een rechthoek met linksboven de naam van het object. Een activiteit is een afgeronde rechthoek. Hierin wordt een korte beschrijving geplaatst. Overgangen worden aangeduid met pijlen. Men probeert er voor te zorgen dat de pijlen van linksboven naar rechtsonder gaan. Een synchronisatiebalk, voorgesteld als een dikke horizontale lijn. Bovenaan kunnen pijlen uit verschillende activiteiten toekomen: dit betekent dat het object wacht tot al deze activiteiten zijn afgewerkt. Als er verschillende activiteiten onder de balk vertrekken betekent dit dat deze allen tegelijk, dus parallel, kunnen beginnen. Ze kunnen ook gewoon achter elkaar uitgevoerd worden. Er zijn beslissingen en voorwaardelijke overgangen. Naast de wachters die we op een overgang kunnen plaatsen hebben we ook een beslissingsruit. (vb zie p. 160) Statendiagram In een statendiagram kunnen we aangeven welke staten mogelijk zijn, en hoe en waarom een object van staat verandert. Maar we kunnen meer doen: zo kan een object overgaan naar de staat waarin het zich bevond, wat het mogelijk maakt om lussen te beschrijven. Maar binnen elke staat kunnen we ook de activiteit van het object beschrijven op een gedetailleerde manier (dus niet alleen door acties bij de overgangspijlen). Hiertoe deelt men de statenrechthoek in twee delen: in het bovenste vakje komt de naam van de staat, onderaan de acties. Hier gebruikt men de gereserveerde woorden entry voor de acties bij het binnenkomen en exit voor het verlaten van de staat. (vb p.161) Men kan deze beschrijving zeer uitgebreid maken, zodanig dat het statendiagram meer op een activiteitsdiagram begint te lijken: men kan synchronisatiebalken en beslissingsruiten toevoegen. Verder gaan we hier niet op in (niet ik, het boek zegt dat). 9 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Samenwerkingsdiagrammen In principe bevat een samenwerkingsdiagram dezelfde informatie als een sequentiediagram. Het legt echter meer de nadruk op de objecten die betrokken zijn de taak, en minder op het tijdsverloop, hoewel alle informatie wel aanwezig is. Maar hoe duiden we an wie op een gegeven moment actief is, en wie controle heeft? Dit gebeurt door nummering. Om de volgorde op een samenwerkingsdiagram aan te duiden gaan we elk bericht van een nummer voorzien. Dit is geen doorlopende nummering, maar een met verschillende niveau’s. Hiervoor worden de volgende regels gebruikt: - De startboodschap heeft een leeg nummer. Als we een extra activiteitsniveau creeren, krijgen nieuwe boodschappen een nummer met een extra indeling. Het prefix van het nieuwe nummer is het nummer van de boodschap die controle doorgaf, het postfix is het nummer van de boodschap op dat niveau. Vergelijken we een eenvoudig sequentiediagram met een samenwerkingsdiagram, dan zien we dat op het tweede de samenhang tussen de verschillende objecten duidelijker naar voor komt dan op het eerste (vb zie p. 163 ev). Merk op dat we de nummers ook mogen vermelden op een sequentiediagram, maar dat ze daar niet veel informatie opleveren. Als alle boodschappen synchroon zijn (automatisch het geval bij programma’s in talen zoals C++) kunnen we het volledige sequentiediagram afleiden uit het samenwerkingsdiagram. Bij asynchrone boodschappen echter ontstaat verwarring. Bovendien kunnen we op een sequentiediagram de creatie en de vernietiging van objecten aanduiden. Op een samenwerkingsdiagram komt dit niet zo tot uiting We kunnen dit aanduiden op een statendiagram. samenwerkingsdiagram+statendiagram=sequentiediagram. 10 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H14: Ontwikkeling van grote systemen Uitgebreide behoefteanalyse Het uitgangspunt is meestal een probleembeschrijving door de potentiële klant. Deze is meestal niet erg gestructureerd, en onvolledig, zodat ze moet aangevuld worden in samenwerking met de klant. Meestal zijn de probleempunten van dezelfde aard: - Vaak ontbreken er vereisten. Dit kan zijn omdat de klant ze vergeten is, of omdat de klant ze evident vindt. Vaak is het niet duidelijk wat de klant bedoelt met bepaalde verzoeken. Soms spreken sommige vereisten elkaar tegen. Soms wil de klant te veel. Hij wil taken laten uitvoeren die te duur zijn of geheel onmogelijk, of onderschat de nodige discipline en inspanning die nodig zijn voor het invoeren en op peil houden van informatie. Hier is het garbage in, garbage out principe van toepassing. Het komt erop neer dat het doel niet is om vast te stellen wat de klant denkt dat hij nodig heeft, maar wel om vast te stellen wat hij nodig heeft. Vaak wordt er een voorontwerp gemaakt dat als basis dient voor het contract. Dit voorontwerp is niet gedetailleerd, maar maakt een schatting van kostprijs en werktijd makkelijker. - De klant stuurt een probleembeschrijving naar de potentiële ontwerper. In 1 of meerdere gesprekken wordt de beschrijving verduidelijkt. De ontwerper maakt een offerte met de verwachtingen van de klant en de leveringen van de ontwerper. Problemen bij het ontwerp van het takenmodel De meest voorkomende fouten vallen in twee categorieën: 1. Gebrek aan volledigheid Als we eerst de actoren identificeren, kan het zijn dat we een aantal taken vergeten. Dit kan zijn - omdat een taak niet bij een actor hoort - of omdat een taak een dienst aan het systeem is, die pas opgemerkt wordt als andere taken verder uitgewerkt worden Bij het eerste ligt het probleem vaak bij het feit dat de beneficiënt van de taak iemand anders is dan de initiatiefnemer. Het tweede kan men vaak oplossen door eerst een takenmodel op te stellen dat alleen de opdrachten aan het systeem omvat, en niet de taken die van het systeem uitgaan. Men probeert dan deze laatste taken af te leiden uit de eerste. 11 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) 2. Gebrek aan objectgerichtheid Indien men het takenmodel ontwerpt los van het klassenmodel kan het zo zijn dat de taken zo geformuleerd worden dat ze moeilijk te implementeren zijn. Men gaat hiertoe een iteratieve methode toepassen. Op basis van een eerste inventaris gaat men een voorlopig klassenmodel opmaken. Op basis hiervan gaat men iteratief een systematische lijst van taken opmaken, en deze lijst uitbreiden, aanpassen en verfijnen. - Uitbreiding: resterende taken toevoegen aan het model - Aanpassingen: de taken formuleren in termen van de klasse. - Verfijnen: in detail nagaan wat de taak nodig heeft. Het klassenmodel kan eventueel aangepast worden. Verdere indelingen In het eenvoudige ontwikkelingsmodel werd de structuur van het te ontwikkelen systeem gekopieerd van het model van de realiteit: dit gaf een indeling in klassen. Voor grote systemen zijn er twee problemen met dergelijke indeling: 1. De indeling in klassen wordt onoverzichtelijk. 2. Bij een groot systeem zijn er specifieke informatica-elementen die geen reflectie zijn van structuren uit de realiteit. Dit geldt vooral voor hardware. Indelen in grotere gehelen heeft verscheidene doeleinden. - Een beter overzicht. Bij niet-lineaire ontwikkelingsmodellen moet het systeem opgesplitst worden in verscheidene delen. Deze indeling gebeurt niet op klassenniveau. Het verdelen van software-elementen over hardware. Er is mogelijk een samenwerking tussen verschillende computers, waarbij men moet aangeven welke software op welke hardware terecht komt. Vandaar dat we niet zomaar beginnen ontwerpen op klassenniveau: klassen bevinden zich bij grote systemen al op een vrij diep niveau, en eerst moet de globale structuur worden opgebouwd. Eenmaal we op het niveau van klassen zijn aangekomen, verloopt het design en de implementatie vrijwel gelijklopend met wat in het eerste deel van het boek beschreven is. Pakketten en deelsystemen Een pakket is een verzameling van modelelementen, dwz van onderdelen van het statische en dynamische model die we al gezien hebben, of nog te bespreken onderdelen. Gewoonlijk beperken we ons tot klassen of tot gehelen van hard- en software. Pakketten kunnen niet alleen klassen, maar ook andere pakketten bevatten, zodanig dat een indeling op verschillende niveaus ontstaat. 12 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Met deze pakketten kunnen we nu een veralgemening van een klassendiagram maken, waarop we de relaties tussen de verschillende pakketten aangeven (zie vb p. 171) In de schematische voorstelling van een pakket geven we aan welke elementen deel uitmaken van dat pakket, maar zonder details van wat we er mee kunnen doen. Vergelijk het met een klasse waarvan we wel de attributen kennen, maar geen operaties. Daarvoor hebben we een speciale vorm van pakketten: het deelsysteem. Een deelsysteem is een deel van het systeem, met zijn eigen gedrag. Bij de voorstelling wordt de grote rechthoek van het pakket in twee verdeeld. Links wordt het gedrag beschreven, waarbij bovenaan plaats is voor de operaties, en onderaan plaats is voor het specificatiedeel dat aangeeft hoe de contacten met de buitenwereld verlopen in de vorm van een takenlijst (vb zie p. 172). Rechts is het realisatiedeel, dat aangeeft welke elementen de specificatie ondersteunen. Dit laatste komt overeen met pakketten. Specificatie- en realisatiedeel hebben een hoofding om verwarring te vermijden, de operatielijst niet. Deelsystemen kunnen andere deelsystemen bevatten, maar elk deelsysteem kan rechtstreeks slechts van één (deel)systeem deel uitmaken. Het ontplooiingsdiagram Als we gaan kijken naar ons uiteindelijke systeem zullen we te doen hebben met code en gegevens, die fysisch aanwezig zijn op apparatuur. Hiervoor hebben we uiteindelijk het ontplooiingsdiagram dat uit twee lagen bestaat. De eerste laag beschrijft de hardware: welke apparatuur aanwezig is, en wat de verbindingen zijn. De tweede laag beschrijft de verdeling van de code en de gegevens over de hardware-elementen. Het ‘zachte’ deel van het systeem wordt voorgesteld door componenten. Het is een samenhangend geheel van software (in de betekenis van code en gegevens), dat zich op één machine bevind, waarbij het wel mogelijk is dat op een machine verschillende componenten van een systeem aanwezig zijn. Het is meestal nuttig om ervoor te zorgen dat een component de realisatie is van een deelsysteem, zodat beide indelingen overeenkomen. Een toestel wordt op een ontplooiingsdiagram voorgesteld door een kubus, een component door een rechthoek met links twee kleine rechthoekjes. De volledige naam wordt geschreven zoals de volledige naam van een object, met een instantienaam gevolgd door een dubbele punt en dan een soortaanduiding. In het ontplooiingsdiagram worden de componenten op het symbool van de machine geplaatst waarop ze terecht moeten komen. Tussen de toestellen worden lijnen geplaatst die aangeven dat er een fysische verbinding is, met een stereotype dat aangeeft welk type verbinding het is. Ook tussen componenten kunnen verbindingen bestaan. Een pijl geeft aan welke component op andere componenten steunt (vb zie p. 174). 13 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Verdelen in deelsystemen Een groot systeem moet dus worden onderverdeeld in deelsystemen, met als doel het overzichtelijk te maken, en niet-lineaire ontwikkelingsmethodes mogelijk te maken. Elk deelsysteem moet logisch samenhangend zijn, en een zo klein mogelijke grens met de rest van de wereld bezitten. De samenhang van een deelsysteem kan bepaald worden door een logische samenhang die uit het systeemmodel volgt, of door gelijkaardige functionaliteit, enz. Bijv: een informaticasysteem dat wordt opgedeeld in twee delen: gebruikersadministratie en het catalogusbeheer. In dit geval is er een logische samenhang tussen de twee deelmodules. Het voordeel is hier dat de interface tussen de twee zeer beperkt is, er moeten enkel verbindingen gelegd worden tussen de gebruikers en hun uitgeleende boeken. Een tweede mogelijkheid voor opdeling is in het databankontwerp en de gebruikersprogramma’s (zoals het programma voor de computer van de uitleenbalie). In dit geval is er een functionele samenhang binnen de twee deelmodules. Dit heeft als voordeel dat elke ontwerper soortgelijke delen krijgt en een specialist kan zijn in de gebruikte hulpmiddelen, zoals een DBMS versus een GUI. De relatie tussen deelsystemen kan op een asymmetrische wijze gebeuren, of een symmetrische: - Asymmetrisch: client-server relatie, flexibel systeem: wijzigingen in de client gebeuren onafhankelijk van de server Symmetrisch: peer-to-peer relatie, meer mogelijkheid tot interactie maar complexere communicatie. De regel is dus: asymmetrisch waar het kan, symmetrisch waar het moet. Gelaagde systemen Een bijzonder type van client-server relatie is dat van de lagen in een gelaagd systeem. Hier gaat de kennis maar in één richting: een laag kent wel de onderliggend laag (of lagen), maar heeft geen weet van bovenliggende lagen. We hebben 2 soorten gelaagde systemen: - - Open systeem: laat toe dat een laag verbinding zoekt met alle onderliggend lagen. Dit geeft grotere efficiëntie maar maakt het minder flexibel. Aanpassing aan een laag moet dan doorgevoerd worden naar alle bovenliggende lagen. Gesloten: laat enkel contact toe met de direct onderliggende laag Systeemarchitectuur Het is nodig dat aan elk deelsysteem de nodige hulpmiddelen moeten worden toegekend, zowel wat apparatuur als wat programmatuur betreft. Dit verloopt in drie stappen: 1. Typeren van hulpsoftware (ontwikkelingssoftware zoals compilers, ondersteuningssoftware zoals DBMS, functionele software die een gedeelte van de taken van het systeem al uitvoert) 2. Inventaris van randapparatuur 3. Keuze van basisapparatuur, en definitieve keuze van (1) en (2), op zo’n manier dat alles op elkaar afgesteld is. 14 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Bij elk van deze stappen zal men een afweging moeten maken tussen het behoud van het bestaande, en vernieuwing. Het typeren van hulpsoftware, kan dit gaan om: - Ontwikkelingssoftware: compilers, … Ondersteuningssoftware: DBMS, … Functionele software: voert gedeelte van de taken van het systeem uit. Het inventariseren van de apparatuur gaat van buiten naar binnen. Aan de hand van het takenmodel bekijkt men eerst welke randapparatuur dat er nodig is, waarna men bepaalt hoe men al deze apparatuur met elkaar gaat verbinden en men deelsystemen toewijst aan een bepaalde machine. Enkele opmerkingen hierover: - - Bij de keuze van de architectuur moet ervoor gezorgd worden dat apparatuur en programmatuur de noodzakelijke beveiliging kan ondersteunen. Een belangrijke keuze is deze van de vorm van procesbesturing, waar men kan kiezen tussen proceduregestuurde systemen en gebeurtenisgestuurde systemen: o Procedure driven: De controle berust bij het programma. Elke procedure vraagt, waar nodig, gegevens van buiten af en wacht daarop. De toestand van het systeem wordt bepaald door de programmavariabelen. Het grootste nadeel van dit model is dat een gebeurtenis slechts zinvol is als het programma erop aan het wachten is. o Event driven: Het programma is geen doorlopende stroom van opdrachten, maar wel een aantal korte procedures die worden opgestart na het voorkomen van een gebeurtenis, waarna het systeem zich terug in ruststand zet. Het systeem wordt gedefinieerd door globale variabelen. Het dynamisch model bevat dan veel taken, waardoor het sequentiediagram zeer complex kan worden Als er een pakket is dat (al dan niet) alle taken voor zich neemt, beperken we ons tot de analyse van de interface van het pakket met de buitenwereld. Als er gekozen is voor wijzigingen aan het bestaande systeem, moet er een planning worden opgemaakt voor gegevensconversie. o Zijn alle gegevens voor het nieuwe systeem aanwezig en in welke vorm. o Blijft de organisatie voor de gegevens hetzelfde, en welke conversies moeten worden doorgevoerd. o Ontbreken er gegevens en hoe moeten ze worden aangevuld. Het keuzeprobleem Voor aan te kopen toestellen moet men beslissen welk model van welke fabrikant men zal nemen, voor software zal men moeten beslissen of men die zelf schrijft, derden dit laat doen of bestaande pakketten aanschaft. 15 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Er zijn drie krachten die aan de ideale oplossing trekken: 1. Het oude systeem: Het behoud kan om verschillende redenen nuttig zijn: a. Het systeem wordt gebruikt voor andere toepassingen b. Het personeel is vertrouwd met het oude systeem c. Vervanging kost geld Anderzijds kan een vervanging kan de functionaliteit van het oude systeem ten goede komen. Een belangrijk aspect is het natuurlijk ‘verval’ van een systeem: de noden veranderen waardoor het systeem minder bruikbaar wordt. 2. Het nieuwe project: De nieuwe elementen dienen zo goed mogelijk aan te sluiten bij de noden van het nieuwe project. 3. De kosten: aankoopprijs, kost van integratie in het oude systeem, kost van het verwerven van nieuwe expertise, onderhoudskosten, … Als een pakket alle taken uitvoert, is een takendiagram voldoende, als het slechts een gedeelte van het systeem uitmaakt, moet de interface meer gedetailleerd omschreven worden. Bij software aan te schaffen van derden zijn er drie niveau’s: - Men kan kant en klare pakketten aanschaffen. Men kan de software volledig laten schrijven. Een tussenvorm is dat sommige software bedrijven een basispakket hebben dat dan wordt aangepast en uitgebreid. Er zijn enkel criteria waar men op moet letten hierbij: - Overtuig jezelf dat de kandidaat de juiste kennis heeft. Vraag naar referenties over vorige projecten, en de tevredenheid van die klanten. Benader gemaakte beloften kritisch. Let op de wijzigbaarheid van software. Als er een onderhoudscontract wordt afgesloten moeten er garanties zijn dat het bedrijf blijft bestaan. Uit dit alles blijkt dat een startend bedrijf moeilijker kan onderzocht worden op zijn kwaliteiten, en minder garanties biedt. Maar alle softwarebedrijven zijn als starter begonnen, en ook een beginnend bedrijf zal kwaliteiten hebben. Generische systemen Een generisch systeem is een systeem ontworpen voor een bepaald soort klant, en niet voor een bepaalde klant. Ze moeten logischerwijze erg flexibel zijn. Bij de analyse gaat men meestal uit van verschillende typegevallen. Van een daarvan maakt men een grondige analyse, aan de hand van deze analyse zoekt men bij de andere gevallen de verschilpunten. Dezen worden opgevangen door parametrisatie. Bij installatie wordt door het invullen van parameters het systeem aangepast aan zijn specifieke omgeving. 16 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H15: Documentatie Er zijn twee grote obstakels bij het maken van goede documentatie: - Documentatie wordt beschouwd als een niet-essentieel onderdeel van het systeem, waardoor het uitgesteld wordt tot het einde, waar er vaak geen tijd meer overschiet voor ze te maken. Vaak wordt de evidentie van bepaalde kennis overschat. Om deze problemen tegen te gaan gebruikt men twee remedies: - - Het ontwerp en het schrijven van de documentatie wordt integraal opgenomen in het project. In elke fase van het project wordt er reeds een gedeelte van de documentatie afgewerkt. Dit zorgt ervoor dat het eerste obstakel al vermeden wordt. Men laat de documentatie schrijven door een team dat bestaat uit ontwerpers, programmeurs en gebruikers. Dit botst gedeeltelijk met de 1ste, omdat men de gebruiker pas kan betrekken als het systeem af is. Bij het ontwerp gebruikt men een tweedimensionale matrix. In de horizontale richting noteert men de verschillende functies van de documentatie, verticaal noteert men de doelgroep. In de vakjes vult men dan de methodes in, en hun beschrijving in de documentatie. Methodes 1. Papieren handleiding: geschikt voor het meegeven van grote hoeveelheid informatie en makkelijk sequentieel te doorlopen. Veel gebruikt voor een kennismaking en voor stap-voorstap beschrijving van te verrichten taken. 2. Hulpschermen: geschikt voor het overbrengen van kleine hoeveelheden informatie. Vaak overbodig door een goede programa- en interfaceopbouw. 3. Hypertekst: Voor kleine hoeveelheden informatie. Men kan uitgaan van een index en verwijzingen tussen de verschillende pagina’s. Wel arbeidsintensief. 4. Tutorial: Gebruikt voor de leerfase, met dummy-informatie bij het invoeren van gegevens. 5. Lessen/demonstraties: niet permanent beschikbaar, goed voor algemene inleiding van het systeem of de leerfase. Wel arbeidsintensief, dus enkel nuttig als verschillende gebruikers tegelijkertijd met het systeem moeten leren omgaan. 6. Helpdesk: Kan ondersteuning zijn door de producent zelf, opgenomen in het onderhoudscontract. De doelgroepen Als er verschillende taken uit te voeren zijn kan het nuttig zijn de documentatie op te splitsen. Na het indelen van de doelgroepen moet men ook denken aan het profiel van de doelgroep: wat is de kennis die men ervan mag verwachten? De meestgemaakte fout is dat men veronderstelt dat de gebruiker kennis heeft van een vorig systeem (upgradesyndroom). 17 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) De functies Traditioneel onderscheidt men 6 functies waarbij de documentatie nuttig kan zijn. 1. Kennismaking: Wat moet de gebruiker weten om een overzicht te hebben over wat het systeem allemaal kan? Met deze functie moet de gebruiker kunnen plannen hoe en waarom hij het systeem zal gebruiken. Hier worden de basisbegrippen uitgelegd. Maak geen beschrijving module per module. Het belangrijkste is dus de doelstellingen en taken van/voor het systeem uiteen te zetten. Deze permanente inleiding heeft als functie: - Het bezorgen van een overzicht van het systeem aan beginnende gebruikers - Het overtuigen van een klant dat het systeem voor hem bruikbaar is - Als startpunt voor de verdere documentatie. Alle andere informatie moet als niet-evident beschouwd worden. De basis: takendiagram De fase waarin ontworpen: ontwerpfase De vorm: op papier (mogelijks ook demonstraties en lessen.) 2. Leren: Hoe leert een beginnend gebruiker met het systeem omgaan? De fase waarin ontworpen: Dit moet worden uitgesteld tot de interface ontworpen is. De vorm: beslist in de ontwerpfase. (cursusprogramma’s, handboek, … tutorials zijn vervelend) 3. Uitvoeren: Hier gaan we uit van een gebruiker die min of meer weet wat er moet gebeuren, maar die hier en daar een geheugensteuntje of extra uitleg nodig heeft. Het is dus een beschrijving van de communicatie tussen het systeem en de buitenwereld. Dit deel van de documentatie bestaat uit twee delen. Het eerste deel is een sequentiële beschrijving, stap voor stap, van elke taak. Men kan hier uitgaan van de gemaakte sequentiediagrammen en scenarios. Dit kan worden gebundeld met het algemeen overzicht. Het tweede deel bevat informatie die specifiek is voor een bepaalde fase in de taak. De nodige documentatie moet worden gemaakt tesamen met de rest van het systeem, vermits het daar integraal deel van uitmaakt. Bij het ontwerp moeten dan ook richtlijnen worden uitgewerkt voor de uitwerking van de gebruikersinterface (de toepassing van de richtlijnen behoort tot de realisatiefase). Deze omvatten: a. Het bepalen van de look and feel van de interface. Fast prototype b. De vorm van de documentatie. Hulpschermen, boekvorm, … c. De normen voor de foutenafhandeling. Het is trouwens bijna altijd beter om eerst de handleiding te maken, en dan pas aan de realisatie van het systeem zelf te beginnen. Bij iteratieve methodes kan dit stapsgewijs gebeuren: voor elke build past men eerst de handleiding aan, en daarna het systeem. De basis: sequentiediagram & scenario De fase waarin ontworpen: samen met het systeem De vorm (en inhoud): beslist in ontwerpfase (hulpschermen, boekvorm,…) 18 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) 4. Probleemoplossen: Deze functie heeft een aantal eigenschappen gemeenschappelijk met de vorige: het gaat over korte stukken informatie die op een bepaald moment nodig zijn. Ze moeten vlot kunnen opgezocht worden, dus een goede index is belangrijk. Meestal is het voor mensen die al vertrouwd zijn met het systeem, dus het niveau van de beschrijvingen kan hieraan worden aangepast. De basis: geen De fase waarin ontworpen: samen met het systeem De vorm: hulpschermen,op papier, helpdesk. 5. Conversie/installatie: Hier hangt het er sterk van af wie dit doet: de persoon die het systeem ontworpen heeft, wat vaak het geval is bij specifiek voor de klant ontworpen systemen, of de klant zelf, bij generische systemen bijvoorbeeld. In het eerste geval is er natuurlijk weinig informatie nodig, in het tweede moet alle heel duidelijk en gedetailleerd uitgelegd worden. De basis: geen De fase waarin ontworpen: ontwerpfase De vorm: op papier. 6. Onderhoud en aanpassingen: Wie een aanpassing wil uitvoeren, moet precies weten wat hij moet veranderen en waar. Veel kan al verholpen worden door zelfdocumenterende programma’s. In tegenstelling tot de gebruikershandleiding is de documentatie hier wel technisch, en is het de bedoeling het inwendige van het systeem te beschrijven. De basis: analyse, als de diagrammen overeen komen. De fase waarin ontworpen: samen met het systeem De vorm: op papier, helpdesk 19 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H16: Planning Planningen worden in de behoefteanalyse gemaakt, en hebben 2 doelen: - Maken van een schatting van de kosten voor een risicoanalyse Het toekennen van hulpmiddelen Voor grote projecten => risicoanalyse Hier vergelijkt men de verwachte kosten en de voordelen van het ontwikkelen van een systeem tegen elkaar af. Als snelveranderende projecten => regelmatig herzien (spiraalmodel) Toekennen van hulpmiddelen doelt vooral op personeel. Mogelijks moeten er extra mensen worden aangeworven, of een deel uitbesteden aan derden. Een planning hangt af van een aantal schattingen (kosten, aantal personeel,…). Zo kan het zijn dat 1 taak meer werk vraagt dan verwacht, en een andere minder. Men moet dan personeel overhevelen. Men moet flexibel kunnen omgaan met de planning, en een zekere veiligheidsmarge inbouwen. Ook zijn er niet in alle fasen evenveel mensen nodig. De eerste (geen modulaire ontwikkeling) en laatste (taken hangen van elkaar af) fasen zijn er minder mensen nodig dan daartussen (parallelle werking mogelijk, enkel wijzigingen overleggen). Bij het maken van een planning moeten een aantal stappen doorlopen worden: - Gehele object onderverdelen in taken - Elke taak nauwkeurig definiëren - Voor elke taak een schatting maken van de hoeveelheid werk - De onderlinge afhankelijkheden bepalen - Een werkschema opstellen Verdeling van taakdefinities Bepalen wat er allemaal moet gebeuren, en de taken nauwkeurig definiëren voor grote projecten is de onderverdeling in fasen niet specifiek genoeg. - Een taak moet kunnen toegewezen worden aan een bepaalde persoon/team. Een taak moet dus zo fijn mogelijk gedefinieerd worden dat verder onderverdelen gaan nut heeft. Een taak moet duidelijk afgebakend zijn. Er moeten mijlpalen worden uitgezet. Een mijlpaal definieert het einde van een taak (analyserapport, stuk code, goedkeuring van een stuk code, …). Als een mijlpaal is bereikt moet de taak herzien worden (review, resultaat voorstellen op een vergadering) 20 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Schattingen Het moeilijkste van de planning is het inschatten van de hoeveelheid werk. Hiervoor zijn er geen normen, alles hangt af van de ervaring. Een oude manier: globale schatting van de hoeveelheid werk door het tellen van de programmaregels. LOC (Lines Of Code) en KDSI (Kilo Delivered Source Instructions) zijn maten waar nogal kritiek op was. 3,2 x KDSI1,5 leidt tot 800% schattingsfouten. Beter is het project splitsen in delen en hierop de schatting maken. Meestal heeft men een lijst met taken en hun werklast. Deze zijn alleen geldig voor die organisatie in enkel dat gebied. Ook extra kosten voor het samenvoegen moet men meerekenen. Afhankelijkheden en werkschema’s Bij lineair model waren er opeenvolgende fasen, die zelf 1voor1 moesten worden uitgevoerd, maar in de fasen kan men mogelijks wel parallel werken. Hier is het het makkelijkst om een graaf te tekenen en het kritisch pad te bepalen (DAG, Directed Acyclic Graph, gerichte lusloze graaf). Het is nuttig om enige speling op te nemen in het kritisch pad, dit verhoogt de flexibiliteit (teveel speling verslapt de aandacht). (kritisch pad => zie algoritmen). Zo een planningsdiagram is geen ULMdiagram, het dient enkel voor te plannen, niet voor te modelleren Bij de berekening van kritisch pad is de flexibiliteit niet voldoende. Beter is het PERT (Program Evalutaion Review Technique), dat 3 schattingen maakt: een optimistische, een pessimistische, en een waarschijnlijke. Op basis van de afhankelijkheden en de beschikbaar van het personeel kan dan het werkschema opgesteld worden (p193) Praktische indeling Eerst even ter nota: De wet van Brooks = In het geval dat er aan een taak, terwijl ze bezig is, mensen worden toegevoegd, leidt dit bijna steeds tot vertraging. De nieuwe mensen moeten eerst ingewerkt geraken eer ze productief worden, en daarbij zullen ze de anderen afleiden. Er zijn twee basismodellen voor groepsorganisatie, het democratische team en het hoofdprogrammeursteam. Democratisch team: Hier gaat men uit van de noodzaak van egoloos programmeren. Daarbij wordt elke programmeur verondersteld de andere leden van het team aan te moedigen om fouten te vinden in zijn code, en om dergelijke rapportering als een positief en noodzakelijk iets te beschouwen. (bij XP is dit vergedreven: code is van iedereen). Het laten ontstaan van zo’n team is vrij moeilijk. Meestal ontstaan ze vrij spontaan omdat de leden van de groep zich als evenwaardig beschouwen. Beslissingen worden dan democratisch genomen. Als er duidelijke verschillen in kennis, ervaring of geldingsdrang zijn, wordt dit erg lastig. Het blijkt wel dat democratische teams erg productief zijn, vooral in omstandigheden waar er veel innovatie en creativiteit vereist zijn. 21 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Hoofdprogrammeursteam: Dit is meer aangewezen bij klassiek programmeerswerk, of als er een grote ongelijkheid is in ervaring en vaardigheid van de groepsleden. De functie van de hoofdprogrammeur in dit team is tweeledig: ten eerste is hij de manager van de groep en zorgt hij dus voor praktische zaken zoals de taakverdeling, maar hij dient ook een expertprogrammeur te zijn die de leiding neemt bij het uittekenen van de software en de moeilijkste programmeerstukken op hem neemt. Omdat hij zo belangrijk is, wordt er een reserve voorzien. Deze neemt ook de speciale programmagedeeltes op zich en neemt zo de hoofdprogrammeur werk uit handen. Naast die twee hebben we ook nog de secretaris. Deze is verantwoordelijk voor de projectdocumentatie, versiebeheer en testen en staat dus hoger dan een programmeur. Omdat hier erg veel verwacht wordt van de hoofdprogrammeur, hebben we ook een gewijzigd model. Daar worden de praktische zaken uitgevoerd door een teammanager, die op zijn beurt ook een reserve heeft. Vaak is deze manager dan ook ineens de secretaris, omdat deze dichter aansluit bij het management dan bij het programmeren. Planningsgebaseerde kostenschattingen Er zijn drie soorten kostenschattingen: 1. Expertschattingen: dezen gaan uit van opgedane ervaringen die men veralgemeent naar een nieuw project. Deze is goed aangepast aan het bedrijf, maar moeilijk te veralgemenen. 2. Algoritmische schattingen: werken niet zonder aanpassing aan het bedrijf, maar hebben bruikbare modellen zoals COCOMO die kunnen geijkt worden aan voorgaande projecten. 3. Planningsgebaseerde schattingen: zie de overige uitleg van dit stuk. Men kan den verschillende schattingen van eenzelfde/verschillende categorieën mengen. Als deze schattingen gelijkaardige resultaten hebben is het ok, zoniet zal men zien waarom ze zover uiteen liggen, en niet gewoon het gemiddelde nemen. Planningsgebaseerde schattingen zijn in principe erg eenvoudig: aan elke gedefinieerde taak moet men hulpbronnen toekennen, men bepaalt de prijs van deze bronnen, en telt alles op. Er zijn wel enkele addertjes. Zo moet men weten: - Welke kosten reeds gemaakt zijn. Welke geschatte kosten moet men verwijderen. Welke geschatte kosten moeten blijven. De eerste twee punten verschillen omdat er een inschattingsfout kan gebeurd zijn. Met moet dan de overige taken ook herbekijken, en de schatting aanpassen. Men moet een idee hebben welk gedeelte van de kosten reeds gemaakt is, dus wanneer dat die kosten gemaakt zijn. Zo zullen aangekochte toestellen of uitbesteedde opdrachten niet meer te recupereren zijn. Ook het moment waarop de kosten worden gemaakt is belangrijk (dag- nacht tarief). Ook is er het probleem van over- en onderbevraging van hulpbronnen. Bij een persoon heeft overbevraging twee gevolgen: meer kosten dankzij overuren, en meer stress en vermoeidheid dus minder goede productiviteit. Onderbevraging zorgt dan voor hogere kosten per taak. 22 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Vaak is het moeilijk kosten te alloceren. Als een persoon 50% van zijn tijd met project 1 bezig is, en niets met project 2, is die de helft van de tijd technisch werkloos. Bij welk project moeten we die kosten dan aanrekenen? Daarvoor is er de flexibiliteitscoëfficiënt. Projecten met een flexibele planning zullen minder verantwoordelijk gesteld worden voor de kosten van over- en onderbevraging dan projecten waar alles stricter moet verlopen. Tot slot zijn er nog 2 opmerkingen die het resultaat van een kostenraming kunnen beïnvloeden: - - De wet van Parkinson: deze zegt dat werk altijd zover uitdeit dat het alle beschikbare tijd en werkkracht inneemt. Projectmanager zullen hierdoor soms een schatting maken die lager ligt dan de eigenlijke schatting, om iedereen ertoe aan te zetten wat harder te werken. Te extreme gevallen werken natuurlijk contra-productief. Pricing to win: waarmee wordt bedoeld dat men een schatting maakt die het meeste winst oplevert. Men schat wat de klant bereid is om te betalen, en maakt dit de geschatte kostprijs van het project. COCOMO (= Constructive Cost Model) Bij algemene methodes voor schattingen heeft men te maken met onnauwkeurigheid, en bij schattingen gebaseerd op ervaring is het moeilijk het nieuwe project met het oude te vergelijken. Men probeert deze twee te combineren door metrieken te parametriseren. Hierbij gebruikt men een bepaalde formule met parameters. Men past deze formule toe op projecten uit het verleden, en probeert zo de juiste waarden voor die parameters te vinden. COCOMO 81 Niet bruikbaar, maar is handig om bepaalde eigenschappen te bekijken. Er zijn hiervan drie varianten, die alle drie gebruik maken van dezelfde metriek: KDSI (Kilo Delivered Sourcecode Instructions). Het is doel steeds om het aantal mensenmaanden te schatten die men nodig heeft om het project uit te voeren. De varianten zijn: - Basis-COCOMO: werk in maanden = a x KDSIk Tussen-COCOMO: andere waarden voor a en k, en cost drivers Gevordere COCOMO: ook cost drivers maar op een meer gesofisticeerde manier De parameters a en k hangen niet alleen van de gebruikte variant af, maar ook van de ontwikkelingsmodus, waarvan er drie soorten zijn: - Organische modus: hier werken vrij kleine teams in een vertrouwde omgeving aan steeds gelijksoortige toepassingen. Halfopen modus: wordt getypeerd door een mix van ervaren en niet-ervaren personeel. Ingebedde modus: de projecten zijn ingebed in een complex geheel van bestaande software en hardware, met strenge regulaties. Hierdoor vraagt ontwikkeling grondige kennis van dit geheel, en is er het gevaar dat de resultaten van het project niet aan de strenge eisen voldoen. 23 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) De ontwikkelingsmodus wordt bepaald adhv verschillende criteria (grootte, innovatie, condities[tijd/geheugen gebruik], …). Als en project groter wordt, zal de k stijgen, waardoor de kosten meer dan lineair stijgen. De resultaten van de tussen-COCOMO moeten worden vermenigvuldigd met cost drivers. Er zijn verschillende cost drivers die de verschillende aspecten van een project en van de ontwikkelingsomgeving beschrijven. Voor elke driver geeft COCOMO een minimum- en een maximumwaarde. Voorbeelden van drivers zijn: ‘ervaring met de programmeertaal’, ‘complexiteit van het project’, ‘bekwaamheid van de analisten/programmeurs’, … De persoonlijke bekwaamheden zullen zo de belangrijkste rol spelen. Er zijn 2 soorten drivers: - Omgevingsfactoren. Bekwaamheid personeel, … deze veranderen niet tussen projecten. Projectfactoren. Deze zijn afhankelijk van het project, en zullen dus telkens opnieuw moeten worden geschat, of moet men door ervaring van het verleden proberen te schatten. Bij gevorderde COCOMO wordt de werkbelasting geschat, niet over het hele project, maar fase per fase, volgens het vereenvoudigd cascademodel - Behoefteplanning en productontwerp Gedetailleerd ontwerp Coderen en testen van modules Integratie en testen Voor elke fase worden dan de drivers bepaald. Zo zal in de eerste fase de driver voor de vaardigheden van de analysten meer doorwegen dan in de volgende fasen. Het gebruik van COCOMO vereist dat men de driverwaarden kent. Deze worden geschat adhv een vorig project, waardoor dit proces zeer fragiel wordt. Er moeten veel parameters bepaald worden, en men heeft altijd last van ruis op de meetwaarden. Er worden wel voorbeeldwaarden gegeven, verkregen door grote bedrijven, waardoor het bepalen van bepaalde drivers vereenvoudigd wordt als er gelijkaardige omgevingen zijn. Een groot voordeel van COCOMO is dat, wie dit model gebruikt, direct een lijst van factoren heeft die de kosten kunnen beïnvloeden, samen met een schatting hoe zwaar elke factor kan doorwegen. Men moet echter wel de KDSI telkens schatten met de natte vinger, wat niet erg nauwkeurig is. Ook gaat COCOMO er van uit dat als men een complexe ontwikkelingsmodus gebruikt, het project ook complex wordt, en dus meer zal doorwegen. Dit is niet altijd juist, en zorgt dus maar voor een ruwe schatting. 24 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) COCOMO II Er zijn een aantal factoren waarom COCOMO 81 minder en minder nut kreeg: - De komst van niet-lineaire ontwikkelingsmodellen Toenemende mate van hergebruik Meer gebruik van IDE’s en CASE-tools Toenemend belang van GUI’s en webapplicaties met andere kostenstructuren Toenemende mate van automatische codegeneratie Invoeringen van bepaalde standaarden (CMM, ISO 9000) zorgen voor besparingen Het eerste probleem dat COCOMO II aanpakte tov COCOMO 81 is dat van de basismaat: men gaat niet meer werken met KDSI, maar wel met KSLOC (Kilo Source Logical code). Men meet nu dus het aantal logische eenheden, zoals if-then-else-structuren. Er bestaan verschillende methodieken om deze SLOC te schatten, en daardoor wordt SLOC als een abstracte eenheid beschouwd. Deze methodieken werken meestal met een puntensysteem: functiepunten, objectpunten en kenmerkpunten. Objectpunten worden bepaald adhv de systeemvereisten, en kunnen al vrij vroeg (analysefase) bepaald worden. Functiepunten en kenmerkpunten steunen op interne gegevens, en kunnen pas na de ontwerpfase geschat worden. Een tweede verschil is dat naarmate het project verder vordert krijgen we met COCOMO II steeds meer informatie binnen. Dit komt omdat COCOMO II zich baseert op drie algoritmes, die op verschillende momenten in de ontwikkeling gebruikt worden: 1. Het vroegeanalysemodel: maakt gebruik van objectpunten. Te gebruiken in de allereerste fase van ontwikkeling. 2. Het vroegeontwerpmodel: maakt gebruik van functiepunten. 3. Het post-architecurale model: te gebruiken op het ogenblik dat de architectuur van de software volledig gekend is. Het vroegeanalysemodel Hier zijn er drie factoren die meetellen: - Het aantal te verwachten schermen voor de gebruikersinterface. Het aantal te verwachten softwarerapporten. Het aantal te verwachten softwarecomponenten. Elk van deze drie getallen worden vermenigvuldigd met een gewichtsfactor, en dan opgeteld (=objectpunten, OP). Men gaat nog kijken naar de mate van hergebruik; OP – (OP x r) = NOP (Nieuwe OP), en de productiviteit van de organisatie, uitgedrukt in 5 niveaus. Elke niveaustijging verhoogt de productiviteit met factor 2. De mogelijke fout door afronding is dan 50%. Het quotiënt van de NOP en de productiviteit levert dan de geschatte werklast op. 25 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Het vroegeontwerpmodel Hier gaat men gebruik maken van een aantal interne factoren, de zogenaamde functiepunten. Deze worden gemeten door een aantal kenmerken op te tellen (na te vermenigvuldigen met een gewicht), zoals inputs, outputs, databestanden, … Het gewicht hangt af van de complexiteit, en kan tussen 3 en 15 liggen. Voor transacties gaat men zo afh van het aantal betrokken bestanden en het aantal datavelden de complexiteit bepalen. De FP gaat men dan in een formule gebruiken: werk in maanden = 2,5 x m x SLOC^1,15 + AE waarbij de m het product van de costdrivers is, en AE staat voor autoeffort, wat aangeeft hoeveel werk de ontwikkelaars steken in het automatisch genereren van code, en de integratie van deze code in andere code. De omrekening van FP naar SLOC moet hier herzien worden. Bij hogere programmeertalen heeft men minder code per functiepunt nodig. Ook de efficiëntie van het productieproces in lijnen code wordt verminderd. Als de productiviteit, uitgedrukt in FP/MM gaat stijgen, zal deze uitgedrukt in SLOC/MM dus dalen. De COCOMO’s moeten dus voor elke taal herijkt worden, omdat we alleen geïnteresseerd zijn in het werk, en niet in de hoeveelheid code. Het post-architecturale model Ook hier gebruikt men een SLOC die afgeleid is van functiepunten, maar met twee aanpassingen aan het bekomen getal: - Variabiliteit aan vereisten: in het geval waar de vereisten gemakkelijk veranderen moet er vrij veel aanpassing gebeuren in latere fasen van het project. Dit leidt tot een hogere kost. De mate van hergebruik. Dit veroorzaakt hoge kosten in het begin van het ontwerp, maar besparingen later. Het post-architecturale model gebruikt 17 costdrivers, verdeeld in 4 groepen: - Producteigenschappen complexiteit en vereiste betrouwbaarheid Hardware-eigenschappen snelheid en beperking geheugengebruik Personeelseigenschappen ervaring Projectomgeving gebruik van CAS Nieuw is dat de exponent k niet vastligt. Deze wordt bepaald door 5 schaalfactoren: - Vertrouwdheid van de ontwikkelaars met dit soort project Ontwikkelingsflexibiliteit (hoog = klant bemoeit zich niet met het ontwikkelingsproces) Risicobeheer (= hoeveel tijd moet er besteed worden aan risicomanagment) Teamsamenhang Maturiteit van de organisatie 26 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Hergebruik Er zijn verschillende categorieën software: - Automatisch gegenereerd code: door tools, bv CASE. Hergebruikte code: wordt als ‘Black Box’ behandeld en ongewijzigd in het project opgenomen. Aangepaste code: wordt als ‘White Box’ behandeld, en gewijzigd voor de noden van het project. Commerciële code (Commercial Of The Shelf, COTS): geen broncode Voor automatisch gegenereerde code bestaan er geen algemene richtlijnen. Voor de 2 volgende categorieën is er een gemeenschappelijke kostenfactor: Assesment en Assimilation (AA) : beoordeling en invoeging, uitgedrukt in kost per eenheid code. Het zoeken naar de herbruikbare code, het beoordelen van alternatieve en de kwaliteit van de documentatie. Bij te wijzigen code komen er nog 2 kostanfactoren bij - Het aanpassen van de code. Afh van de totale hoeveelheid code en de aanpassingsfactor AAF Deze factor is zelf afhankelijk van 3 verschillende factoren: o Design Modification (DM) o Code Modification (CM) o Integration Modification (IM) Deze kunnen gecombineerd worden volgens de formule: AAF=(0,4 x DM) + (0,3 x CM) + (0,3 x IM) - Het vertrouwd raken met de code. Dit hangt af van de onvertrouwdheid (UNFaMiliarity, UNFM) en van de begrijpbaarheid (Software Understanding, SU). Dit wordt beoordeeld obv structuur, duidelijkheid en zelfbeschrijvendheid. De totale kost is dan UNFM x SU. Maar: bij veel aanpassingen moet de code grondig gekend zijn. Als er dus 50% van de code aangepast moet worden, moet men de volledige code begrijpen. Het vereiste werk is dan VC = (SU x UNFM / 100%) x (AAF x 2 / 100%) en als AAF>50% valt de tweede term weg. Bij herbruikbare code, gegenereerde code en COTS is DM en CM = 0 en IM zeer klein, waardoor AAF klein is. Bij aanpasbare code is meestal CM > DM > 0 en IM meestal + 50%, soms >100%, waardoor AAF stijgt. De totale inspanning AAM = ( AA + AAF + VC ) / 100%, uitgedrukt als een fractie van de broncode. De equivalente code KSLOC = bronhoeveelheid KSLOC x AAM. De broncode is gekend, dus kan geteld worden. Bij grote projecten moet nog de Requirements Evolution and VoLatility (REVL, verandering van de eisen) meegerekend worden. Grootte = (1 + REVL / 100% ) x ( nieuwe KSLOC + hergebruikte KSLOC ) 27 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) COCOTS COTS is volgens COCOTS-definitie: commercieel softwareontwerp met eigenschappen: - Verkocht of geleased aan aangekondigde prijs Geen sourcecode beschikbaar Periodieke updates Ontwikkeling niet onder controle van de ontwikkelaar De ontwerpen die de COTSsoftware gaat gebruiken heeft geen zeggenschap over de functionaliteiten en de evolutie. Na updates gaat de oude versie niet meer ondersteund worden, waardoor de ontwikkelaar vaak verplicht is om te upgraden. De software kan ook enkel door de ontwikkelaar aangemaakt worden. Men moet dus behalve de kwaliteit van de code ook de kwaliteit van de leverancier beoordelen. - Beoordeling: afweging van de verschillende opties (COTS - open source – zelf schrijven). Dit is de factor AA van hierboven Aanpassing: configuratie voor eigen gebruik. Gedeelte van IM Maken van Lijmcode: integreren van de COTS-module. Gedeelte van IM Vluchtigheid: de noodzaak voor upgrades MM = A x Grootte^k x (voor elke i) EMi waar k afhankelijk is van de schaalfactoren,en i tussen 1 en 14 ligt en de 14 cost drivers voorstelt. Risicoanalyse en –beheer Bij risicobeheer probeert men de risico’s te voorzien en op te vangen (mogelijkheid: oplossen als voordoet) Voor een goede planning en prijsofferte is enig zicht op extra kosten onontbeerlijk. Risico’s vallen per definitie niet te voorspellen, laat staan beheersen. Meestal zijn er een aantal risico’s verbonden met vrij vaak voorkomende gebeurtenissen, zodat men een idee heeft van de kans van gebeurtenis en impact. Er zijn 2 soorten risicobeheer verbonden aan softwareprojecten: - Softwareveiligheid: wat ken er misgaan bij het gebruik van de software en wat zijn de mogelijke gevolgen. Dit is moeilijk in te schatten - Procesveiligheid: wat kan er misgaan bij het ontwikkelingproces. De gevolgen zijn meestal meerkost of vertragingen, of zelfs verminderde kwaliteit van de af te leveren software. Hier zijn 2 verschillende aanpakken o Passieve: het risico wordt als onvermijdelijk beschouwd en de gevolgen worden beperkt o Actieve: men gaat proberen de waarschijnlijkheid van het risico te verminderen. De actieve oplossing is niet noodzakelijk beter dan de passieve. Veel risico’s zijn niet te vermijden (wispelturige klant). Men gaat dan beter de kostprijs berekenen met en zonder extra maatregelen, en deze dan vergelijken. Hierdoor heeft men een het nut van bepaalde maatregelen. Als het vermijden 10% vd kostprijs vraagt, en de gevolgen bedragen slechts 8%, dan is men beter met een passieve aanpak. 28 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Bij de berekening van de kostprijs zijn er 2 soorten aanpak: - Impliciet. Uitgaan van de kenmerken van een project, de bronnen worden niet opgesomd. Hier maakt men een inschatting van de kenmerken waar de ervaring van zegt dat ze risico’s opleveren. COCOMO voorziet hiren door de factor REVL (veranderen van specificaties) en de costdrivers zoals complexiteit en ervarenheid van het personeel. - Expliciet. Risico per risico de kostprijs berekenen Deze methode is beter te gebruiken bij een actieve aanpak. Eerst moet men de risico’s bepalen. Dit kan dmv een lijst met mogelijke bronnen van risico’s. Men bepaalt dan per item het bijhorende risico (bv Testen:testomgeving en Realisatie:automatisatie) en de mogelijke manieren om dit risico te verminderen. Impliciet: Bij de functiepuntenanalyse maakt men gebruik van een verwante impliciete methode. Deze FPen leveren een methode om de grootte van het project te schatten. De FP kunnen gewijzigd worden door de systeemkarakteristieken die de aan- of afwezigheid van de risico’s beschrijven. (herbruikbaarheid van de code, belasting van de hardware,…) Elke karakteristiek krijgt een DI waarde die tussen 0 en 5 ligt. Het aantal functiepunten vermenigvuldigd met VAF = 0,65 + 0,1 x (som van i=0 tot 14) DIi (=> max 35% meer) Expliciet: Men kan het risico verminderen op 2 manieren; de kans P beperken (actief) en de kost C beperken (passief). Dit levert de impact I op, met I = C x P. De totale kost is dan de som van al deze risico-impacts. Deze moet dan zo klein mogelijk zijn. Als we voor een risico een maatregel treffen, levert deze ook een kost M op > 0 (als kleiner dan zeker doen, want is veel beter). De efficiëntie van de investering M is dan RRL=( Ivoor + Ina )/M. en deze moet > 1 (aangezien een schatting, wordt =1 niet aanvaard). Als er nu een zeer grote kost C is met een lage waarschijnlijkheid P, dan gaat men maatregelen treffen die RRL<1 hebben. Het verzekeringsprincipe. De impact van het risico is dan kleiner dan de som van de premie. Het bepalen van de kost en de kans is zeer moeilijk, en men gaat dan ook vaak met vaste waarden werken (kost van 1% tot 5% en de kans van 15%-35%-50%-65%-85%). Na het opstellen van deze kosten, kan men een risicocurve tekenen. (p22) 29 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H17: Verificatie en validatie Verificatie = Ontdekken van fouten in het systeem. Validatie = Controleren of het systeem bruikbaar is in de situaties waarvoor het ontworpen is. Verficiatietechnieken komen in 2 groepen, zijnde statische evaluatie (nagaan van de structuur van de programma’s zonder ze te laten lopen) en dynamische evaluatie (kijkt naar het gedrag van de programmatuur). Dit laatste, ook testen genoemd, komt in 2 vormen: 1. Foutzoeken: Er wordt gepoogd het systeem verkeerd te laten lopen. Een correcte test is een test die fouten oplevert 2. Functioneel testen: Hier wordt gecontroleerd of het systeem in de meeste omstandigheden werkt. Hier is een correcte test een test zonder fouten. Ook wordt hier meteen aan validatie gedaan, als een systeem correct verloopt is aan alle specificaties voldaan. Testen zal nooit volledige zekerheid geven dat een programma nooit meer fouten zal vertonen. Daarom gebruikt men statistische foutenanalyse om een maat te hebben voor de kwaliteit van het systeem. Statische verificatie Het is belangrijk bij statische verificatie dat de auteur van het programma niet op zijn eentje instaat voor de inspectie, omdat die anders over heel wat van zijn eigen fouten overkijkt. Er bestaan 2 methodes voor statische verificatie: programma-inspectie en wiskundige verificatie Programma-inspectie Veel fouten zijn te wijten aan het ingaan tegen de algemene regels van net programmeren. Inspectie brengt deze fouten aan het licht. Ze vindt een groot aantal fouten niet, maar bespaart veel tijd in de latere methodes. De inspecteur moet niet noodzakelijk weten wat het programma doet, maar het maakt de controle natuurlijk wel handiger. inspectie gebeurt aan de hand van een aantal lijsten met mogelijke fouten. Normaal zijn er twee zulke lijsten: de eerste volgt uit algemene programmeerregels (worden alle programmadeeltjes gebruikt, zijn er geen oneindige lussen, heeft elke if-else nut, enz.). De tweede gaat over specifieke afspraken binnen het project (naamgeving van variabelen, foutenafhandeling volgens de afspraken, enz). Een gedeelte van deze checks kunnen automatisch gebeuren, wat bij sommige compilers ed ook gebeurt. Mathematische inspectie Dit wordt ook het bewijzen van het programma genoemd, hoewel het bewijs niet geheel sluitend is. Bij de implementatie van een procedure voert men toestanden in, en gaat men achteraf deze toestand verbinden met code. Bij mathematische inspectie gaat men uit van de code en probeert men logische plaatsen te vinden om een tussenstand in te voegen. Op deze manier wordt het programma verdeeld in 30 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) n verschillende delen. We kunnen dit ook zien als een boomstructuur, waar de knopen de scheidingspunten zijn, de wortel het aanvangspunt van de procedure en de bladeren de verschillende eindpunten (bijv de returnopdrachten) zijn. De takken zijn dan codefragmenten. Bij elke knoop wordt dan de toestand beschreven. De toestanden van de wortel en bladeren zijn beschreven in de specificatie van de procedure: ze zijn de pre- en postconditie ervan. Het ‘bewijs’ van het programma bestaat er in om aan te tonen dat 1. Elk stuk code de veranderingen verzorgt die gevraagd zijn door de overeenkomende tak. 2. De splitsingen aan elke knoop met verschillende kinderen correct wordt uitgevoerd. Voor lussen is er dan nog een speciale techniek nodig. Eerst heeft men de toestand voor de uitvoering van de lus, en deze erna. Aan de hand daarvan maakt men een beschrijving voor een enkele uitvoering van de code binnen de lus, en erna. Men dient dan aan te tonen dat: 1. De code exact deze wijzingen meebrengt. 2. De toestanden op elkaar volgend (de eindtoestand van een uitvoering is de begintoestand van de volgende). 3. De rij van toestanden steeds eindig is (de lus stopt altijd). Organisatie Het is duidelijk dat de statische verificatie niet goed kan worden uitgevoerd door de programmeur van de code. Er zijn twee mogelijkheden: 1. Iemand anders (een persoon of een team) voert de specificatie uit en geeft de resultaten aan de programmeur. 2. De verificatie wordt in groep uitgevoerd, dmv een presentatie of walkthrough. Dit laatste kan een gevoelig punt zijn voor de programmeur, omdat er dan andere mensen fouten ontdekken in zijn code. Dit kan opgevangen worden door bijv de code van meerdere mensen in één keer te bekijken. Dan zal hij ongetwijfeld niet alleen zijn in zijn achterlijkheid… stomme puntkomma’s.. Men moet altijd proberen om egoloos te programmeren. Testen op fouten Een test bestaat erin de te testen module te laten lopen in een speciaal gecreëerde omgeving, en het resultaat te vergelijken met wat men volgens de specificaties verwacht. Het kan uiteraard nodig zijn om programma’s te schrijven om zulke omgevingen te creëren, en ook om de resultaten te testen. Soms kan men gebruik maken van een orakel. Dit is een programma dat aan de hand van de testgegevens het correcte resultaat van de te lopen procedure kan voorspellen. Waarom maakt men nu een nieuwe module aan als men toch al een orakel heeft dat dezelfde functies kan uitvoeren? Er zijn twee belangrijke situaties waarin dit kan voorkomen: 31 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) 1. Het orakel heeft bepaalde functies niet die de te testen module wel heeft. Voor de functies die het oude systeem naar alle tevredenheid uitvoert kan men het oude systeem als orakel gebruiken. Meestal kan men dus slechts een deel van de functionaliteiten testen. 2. De nieuwe module werkt zelf samen met andere, eveneens nieuwe modules. Als men bijv een nieuwe printdriver wilt uittesten voor een nieuwe printer, dan moet men testafdrukken maken op de nieuwe printer en de oude: die moeten dan hetzelfde zijn Het is ook mogelijk om 2 verschillende teams een systeem te laten ontwerpen. De resultaten kunnen dan als orakel gebruikt worden voor elkaar. Men moet evenwel oppassen voor mogelijk fouten in de test zelf. De constructie van de testomgeving moet dus met alle zorg gebeuren. Als de module interageert met delen van het systeem die nog niet gerealiseerd zijn, dan is het nodig deze delen te simuleren. Daarvoor maakt men dummymodules aan, die ook stubs worden genoemd. Deze reageren zoals de echte modules die ze vervangen zouden doen, maar niet met de juiste gegevens. Ze worden vaak gebruikt bij de constructie van fast prototypes. Men heeft ook nog simulatoren. Deze vervangen gedeelten van het systeem of van de buitenwereld als het praktisch onmogelijk is om deze te gebruiken bij testen. Het grootste probleem bij foutdetectie is dat een groot deel van de fouten niet gevonden wordt. Er moet dus een planning worden opgemaakt van welke test men gaat uitvoeren. Er zijn twee soorten van testen: - - Blackboxtesten: Men maakt enkel gebruik van kennis over de omgeving waarin ze werkt, niets inwendig. Men probeert de mogelijke situaties waarin de module zich kan bevinden in te delen in verschillende klassen, waarbij vooral probleem- en randgevallen bijzondere aandacht krijgen. Dit wordt gebruikt als de test worden geschreven vóór de implementatie van de procedure. Whiteboxtesten: Hier gebruikt men wel kennis van het inwendige van de module. Men ontwerpt een verzameling tests die elk deel van de module gebruikt. Men gaat hier vaak gebruik maken van dynamische analyseprogramma’s. Zo’n programma houdt van elke programmaopdracht bij hoe vaak ze wordt uitgevoerd. Hiermee kan men nagaan of de test inderdaad alle code gebruikt. De meest uitgevoerde stukken komen dan ineens het eerst in aanmerking voor optimalisatie. Whiteboxtesten heeft als nadeel dat het fundamentele programmeerfouten niet zal ontdekken: als een programmeur voor een speciaal geval geen code heeft geschreven, wordt er voor die code ook geen test gemaakt. Het voordeel is dan weer dat men een richtlijn heeft om mogelijke invoercombinaties op te stellen. Meestal zal men dan ook beide soorten testen toepassen. Het is heel belangrijk om niet alleen de kleine delen te testen, maar ook de interacties tussen de grotere onderdelen. In dit opzicht zijn er twee manieren van testen: de top-down methode en de bottom-up methode. 32 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Bij de top-down methode wordt een geheel systeem opgebouwd uit dummy’s. Telkens er onderdelen geproduceerd zijn test men het systeem op de functies die het al kan uitvoeren, rekening houdend met het afwijkend gedrag van de dummy’s. De voordelen van dit model zijn de nadelen van bottom-up en omgekeerd: Voordelen van top-down=nadelen bottom-up: - Ontwerpfouten worden vaak vroeg ontdekt, nog voor de implementatie van de eigenlijke submodules. Elke keer er een nieuw onderdeel is afgewerkt kan het ingepast worden zodat een omgeving bestaat om het te testen. Men beschikt al vrij vroeg over een systeem dat tenminste gedeeltelijk bruikbaar is. Dit is goed tov de klant, en leuker voor de ontwerpploeg. Nadelen van top-down=voordelen bottom-up: - De resultaten van de acties van een onderdeel kunnen niet altijd direct waargenomen worden omdat ze intern zijn aan het systeem. Het is niet altijd veel gemakkelijker om dummy’s te maken dan de onderdelen zelf. In de praktijk zal men dus meestal een gemengde methode gebruiken die soms bottom-up en soms topdown werkt. Testen bij hergebruik Het heeft geen zin om hier whiteboxtesten te gaan doen: deze technieken zijn al gebruikt bij de eerste contructie van die module. Bij blackboxtesten is het anders: daar de module in een andere situatie gebruikt wordt, is het zeer wel mogelijk dat de verzameling van relevante situaties verandert. Er moeten dus nieuwe testen ontworpen worden voor alle mogelijke situaties. Bij het debuggen moet men wel in gedachten houden dat de gebruikte modules nog fouten kunnen bevatten die vroeger niet ontdekt zijn. Foutenschattingen Een methode om de tests te testen staat bekend als foutzaaien. Men vervangt de module die men wil testen door een module waarin moedwillig fouten zijn aangebracht. Men gaat ervan uit dat de tests een even groot percentage van de fouten zal vinden in beide gevallen, zodat men weet hoeveel er nog over zijn. Het is echter zeer moeilijk om ervoor te zorgen dat de ingezaaide fouten van dezelfde types zijn als degene die er nog inzitten, aangezien men die niet kent. Dit is dus niet erg betrouwbaar. Een andere methode bestaat erin de tests te verdelen over verschillende, even grote groepen. Men gaat ervan uit dat elke groep tests een even groot percentage van de nog aanwezige fouten zal vinden. Men kan nu door de verhouding van gevonden en totale fouten een formule bapelen die adhv de gevonden fouten, het aantal resterende kan bepalen. Ook deze methode is allesbehalve nauwkeurig. (er is dus geen betrouwbare manier om de tests te testen… is da nu zo moeilijk om het gewoon zo te zeggen?) 33 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Functioneel testen en betrouwbaarheid Het grote verschil tussen het testen op fouten en het functioneel testen is dat men bij foutzoeken probeert tests te vinden die zo snel mogelijk fouten in het systeem ontdekken, terwijl bij functioneel testen wordt nagegaan hoe het systeem zich in de praktijk gedraagt, maw in doorsnee situaties, niet in uitzonderingen. Er zijn twee manieren van functioneel testen: 1. Droog testen: het systeem wordt getest in een kunstmatige omgeving (=alfatest) 2. Nat testen: de eigenlijke werkomgeving wordt als test gebruikt (= betatest) Dit is zeer belastend voor de klant. Fouten tijdens deze fase verbeteren is duur. Het lokaliseren is zeer moeilijk, en het repareren heeft meestal tot gevolg dat andere delen moeten herschreven worden. Ook de goodwill van de klant verdwijnt en de tijdsdruk neemt toe. Feit is dat geen enkel groot systeem perfect is. Er is een toenemende kost om fouten te verwijderen naarmate er minder zijn. Daarom gaat men uit van een acceptabele kwaliteit: men stelt een grens aan het aantal fouten dat mag optreden. Hiervoor zijn er twee manieren: - Men geeft op hoeveel fouten het systeem mag bevatten. Men geeft aan hoe vaak het systeem mag falen, uitgaande van een normale werksituatie. Opvallend is dat geen van de klassieke maten expliciet rekening houdt met de ernst van de storingen. Om dit op te vangen worden soms mogelijke storingen opgedeeld in klassen, met elk een verschillend niveau van tolerantie. 34 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H19: Specificatietheorie Er zijn problemen met het verschil tussen specificatie en implementatie. Deze liggen in grote lijnen op 2 gebieden: het datagedeelte en het procedureel gedeelte. Datagedeelte: we beginnen met een abstracte beschrijving van modules. Bij de implementatie duiken er dan problemen op, doordat het klassendiagram niet eenduidig is. Welke attributen zijn afgeleid, en welke zijn echt? Proceduraal gedeelte: hoe worden de post- en precondities gedefinieerd? Deze moeten ondubbelzinnig zijn, maar ook niet nodeloos lang. (bv zoeken, maar geen specificatie ivm duplicaten, of foutwaarden) We zitten met een specificatieprobleem bij verschillende methoden. Wiskundige inspectie: op een vlotte en duidelijke manier de tussentoestanden beschrijven. Testen: wat moet een module juist doen? Bij het ontwerp van blackboxtesten gaan we uit van de specificaties, en nog zeer specifiek over de randgevallen. Deze moeten dus expliciet vermeld worden. Als we de specificaties goed beschrijven, kunnen we eventueel testen automatisch laten verlopen. (functie die bool terug geeft). Bij het definiëren van de specificaties kan men gebruik maken van formele specificatietheorieën. Deze proberen de overgang van abstracte definitie naar concrete implementatie zo vlot mogelijk te doen verlopen. Specificaties kunnen dan uitgedrukt worden in een formele taal, waardoor de automatisering nog vlotter kan verlopen. Representatie- en abstracte waardenverzameling Een object heeft een toestand. De verzameling van mogelijke toestanden voor een gegeven klasse is de abstracte ruimte Abs of Abs(klassennaam).Deze Abs stelt dus de realiteit voor. Abstract, omdat niet alle waarden ook effectief zullen voorkomen. De Abs wordt gedefinieerd tijdens de modellering van de realiteit (de specificatie van de klasse), en dus voor elke implementatie. De representatieruimte Rep is de verzameling van alle mogelijke toestanden van de implementatieobjecten. Dit zijn dus alle mogelijk combinaties (geldig of niet geldig) van alle velden. Deze ruimte wordt gekozen, en wordt dus niet volledig bepaald door Abs. Zo is er het niveau waarop de attributen worden opgeslagen (int-double), de keuze van afgeleide attributen (gemiddelde-som) en de implementering van verzamelingen (vector-gelinkte lijst). Dit gebeurt tijdens het ontwerp van de implementatie. Een implementatieobject moet overeenstemmen met een reëel object. - Welke waarden in de representatieruimte komen overeen met een toestand in de abstracte ruimte? Met welk abstracte toestand komt een geldige waarde overeen? Dit zijn 2 verschillende vragen! Het is niet omdat een implementatieobject overeenkomt met een element Abs, dat we weten met welk object het overeenkomt. (eventuele maten: centimeter? meter?) 35 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Het antwoord op de eerste vraag kunnen we vervatten in een functie: de logische functie R. R: Rep->{waar,onwaar} R geeft waar als de waarden van een implementatieobject overeenkomen met een toestand in de abstracte ruimte. R wordt de representatie-invariant genoemd, afgekort rep-invariant. Deze functie kan een lidfunctie zijn van de klasse, en wordt enkel gebruikt in de testfase. Het antwoord op de tweede vraag kunnen we vervatten in een functie: de logische functie A. A:Rep->Abs A is alleen gedefinieerd voor geldige waarden in Rep, maar kan niet geïmplementeerd worden, omdat we geen computervoorstelling hebben van de realiteit. Het is wel mogelijk dat 2 verschillende elementen van Rep worden afgebeeld op hetzelfde element van Abs (hashtabel met lege vakjes, en met geschrapte vakjes zijn beide lege hashtabellen). Voorbeeld pagina 29-31 extra bladen. Rep, staten en overerving Er zijn 2 soorten overerving: uitbreiding en restrictie. We gaan uit van bovenklasse A en onderklasse B. Overerving door uitbreiding elk element van B bevat alle eigenschappen van uit A, maar ook bijkomende eigenschappen. Als de eigenschappen alleen nieuwe operaties zijn, dan veranderd er niets aan de representatie. Abs(A)=Abs(B), Rep(A)=Rep(B), Ra=Rb en Aa=Ab. Een operatie hoeft niet altijd zinvol te zijn. Bij sommige staten van een klasse moet de operatie niet zinvol zijn. Maar omdat B door uitbreiding in stand is gekomen, moet voor elk element van Abs(A) een zinvolle uitbreiding aanwezig zijn. Dit legt een restrictievoorwaarde op: De klasse B beschrijft alleen elementen van A waarvoor de uitbreiding zinvol is. Als dit klopt, is B door restrictie en niet door uitbreiding tot stand gekomen. We nemen dus dat B voor alle elementen van Abs(A) minstens 1 zinvolle uitbreiding heeft. Er mag dan ook geen sprake zijn van functies overschrijven. Elk element van Abs(A) (=Abs(B)) kan voorgesteld worden door b uit B of a uit A. Als men dan de functie oproept moet deze in beide gevallen dezelfde waarde geven, en mag dus niet verschillen, of dit breekt met de consistentievoorwaarde. Als B dus enkel operaties bevat, en geen extra datavelden beschrijft B enkel meer eigenschappen van de elementen uit A, en is A eigenlijk overbodig. We stellen dus dat B het datagedeelte van A uitbreidt. Nu kunnen we b uit B voorstellen als a uit A samen met b’ uit B’, die alle datavelden en operaties bevat die van de uitbreiding deel uitmaken. De link tussen beide wordt voorgesteld als Y(b’)=a. Nu is Abs(B) de deelverzameling van Abs(A). Dit mag omdat we niet alleen operaties, maar ook datavelden toevoegen, waardoor het geen restrictie is. Alleen elementen van Abs(A) die overeenkomen met een element b’ uit B’ zijn lid van Abs(B). 36 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Elk element uit Rep(B) is samengesteld uit een de velden van A en de velden van B’. Rep(B) = Rep(A) x Rep(B’), elk element b is dus te beschrijven als een koppel (a,b’) elk koppel (a;b’) moet voldoen aan: - Ra(a); a moet element zijn van Abs(A) - Rb’(b’); b’ moet element zijn van Abs(B’) - Y(b’) = a; de twee delen moeten bijeen horen. Rb( (a,b’) ) = Ra(a) && Rb’(b’) && Y(b’)==a De abstractiefunctie Ab is een element b uit Rep(B) waarvoor Rb is afgebeeld op Abs(B). de afbeelding hangt echter alleen af van a, dus Ab( (a,b’) ) = Aa(a) Overerving door restrictie Hier gaat het om extra voorwaarden voor de objecten uit de bovenklasse. Zo is een vierkant een speciaal geval van een rechthoek. Eenvoudig te begrijpen is dan dat Abs(B) een deelverzameling is van Abs(A). Er zijn ook geen extra velden nodig, waardoor Rep(B) = Rep(A). Het verschil zit in de invarianten Ra en Rb. Beide functies werken op dezelfde verzameling, maar Rb is veel striker dan Ra. Voor elke x element van Rep(B) : Rb(x) = Ra(x) && resrictievoorwaarde(x) Als Rb(x) geldt, zal dus ook Ra(x) gelden. B beeld nu ook afbeeldingen of uit A, dus is Ab(x) = Aa(x) Het verschil tussen restrictie en staten is dat men van staat kan veranderen, maar niet van klasse. Als we nu een klasse A nemen, met verschillende staten S1 tot Sn, dan kunnen we Abs(A) opdelen in n verzamelingen, die ondelring geen gemeenschappelijke elementen hebben, en waarbij elk element in een staat zit. Abs(A) is dan de unie van alle Abs(A,Si). Hiervoor kan ook een staat-invariant Rs gecreëerd worden Rsi:Rep->{waar,onwaar} : Rsi(a) = Ra(a) && Aa(a) is deelverzameling van Abs(A,Si) In woorden: Rsi(a) is waar asa de rep-invariant waar is voor a en als de abstractiefunctie a afbeeldt op een reël object in staat Si Het gebruik van R bij specificatie en V&V Na het definiëren van de rep-invariant moet deze ook geïmplementeerd worden. De functie mag geen parameters meekrijgen (afhankelijk van *this en uitwendige parameters) en het definiëren moet met de grootste zorg gebeuren, liever een vals alarm, dan fouten die niet worden gevonden. 37 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Richtlijnen om een goede rep-invariant te vinden: - Zoek zoveel mogelijk elementen uit Rep waarvoor de abstractiefunctie geen zin heeft (personen met negatieve lengte) Let op voorwaarde die horen bij gebruikte algoritmen. (min 1 element in tabel voor zoeken) - Zoek naar gegevens die synchroon moeten aangepast worden, en probeer deze uit (aantal knopen moet aangepast worden bij toevoegen/verwijderen) - Zoek naar voorwaarden in de ruimte Abs. (meer dan 32 schaakstukken op schaakbord) - Zoek naar situaties die de code zouden doen crashen. (nullpointers, deling door 0, …) Mogelijks is bij de uitvoering van code tijdelijk niet voldaan aan de rep-invariant. Er kan namelijk maar 1 opdracht tegelijk uitgevoerd worden. Nu kan men tussentoestanden invoeren, die aanduiden waar de repvariant voldaan is. Men probeert dan ook zo snel mogelijk deze terug in orde te krijgen. Een inbreuk aan de repvariant kan mogelijks doorgegeven worden tussen verschillende methodes, dit komt vaak voor bij complexe datastructuren. (wortel uit heap verwijderen) De regel is hier dat de repinvariant verbroken mag zijn zolang het object de controle heeft dat het hersteld wordt. Een object mag ook de rep-invariant van een ander object verbreken, zolang dat hij voor het verlies van controle de repinvariant terug goed zet. Blootstelling van Rep Een object mag zijn eigen rep-invariant tijdelijk doorbreken, maar moet ervoor zorgen dat geen ander object zijn rep-invariant doorbreekt. Er zijn 2 bronnen van blootstelling: - Het publiek maken van datavelden. Vaak om efficiëntieredenen - Een pointer naar een dataveld of deelobject doorgeven Voorbeeld: gesorteerde tabel, en een pointer naar een index teruggeven. Oplossing: const pointer teruggeven. Voorbeeld: pointer naar een ‘sleutel-data paar’ geven, men kan de inhoud van dit object aanpassen. Zowel de sleutel en de data zijn dus aanpasbaar. Oplossing: niet doen Voorbeelden p37-38 Er bestaan 2 vormen van blootstelling: - Exporteren. Het doorgeven van het adres van een item dat niet mag gewijzigd worden. - Importeren. Het invullen van een bestaand object door de cliënt. Dit kan nog steeds veranderd worden door de cliënt zelf (lokale variabelen die worden verwijderd bij eindigen van while/functie/…) 38 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Formele specificatie Specifiëren van een module houdt in: - De preconditie beschrijft de verwachtingen van de buitenwereld. De toegelaten waarden van parameters, de staat van het *this object en de toegestane hulpmiddelen. - De postconditie beschrijft de verwachting van de module Men moet duidelijk afspreken wat er wel en niet in de pre- of postcondities mag staan. De rep-invariant moet altijd voldaan zijn, en moet niet vermeld worden. Uitzonderingen waarvoor deze niet voldaan is: - De precondities van de constructor. - De postcondities van de destructor. De specificatie moet uit 4 delen bestaan: Het publiek maken van datavelden. Vaak om efficiëntieredenen - Precondities (vereisten): de mogelijke waarden van parameters en de staat van alle betrokken objecten. Default: rep-invariant - Frame (kader): deelobjecten (en datavelden van *this) die kunnen gewijzigd worden. Dit is een deel van de postcondities omdat het aangeeft wat de procedure niet mag wijzigen (alles dat niet vermeld wordt). Default: leeg - Postcondities (zorgt-voor): Alle voorwaarden waar de module aan moet voldoen. Als alleen toegestane wijizigingen zijn gemaakt die voldoen aan de postconditie is de module correct (wijzigen van een index => welke waarden?) Default: rep-invariant - Returns (teruggeefwaarde): wat geeft de module terug. (overschrijven van functie bv roteer voor een cirkel). Default: niks Een ongedetermineerde specificatie: enige vrijheid van implementatie (index van element, geen specificatie voor duplicaten). Deze zijn vaak het gevolg van slordigheid. Voordeel: de programmeur kan zelf de implementatie aanpassen aan de efficiëntie (quicksort=duplicaten andere volgorde) Nadeel: uitgaan van een interpretatie, waardoor fouten gemaakt worden. Daarom moet de speling expliciet vermeld worden! Dit maant aan tot voorzichtigheid Dit soort specificaties wordt ook vaak niet-deterministisch genoemd. (code die niet altijd hetzelfde uitvoert, vaak door randomgenerator). Er is dan niet sprake van HET juiste resultaat maar EEN juist resultaat. Een orakel kan hier niet gebruikt worden, omdat verschillende resultaten geen fouten impliceren. 39 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Algebraïsche specificaties Bij een beschrijving kan men uitgaan van een benadering obv - Gebeurtenissen. De binnenkant van objecten is onzichtbaar, enkel de operaties en hun invloed is gekend. Hier wordt gebruik gemaakt van procesalgebra. - Model van de toestand van het object. Hier wordt gebruik gemaakt van modeltalen. Bij Algebraïsche specificaties gaat men de eerste benadering toepassen. Naast de opsomming van de operaties worden axioma’s gegeven. Dit is een uitspraak die altijd waar moet zijn, en die bestaat uit een vergelijking van 2 waarden (meestal objecten van een klasse). Hiervoor moeten de comperatoren gedefinieerd zijn. Operaties worden onderverdeeld in 4 verschillende soorten: - Creatoren. Deze maken een nieuw object van een klasse. Deze mogen geen parameters bevatten die objecten van de eigen klasse voorstellen. (constructor) - Producenten. Deze creëren een nieuw object obv een of meerdere objecten van de eigen klasse. (copyconstructor) - Modificator. Deze veranderen het *this object (alle overige) - Kijkoperaties. Deze geven informatie over het object terug (aanmaken object bij factory, dit is voor de klasse zelf een creator) Deze eerste 3 soorten geven allemaal een object terug van dezelfde klasse. De vierde kan een totaal willekeurige klasse zijn. Als men deze operaties gaat beschrijven, gaat het *this object als eerste parameter worden gegeven (in C programmas bevat een klasse geen operatoren) Er is dan geen verschil te merken tussen een modificator en een producent. Deze worden gegroepeerd onder de noemer Mod. Creators zijn Crea en kijkoperaties Kijk. In een reguliere expressie (REGOU) kan men na een uitdrukking ook de * operator (0 of meer keer) gebruiken om sequenties aan te duiden. Bij algebraïsche specificatie wordt eerst de naam van de klasse gegeven, dan een opsomming van alle mogelijk operatoren met hun signatuur, parameters en resultaat, en dan een specificatie dmv axioma’s. Voorbeeld p 42 Volledigheid Is het definiëren in axiomas volledig? Kan men voor een willekeurige reeks van operaties afleiden wat het resultaat is? Om te beginnen moet men een willekeurige reeks operaties specificeren als een reeks operaties die zinvol zijn. Men moet dan beginnen met een Crea, hierop een aantal Mod toepassen en eventueel eindigen met een Kijk. Een andere volgorde zou foutief zijn. Hier moeten we dan ook meerekenen dat een eventuele exceptie kan opgegooid worden. Nu beschouwen we dat een functie op een exceptie zelf een exceptie oplevert. We bekomen dan K = Kijk Mod * Crea (we moeten rekening houden dat we van rechts naar links gaan overlopen) 40 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) De eis dat axioma’s volledig zijn kan nu beschouwd worden door de functie W totaal te beschouwen. W : K -> Waarden Dit moet dus gelden voor elke waarde van K Hier is W de waardenfunctie is, en Waarden de verzameling van alle mogelijke waarden. De waarde van een object wordt bepaald door de toepassing van alle mogelijke operatoren op het object. Als de klasse ondergedetermineerd is, en er dus meerdere objecten mogelijk zijn voor dezelfde operatie, kan men de waarde bepalen, maar dit is te moeilijk. Als men de axioma’s standaardiseert kan men eenvoudiger bepalen aan welke eisen de axioma’s hoeven te voldoen. Eerst definiëren we het begrip: een reduceerbare modificator - Het resultaat van de Mod toegepast op een willekeurige Crea moet uit te drukken zijn als een resultaat van een Crea. Als Mod de laatste Mod is van een rij, toegepast op een Crea, dan kunnen we deze rij vervangen door een equivalente rij die ofwel kort is, ofwel even lang, maar eindigt met een nietreduceerbare operator. We moeten kunnen afleiden uit de axioma’s wat elke zinvolle reeks operatoren als antwoord zou geven. Voor elke reeks moeten we dus het resultaat kunnen afleiden. Dit bewijzen we door inductie: We gaan elke lange reeks proberen te reduceren tot een kortere. We beschouwen een zinvolle reeks met 1 Crea, m Mod en 1 Kijk: - Als m==0, dan kan men het resultaat afleiden uit de axioma gedefinieerd door de Kijk op de Crea Als m>0, dan zijn er 3 mogelijkheden: o De laatste modificator is niet-reduceerbare modificator. We lossen dan de reeks op, tot we aan deze modificator zitten, en dan kan men door zijn axioma’s een resultaat bekomen. We kunnen dan ook voor de Kijk zijn interactie met de Mod bekijken. o Alle modificatoren zijn reduceerbaar. Men kan dan de Mod op de Crea uitvoeren, waarmee men een nieuwe Crea bekomt. Deze redering wordt verder gezet tot het einde. o De laatste modificator is een reduceerbare, maar een komt een niet-reduceerbare voor in de reeks. Men kan dan deze niet-reduceerbare Mod naar links opschuiven of laten verdwijnen. Men kan in geval 1 of 2 terechtkomen. Men kan nu makkelijk bepalen hoeveel axioma’ er nodig zijn. Voor elke reduceerbare Mod (r) of Kijk (k) moet men moet er een axioma zijn dat zijn interactie bepaald met de mogelijke Crea (c) en de mogelijke niet-reduceerbare Mod (n). Het aantal benodigde axioma’s is dan ( r + k ) x ( c + n ) 41 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Nu heeft men het geval dat een axioma zelf ook parameters kan bevatten (een koffieautomaat gaat bij het geven van een kop koffie zowel een resultaat als een nieuwe automaat geven, een Kijk én een Mod). Hier voeren we dan nieuwe notaties toe. P is de projectieoperator op het eerste element (het resultaat=>Kijk) en P2 is de projectieoperator op het tweede element (de nieuwe automaat=>Mod). Om de axioma’s te standaardiseren moeten de axioma’s met parameters gesplitst worden. Een axioma waar x aantal keer een functie moet worden uitgevoerd, kan dan beschreven worden ifv deze functie. Zo word een functie vulbij (A,p) gesplitst door vuleenbijp (A). Voorbeeld p44-46 Toestand en attributen Algebraïsche specificaties bevatten geen expliciete attributen, maar toestanden kunnen wel gedefinieerd worden, waardoor het bestaan van bepaalde attributen kan bewezen worden. Deze moeten dus op zijn minst afleidbaar zijn. Een levensloop is een Crea, gevolgd door x aantal Mod. De paramaters worden ingevuld, en bepaken de verschillende levenslopen. LL = Mod* Crea Nu kunnen 2 objecten verschillende levensloop hebben en toch in dezelfde toestand verkeren. 2 levenslopen zijn equivalent als ze beide voor een willekeurige reeks Mod, gevolgd door een Kijk dezelfde waarde opleveren. Als er sprake is van ondergedetermineerdheid klopt deze stelling niet, omdat dezelfde levensloop dan niet equivalent is met zichzelf. Een levensloop is altijd equivalent met een andere levensloop die alleen maar niet-reduceerbare Mod bevat, ln genoemd. Voor elke reduceerbare Mod kunnen we namelijk door reductie bewijzen dat de levensloop equivalent is met een kortere. Door dit meerdere malen te doen houden we geen reduceerbare Mods meer over. Een toestand is nu een verzameling die alle equivalente levenslopen bevat. Men kan deze toestand nu voorstellen door een attribuut, dat de waarde van n voorstelt. Nu kunnen we deze attributen ook op een andere manier bepalen, door de vragen te bekijken die we aan de levensloop kunnen stellen: V = Kijk Mod* V is de verzameling vragen die we aan de levensloop kunnen stellen. Als v een vraag is en l een levensloop dan is W(vl) het antwoord op vraag v aan levensloop l. 2 vragen zijn equivalent als het antwoord op beide vragen voor dezelfde levensloop hetzelfde is. Een vraag is triviaal als het antwoord op de vraag voor alle levenslopen hetzelfde is. Een attribuut stelt nu een toestand voor die een equivalentieklasse is van niet-triviale vragen. 42 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Nu vinden we zeker alle relevante attributen, maar ook alle afgeleide attributen. in het voorbeeld op p49 komt hij een oneindig aantal verschillende attributen voor, maar deze geven slechts 2 verschillende waarden => casten naar bool dmv een rep-invariant. De rulmtes Rep en Abs zijn reeds ingevoerd, nu gaan we T invoeren, de verzameling van toestanden van een klasse, zoals gedefinieerd met algebraïsche specificatie. T en Rep houden zou weinig mogelijk verband met elkaar: Rep is afhankelijk van de implementatie, en T is juist zo onafhankelijk van dit verband. T en Abs houden juist veel verband met elkaar: de eventuele excepties in de implementatie zijn elementen van Rep die niet voorkomen in Abs. Nu vormen deze excepties 1 toestand, en alle levenslopen die niet tot deze toestand behoren, stellen elementen voor in Abs. Nu is er wel een eenduidig verband tussen een levensloop (dat het gedrag voorstelt van een of meerdere element uit Rep) en een element uit Abs dat bepaald wordt door zijn gedrag.1 element uit Abs komt dan overeen met juist 1 levensloop. Ook andersom werkt deze redenering. 2 levenslopen die equivalent zijn, hebben hetzelfde potentieel gedrag. En modelleren dus hetzelfde element uit Abs. Met elke toestand uit T komt dus juist 1 element voor uit Abs. Als er elementen zijn uit Abs die niet overeenkomen met een toestand, dan kan er geen informatie verwerkt worden van deze elementen, en is de specificatie foutief. Bij een goed ontwerp is er een 1-op-1 relatie tussen de toestanden in T en de elementen ui Abs. Een attribuut dat natuurlijk lijkt in Abs moet dus af te leiden zijn uit de levenslopen van de klassespecificatie. Nu is de moeilijkheid te bepalen of alle attributen wel onafhankelijk zijn (en niet afgeleid) en of wel alle relevante attributen bepaald zijn. Algebraïsche specificatie en geparametriseerde klassen Als men de algebraïsche specificatie van een geparametriseerde klasse wilt bepalen, moet men rekening houden met de eigenschappen van de parameters. Deze moeten waarschijnlijk aan bepaalde eisen voldoen. Zo moet een gesorteerde lijst (klasse) parameters hebben die sorteerbaar zijn. Deze eisen worden uitgedrukt door diensten. Dit is een geheel van operaties voor een klasse met hun (algebraïsche) specificaties. Als men gebruik wilt maken van deze diensten, moet men dit geheel van operaties ondersteunen. Als er communicatie tussen verschillende objecten plaatsvindt, moeten operaties soms berichten sturen naar andere objecten en ook antwoorden ontvangen. Dit modelleert men door: - Het sturen van berichten te beschouwen als een kijkoperatie, die als resultaat het bericht zelf en het aders van het ontvangende object teruggeeft Het ontvangen van berichten te beschouwen als een extra parameter mee te geven aan de operatie. 43 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Modelspecificatie met Z Modeltalen geven een specificatie van een systeem op basis van de toestand ervan. De toestand wordt beschreven adhv een aantal attributen, en operaties door de wijziging van de attributen (Mod) of door de functionele relatie tussen attributen en teruggeefwaarden (Kijk). Z werkt met schema’s. Deze bestaan uit 3 delen: de naam, de signatuur en het predicaat. De signatuur bestaat uit een lijst van entiteiten die deel uitmaken van het schema aangeduid met naam en type. Het predicaat is een uitspraak die waar moet zijn. De uitspraak geeft de relatie tussen entiteiten uit de signatuur. De signatuur kan ook andere schema’s bevatten. De entiteiten worden dan samengesmolten en het predicaat is de logische en van de verschillende predicaten. Als de signatuur een V tussen beide signaturen bevat, wilt dit zeggen dat de entiteiten samensmelten, en de predicaten door een or gecombineerd worden. Parameters hebben een ? na hun naam, en teruggeefwaarden een !. Het deltaschema wordt afgeleid uit het origineel en stelt de signatuur en het predicaat voor en na de actie voor. De signatuur wordt gekopieerd en overal een ‘ achter geplaatst, het predicaat wordt verdubbeld. Opgepast: specificaties mogen ondergedetermineerd zijn. Elke entiteit met een ‘ mag ingevuld worden naar wens, de constanten moeten dus aangeduid worden in de signatuur! Het ksischema is vergelijkbaar met het deltaschema, alleen wordt in het predicaat toegevoegd dat alle enteiten constant blijven. Door het deltaschema en het ksischema te gebruiken verdwijnt de nood voor het origineel. Functies worden bekeken als een verzameling van paren. Ipv nr(“naam”)=telnummer kan men dus (“naam”,telnummer) element van nr schrijven Voorbeeld p51-56 Modelspecificatie met Object-Z Object-Z lost het probleem van meerdere entiteiten voor een klasse. Een klassedefinitie in Object-Z bestaat uit een aantal Z-schema’s. Het Object-Z schema begint ook eerst met de naam van de klasse. Dan wordt er een lijst van constanten gegeven. Als men klasseconstanten wilt definiëren, dan moeten we een predicaat opgeven onder de constantenlijst. (p57) Dan hebben we een beschrijving van de klasse. Daaronder een schema met attributen en onderdelen: het toestandsschema. Object-Z ondersteunt aggregatie, waardoor objecten van andere klasse deel kunnen uitmaken van een object. De waarden van attributen kunnen onderhevig zijn aan voorwaarden (deze stellen tenslotte de toestand voor). Deze attributen zijn welliswaar specificatieattributen en geen implementatieattributen, maar aangezien 44 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) ze niet uniek bepaald zijn in Abs kunnen ook hier rep-invarrianten en abstractiefuncties gebruikt worden. Daaronder volgen de operatieschema’s, aangezien het om specificatie gaat zijn alle operaties publiek. De rep-invarriant maakt onderdeel uit van de pre- en postconditie. Deze moet evenwel niet expliciet vermeld worden. Het eerste schema is altijd het Initschema. Aangezien alle verschillende schema’s kunnen samengevoegd worden, is er maar 1 initschema. Ook zijn hier geen accentenvariabelen: alleen de eindtoestand is bepaald. Voor de andere operaties (schema’s) is er een nieuw element: de Deltalijst die aangeeft welke attributen en onderdelen kunnen veranderen. Als het niet vermeld staat, mag het niet veranderd worden (soortgelijk de wijzigtclausule). Ook de pre- en postcondities zijn niet expliciet vermeld, deze zijn vaag af te leiden uit het predicaat. De levensloop van de algebraïsche specificatie is hier beschouwd als de geschiedenis van een object. Hier hebben we een sequentie, waarin toestanden en operaties elkaar afwisselen. De eerste is de initiële toestand, bepaald door de INIToperatie. Deze is afhankelijk van parameters, en zal dus verschillende objecten kunnen weergeven. Daarna volgen alle doorlopen toestanden, en de operaties die deze overgang veroorzaakten. Een toestand in de Object-Z (Z-toestand) is anders dan bij een algebraïsche specificatie (A-toestand). Hier wordt er gebruikt gemaakt van attributen, terwijl bij de A-toestand wordt uitgegaan van antwoord op niet-triviale vragen. Er is ook geen 1-1 relatie tussen beide:als we 2 geschiedenissen die dezelfde Z-toestand voorstellen beschouwen zullen deze 2 levenslopen ook dezelfde A-toestand voorstellen. Maar als deze 2 geschiedenissen verschillende Z-toestanden voorstellen (attributen verschillen) kunnen deze toch dezelfde A-toestand voorstellen. Enkel als de Z-toestanden door de Abstractiefunctie op hetzelfde element uit Abs worden afgebeeld, zullen ze ook gelijke A-toestanden voorstellen. (voorbeeld p 59) Samengestelde objecten zijn objecten die deelobjecten hebben. - Elk object A bevat een vast aantal objecten B => benoemde aggregatie - Een object A bevat een variabel aantal objecten B => functies of sequenties. Met een functie kunnen we aggregatie modelleren, associatie kan dmv Aggregatie bij niet-objectgerichte modelspecificaties en algebraïsche specificatie: hier kan niet op verschillende niveaus van detaillering gewerkt worden. Dit is resp. een noodzaak (geen duidelijke hiërarchie) of een principezaak (enkel het uitwendige bekijken). 45 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Statisch (klassendiagram) Zo kunnen we een statisch klassendiagram omzetten naar een Object-Z specificatie. Alleen de samenwerking tussen de klassen kunnen we niet vatten. Hiervoor moet je een object invoeren op een hoger niveau dat deze samenwerking aanduid in zijn operatieschema’s. In zijn toestandschema’s kan hij aangeven welke objecten er voorkomen(lijst van constanten), welke de verbindingen er zijn (associaties, signatuurgedeelte) en de eigenschappen hiervan (predicaat). Dit is dan weer meer dan het UMLdiagram kan tonen. (voorbeeld p60). We voegen nu ook een extra schema in: het fischema. Dit schema stelt is het raamschema, dat ervoor zorgt dat we 1 element uit een domein kunnen verwijderen (p61). Deze duiden zelf geen operaties aan, maar kunnen wel opgenomen worden in het schema voor een operatie. Dynamisch (sequentiediagram) Voor het uitwisselen van symbolen hebben we de symbolen || en = met een ^op. = (met een ^ op) identificeert een operatie van een object met de operatie van een deelobject. Hiervoor geldt dat het linkerlid de invoerparameter overneemt van het rechterdeel || bepaald dat de gelijknamige uitvoerparameters links en invoerparameters rechts worden gekoppeld. Ook voor grotere systemen voorziet Object-Z een klassenschema voor deelsystemen, en maakt hier geen onderscheid in met klassen. Bij UML is er een basisniveau dat gekozen wordt, en alles erboven is een systeem. Dit is bij Object-Z niet het geval, alles is een klassenschema. Als een object dieper moet gespecificeerd worden, hoeft men dit gewoon te splitsen en verder uit te werken. Overerving Polymorfisme eist dat we een element van een deelklasse kunnen gebruiken als element van een bovenklasse. Aggregatie mag dan ook nooit als overerving beschouwd worden. Bij overerving kunnen parameters ook hernoemd worden. (p67) Bij overerving wordt standaard alle elementen en operaties van de bovenklasse overgenomen, alleen de bijkomende elementen en de wijzigingen moeten vermeld worden. Een nieuw schema, dat gebruik maakt van overerving is dus slechts een uitbreiding op het oud schema. Na de naam van de bovenklasse volgt een lijst met substituties. Bij het operatieschema moeten we enkel de nieuwe elementen vermelden. Als we een functie willen overschrijven, moet dit gebeuren door in de lijst met substituties ‘redef functienaam’ te zetten. 46 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Vergelijking Gebeurtenistalen (algebraïsche specificatie) Voordeel: Deze manier sluit nauw aan bij de testpraktijk. Men bepaald wat de uitvoer moet zijn van sequenties van test, waardoor dit makkelijk te controleren is. Bij een gebeurtenistaal is het onmogelijk om de implementatie te bepalen, waardoor men niet geremd wordt door deze veronderstelling. Nadeel: De specificaties doen zeer eigenaardig aan en zijn vrij ingewikkeld. Men kan namelijk geen specificatie van een operatie op zich geven, enkel een combinatie van operaties kan worden gedefinieerd. Bij het beschrijven van een systeem mogen we geen interne delen onderscheiden, waardoor de beschrijving van het hele systeem een groot en complex geheel wordt. Alles moet afgehandeld worden op het niveau van de operaties, waardoor men niet kan ‘groeperen per object’ zoals een klassendiagram. Aggregatie is dan ook principieel onmogelijk. Modeltalen (UML/ Object-Z) Voordeel: Deze sluiten beter aan bij de klassieke praktijk van de post- en precondities. Ze beschrijven een operaties ook 1-voor-1. Bij het beschrijven van het systeem delen we dit op: een klassendiagram (alle mogelijke objecten), een takendiagram (alle mogelijke taken), … Hierdoor wordt de beschrijving overzichtelijk. Nadeel: Ze hebben een noodzaak om toestanden te beschrijven adhv attributen. Dit zorgt voor problemen: welke attributen moeten als originele en welke als afgeleide worden beschouwd? Het werken met toestanden stuurt ook de implementatie. Deze implementatie kan pas goed gekozen worden als de belangrijke eigenschappen van de structuur bepaald zijn (de specificatie). Universeel Het specificeren van attributen doorbreekt de modulariteitseis dat de grens van de module moet worden beschreven onafhankelijk van het inwendige. Daarom zijn gebeurtenistalen zuiverder dan modeltalen. De nadelen hiervan zijn dat het rap een groot kluwen wordt. 47 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) H20: Petrinetten en parallelle systemen Door het oprukkende parallellisme (threads, sockets, …) wordt het testen van code zeer moeilijk. Fouten kunnen namelijk voorkomen door de samenhang van de processen. Zo zijn er deadlocks mogelijk, starvation en data races, waarbij het resultaat wordt beïnvloed door de volgorde waarin de delen van verschillende processen worden uitgevoerd. Debuggen is dan onmogelijk. Men kan niet systematisch alle mogelijkheden afgaan, en als men een fout vind, kan men deze niet betrouwbaar reproduceren. Daarom gaat men de structuur van de te schrijven toepassing formeel beschrijven op een manier waarop kan worden nagegaan of er zich problemen voordoen. Men gaat dan theoretisch alle mogelijke volgordes bekijken, en zien of deze problemen opleveren. Men kan hiervoor pertrinetten gebruiken, hoewel men van de ene formaliteit in de andere kan overgaan, zodat ook statenmachines kunnen gebruikt worden. Petrinetten Een pertrinet is een bipartite gewogen gerichte graaf. Bipartite = 2 soorten knopen, en een tak verbind telkens twee objecten van de verschillende soorten. Hier zijn dit plaatsen (cirkels) en transities (rechthoeken). Alle takken gaan van een plaats naar een transitie of omgekeerd. Gewogen= het gewicht van een tak is strikt geheel positief (en slechts getekend als groter dan 1). De toestand van het net wordt aangegeven door een markering, en elke plaats kan een aantal tokens (zwarte stippen) bevatten. De markering geeft aan hoeveel tokens elke plaats bevat en kan dus als functie M beschouwd worden. Een markering M1 < M2 als M1(p) < M2(p) voor elke plaats p. De combinatie van petrinet met een markering is een gemarkeerd net. Een transitie is geladen als in elke voorganger minstens evenveel tokens zitten als het gewicht van de verbinding. Uit alle geladen transities wordt dan 1 gekozen en afgevuurd. De tokens worden verdeeld adhv de gewichten op de verbinding. Het aantal tokens kan dus verschillen na deze actie. Verbodsverbindingen (verbinding tussen plaats en transitie met een cirkel op einde) zorgen dat de transitie niet kan niet kan afvuren als de plaats een token bezit. een verzameling van voorganger van knoop k is (normaal bolletje, hier *) *k en een van opvolgers k*, terwijl een verzameling elementen een zak z is. Het aantal elementen in de zak is |z| en kan leeg (0) zijn. *k en k* zijn dus zakken van knopen. Een markering van een net is een zak van plaatsen. Als t een transitie is, dan zijn *t en t* markeringen. *t is dan de kleinste markering waarin t geladen is. En t* het resultaat na het afvuren van t. Een transitie is geladen in markering M als *t < M. Als t dan afvuurt is M’ = M - *t + t*. 48 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Een bereikbaarheidsanalyse zoekt welke bereikbaarheidsgraaf men kan bekomen. N is een pertinet, en M(N) is de verzameling van markeringen. Als we een vaste markering M0 nemen kijken we voor deze markering welke transities geladen zijn. Elke geladen transitie kan resulteren in een nieuwe markering. Zo kunnen we de bereikbaarheidsgraaf van N en M0 opstellen. Hierop kan men de volgorde van de transities bekijken, die overeenkomen met stukken code. Door deze bereikbaarheidsgraaf kan men makkelijk een testomgeving ontwerpen. Een bereikbaarheidsgraaf is beperkt in grootte als - het aantal tokens en plaatsen beperkt is er geen transitie is die meer tokens produceert dan dat hij verbruikt en men met winst opnieuw deze transitie kan starten. - Er geen transitie is die spontaan kan starten (*t=0) Als de graaf beperkt is in grootte spreekt men van een begrensde pertinet. Voor de bereikbaarheidsanalyse wordt de volgende terminologie gebruikt: - Een transitie t is levend als er vanuit elke markering M van de bereikbaarheidsgraaf een graaf M’ kan bereikt worden waarin t geladen is. Het gemarkeerde net is levend als al zijn transities levend zijn. Een transitie is dood als er geen enkele markering in de bereikbaarheidsgraaf zit waarin t geladen is. Een dode transitie is evenwel nooit dood in alle markering. Een markering M zit in een impasse als alle transities dood zijn. Een transitie kan noch dood noch levend zijn. Hiërarchische petrinetten Hergebruik is bij modellering belangrijk. Petrinetten moeten dan ook kunnen worden opgesplitst. Zo verkrijgen we een hiërarchie: een net bestaat uit plaasen, transities en deelnetten, samen met hun verbindingen. Alle delen krijgen een interface die bepaald wordt door het inwendige. Deze interface bestaat uit 4 soorten pinnen: naar de in- of uitgang van transities of plaatsen. Meestal worden alleen plaatsen van buiten het subnet verbonden met transities binnen, behalve als het subnet een plaats voorstelt (P-netten), deze vervangen een plaats of een pin in het bovenliggende net. Een gesloten net is een net zonder pinnen en kan opengevouwd worden tot een petrinet. Soms moet men met synchronisatieverbindingen werken. Stel dat 2 transities in 2 verschillende deelnetten tegelijkertijd moeten worden afgevuurd. Deze worden dan meestal vervangen door 1 transitie en de in- en uitgangen worden samengevoegd. Om beide subnetten gescheiden te houden wordt een synchronisatieverbinding gebruikt (p 76) 49 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Voorbeelden van petrinetten Statennet Een statennet komt overeen met een statendiagram uit UML. Dit net geeft vaak de staten van een object weer. Elke staat komt zo overeen met een plaats in het net. Typisch voor een statennet is: - Elke transitie heeft 1 ingang en 1 uitgang. Alle gewichten zijn gelijk aan 1 De bedoeling van het statennet is dat het in een groter net de staat weergeeft waar het object zich in bevind. Het startpunt in het statendiagram stelt dan de plaats voor in het net waar het token kan binnenkomen in het net. Het eindpunt is de plaats waar dit token verdwijnt. Er is dan ook maximaal 1 token toegelaten in het net. Het is ook mogelijk dat een object bepaalde staten niet gebruikt, het statennet zal dan minder plaatsen hebben dan toestanden in het UML statendiagram. Het statennet heeft dus de eis dat |*t| = |t*| = 1 voor alle transities. Takennet Deze modelleert een takengraaf zoals reeds in hoofdstuk 16 gezien. Het takennet geeft de afhankelijkheden weer tussen de verschillende deeltaken van een project. Voor elke taak is er dan een transitie. Als de taak moet wachten op een andere taak, dan wordt er een plaats voorgezet die de tokens van de voorafgaande taken verzamelt, het gewicht van de verbinding stelt dan het aantal taken voor waarop gewacht dient te worden (voorbeeld p77). Als we dit takennet willen gebruiken, moeten we hier een P-net van maken, door vooraan (i) en achteraan (f) een plaats toegevoegd. i leidt naar een transitie die een token aanmaakt voor elke traak met ingraad 0 en elke dergelijke taak wordt aangevuld met een plaats om dit token op te vangen. Hetzelfde wordt achteraan gedaan, zodat er juist 1 token in f terecht komt als de taken zijn afgehandeld. Dit net moet aan 2 zaken voldoen: - Er zijn 2 speciale plaatsen i en f waarbij i geen voorgangers en f geen opvolgers heeft. *i = f* = 0 - Elke andere knoop ligt op een pad van i naar f. De takengraaf is dus slechts een speciaal geval van een P-net, waarbij een hoop voorwaarden niet verplicht zijn: - Elke transitie heeft ingraad 1 - Elke plaats heeft uitgraad 1 - Het bevat geen lussen. We kunnen nu P-netten gebruiken als bouwsteen. Een plaats p in een net N kunnen we nu vervangen door een P-net P dat de verschillende taken van deze plaats bepaald. Aan het net N mag geen wijziging gemerkt worden. Dit heeft verfijning 50 Samenvatting Systeemanalyse II – Dieter Van der Stock(‘07-‘08) – Koen Hoof (’09-’10) Voor elk token dat toekomt in i moet er dus juist 1 token in f uitkomen, en mag er geen achterblijven. Een net dat aan deze voorwaarde voldoet voor k tokens, is k-robuust. Een net dat k-robuust is voor alle mogelijke waarden k is robuust. Voorbeeld p 79 Dikwijls hebben we ook een module dat verschillende soorten berichten kan verwerken. Deze worden gemoduleerd door een T-net. Een T-net is een petrinet met een aantal ingangstransities en een aantal uitgangstransities. Voor ingangstransitie t is *t = 0, en voor uitgangstransitie is t* = 0. De voorwaarden voor een T-net: - We moeten een P-net bekomen als we alle ingangstransities verbinden met een nieuwe plaas i en alle uitgangstransities met een plaats f Het is dus de bedoeling (in tegenstelling tot een takennet) om een token te verwerken langs een weg binnen het net. Ook hier spreekt men ven (k-)robuustheid als het P-net dit is. Nu kunnen we ook een transitie t in net N vervangen door een monadisch T-net. Dit is een T-net dat juist 1 begin- en eindtransitie heeft. Ook dit heet verfijning.