Critical Design Review $Revision: 1.4 $ Software Engineering, Groep 1 Wouter Van den Broeck - wjvdbroe [at] vub.ac.be Brecht Desmet - bdesmet [at] vub.ac.be Table of Contents Introductie Doel en bereik van dit document Definities, acroniemen, & afkortingen Referenties Overzicht primaire design principes Design vereisten Uitbreidbaarheid Overzicht Mogelijke uitbreidingen Efficiëntie Abstractie Beschouwingen Voordelen Voordelen van een ontwerp mbv toestandsmachine Voordelen van het gebruik van de sessiefunctionaliteit voorzien in DvCGI Nadelen Nadelen van het huidige ontwerp Nadelen van het gebruik van de sessiefunctionaliteit voorzien in DvCGI Bemerkingen betreffende beveiliging Revisie geschiedenis Introductie Doel en bereik van dit document Dit document bevat het verslag van de evaluatie van het voorgestelde ontwerp van het eToets-Systeem van groep 1 voor het vak Software Engineering, Vrije Universiteit Brussel, academiejaar 2003-2004. Het betreft het ontwerp zoals beschreven in de SDD, en uitgewerkt in de finale implementatie. Dit verslag behandeld de design-vereisten, de voor- en nadelen, en gaat dieper in op de geleerde lessen en potentiële verbeteringen. Een (tussentijdse) review van het ontwerp van de HTML vormgeving van het product is voorzien in reports\sdd\prototype-review.lyx. Definities, acroniemen, & afkortingen Voor algemene definities, acroniemen, & afkortingen zie: Algemene definities, acroniemen, afkortingen [http://wilma.vub.ac.be/~se1/documents/definities.html]. Referenties Zie Algemene Referenties [http://wilma.vub.ac.be/~se1/documents/referenties.html], en Bibliografie onderaan dit document, voor meer verwijzingen. Overzicht primaire design principes Het huidige design steunt op een aantal centrale concepten: Sessie-beheer: Bouwt op de sessie functionaliteit voorzien door de 'DvCgi library'. Een gebruikersessie die loopt over verschillende request-reply interacties tussen gebruiker en systeem is bevat in een proces/thread. Alle state-data kan dus bevat worden in dit proces, en opslag met bijhorende (de)serializatie is niet nodig. Toestandsmachine: Een gebruikersessie wordt beschouwd als een reeks opeenvolgende toestanden waarbij logische verbanden (mbt bv opeenvolging) tussen toestanden gerespecteerd worden. Elke toestand is voorzien als een klasse waarin de toestandspecifieke implementatie voorzien is. Deze toestandklassen vormen een hiërarchie wat betreft overerving en specialisatie van functionaliteit. De state-data zoals bijgehouden in de sessie (zie hierboven) is principieel een verwijzing naar de huidige toestandsinstantie. Adapters naar externe functionaliteit: De communicatie tussen toestanden en externe componenten (bv. gebruikersvalidate en opslag van inter-sessie gegevens) vind plaats via adapters. Deze voorzien in een strikte scheiding tussen de domein- en externe componenten. Scheiding van structuur en representatie in gebruikersinteractie: De toestanden genereren XML-data die dient als basis voor de interactie met de gebruiker. Aan de hand van deze 'semistructured' data kan de concrete interface voorzien worden. Design vereisten Het design dient de vereisten zoals gespecificeerd in de SRS te respecteren. Dit betreft enerzijds functionaliteitspecifieke vereisten, en algemene vereisten zoals uitbreidbaarheid, platform-onafhankelijkheid, efficiëntie, etc. anderzijds. Uitbreidbaarheid Overzicht Gezien de eenvormige en coherente structuur van de toestandenhiërarchie, is de vereiste tot uitbreidbaarheid wat betreft de centrale interactieve functionaliteit grotendeels gerespecteerd. Nieuwe toestanden kunnen probleemloos toegevoegd worden. De knelpunten die zich voordoen zijn: Het specificeren van de transities tussen bestaande toestanden en nieuw toegevoegde toestanden vereist een ingreep in de bestaande toestanden en/of een centrale locatie. Het specificeren van bijkomende gebruikerscommando's die door nieuwe toestanden afgehandeld kunnen worden vereist een ingreep in de centrale dispatcher. Mogelijke remediëringen hiervoor zijn: Uitwerken van een transitie-abstractie volgens geavanceerde 'state design patterns' zoals bijvoorbeeld terug te vinden in "Finite State Machine Patterns" (Yacoub et. al, 1999, in "Pattern Languages of Program Design 4"). Uitwerken van een systeem waarbij toestanden door hun 'herkende' gebruikerscommando's kunnen registreren in een geavanceerde dispatcher. Deze dispatcher wordt verder uitgebreider behandeld. Wat betreft uitbreidbaarheid naar andere externe componenten is er ook geen probleem dankzij de adapters. Door de scheiding van de structuur en representatie van de gebruikersinteractie is het perfect mogelijk andere interactie-media te voorzien zoals bijvoorbeeld een 'dedicated' client, Mozilla XUL, een Macromedia Flash 'rich-media' client, etc. Specialisatie van functionaliteit kan in vele gevallen voorzien worden dmv subklassen. Zo kan men bijvoorbeeld bijkomende verbeter strategieën voorzien dmv nieuwe subklassen van Strategy. Tenslotte laat de scheiding van structuur en representatie toe om alternatieve lay-out van de HTML, of een totaal verschillend gebruikersinteractiemechanisme, te voorzien door alternatieve XSL en/of CSS stylesheets te voorzien. Mogelijke uitbreidingen De hiervoor vermelde mogelijke uitbreidingen bieden perspectieven mbt de volgende domein-specifieke funtionaliteiten: Proef-toetsen twee mogelijke visies: Resultaat van proeftoets moet bijgehouden worden. Hierbij dient de gebruiker gekend te zijn. Proeftoets kan door iedereen, zonder in te loggen, afgelegd worden, zoals bv. het examinatiesystemen beschikbaar in het VUB Zelfstudie-centrum. De resultaten kunnen hierbij na afloop van de toets weergegeven worden. De resultaten kunnen echter niet worden bijgehouden daar de gebruiker niet gekend is. Voor deze functionaliteit dienen de volgende uitbreidingen voorzien te worden. transitie bouwen die rechtstreeks naar ValidatedState gaat gedragscode van bepaalde operaties (bv. wegschrijven naar database) aanpassen StudentType/AnonymType Quizzen kan een meer gesofisticeerde verbeterstrategie wensen (evt. Strategy-object uitbreiden met score tot dan toe) verwacht een luchtigere gebruikersinterface (OK) wegschrijven van resultaten is niet altijd wenselijk, punten drukken geen verhoudingsgetal uit (OK) Enquêtes score-verwerking/presentatie moet anders gebeuren opslaan van detailresultaten is meestal niet wenselijk geen login vereist, of login krijgt een nieuw karakter: een gebruiker kan maar één keer een enquête kan afleggen (zie onderwijsevaluatie) LoginState corrigeren naast StudentType en AnonymType, een nieuwe InterviewType voorzien ScoreState corrigeren in principe zal de database bijna niet aangepast hoeven te worden Efficiëntie Het thread-gebaseerde sessiebeheer vermijdt de noodzaak om toestandsdata op te slaan en op te halen, en de daarbij noodzakelijk serialisatie en deserialisatie. Dit komt de efficiëntie enerzijds ten goede, maar vergt meer activiteit op systeemniveau. We gaan er echter van uit dat de efficiëntie van het onderliggende systeem optimaal is, en dat de kost van deze aanpak kleiner is dan het alternatief met opslag van toestandsdata. De centrale gebruikerscommando's dispatcher is momenteel voorzien als een grote 'if-then-else' constructie. Dit is een belangrijk pijnpunt, en is een primaire kandidaat voor verbetering. In concreto zou een geavanceerde dispatcher (zoals hierboven reeds aangehaald en later uitgebreider behandeld) de mapping tussen commando's en verwerkende toestanden kunnen voorzien dmv een hash-tabel met een O(1) access-performantie. Dit is een duidelijke verbetering van de huidige O(n) performantie (met n := het aantal aanvaarde commando's). Abstractie Essentieel bij abstractie is de ontkoppeling van componenten. Op een hoog niveau - interactie tussen kern-systeem en externe componenten - is er dankzij de adapters wat dit betreft geen probleem. Wat betreft de toestandsmachine is er een weinig expliciete koppeling tussen toestanden, maar deze koppeling wordt gereflecteerd in de toestandsklassen-hiërarchie, en is dus duidelijk traceerbaar. Er zijn echter ook een paar secundaire, impliciete koppelingen: de transities tussen toestanden, en de data-vereisten die sommige toestanden stellen, en die moeten worden ingevuld door voorgaande toestanden. Voor een betere abstractie van het geheel van commando-dispatching en transitiecoördinatie is het misschien interessant om te onderzoeken in hoeverre de commando's kunnen worden geïnterpreteerd als de letters van een taal. De grammatica van deze taal zou dan de mogelijke client-server-interactiepatronen specificeren. De dispatcher wordt dan de parser van deze taal. Transities tussen toestanden kunnen gespecificeerd worden als productie-regels in de grammatica. Bij een interpretatie als context-vrije grammatica zou de uitwisseling van toestandsdata tussen toestanden kunnen gestroomlijnd worden dmv de stack in de push-down-automaat. Beschouwingen Voordelen Voordelen van een ontwerp mbv toestandsmachine Fine-grained modulaire aanpak. Het systeem blijft overzichtelijk voor buitenstaanders. iemand die de code nog nooit gezien heeft, zal heel snel 'the hang of it' doorhebben door het eenvoudige maar krachtige opzet. Er zijn geen afhankelijkheden tussen verschillende semi-onafhankelijke applicaties (login.cgi, menu.cgi, ). Als ontwikkelaar beheers je dus het systeem als een geheel. Een hiërarchie met verschillende logische verdiepingen nodigt uit om code te herbruiken. Voordelen van het gebruik van de sessiefunctionaliteit voorzien in DvCGI Omdat elke sessie als een aparte thread voorzien wordt waarin de toestandsdata beschikbaar is zolang de sessie actief blijft, is een mooie implementatie van de toestandsmachine mogelijk. Omdat alle toestandsdata in hun run-time toestand beschikbaar blijven zolang de sessie actief is, is het niet nodig dure operaties uit te voeren om de toestandsdata op te slaan en terug op te halen voor elke activatie van de sessie. Nadelen Nadelen van het huidige ontwerp Er zijn enorm veel klassen. Het systeem is momenteel voorzien als één grote applicatie waardoor de build-time hoog oploopt (+5 min op een standaard PC), wat de ontwikkeling ernstig vertraagt. Een mogelijk remediëring is het opsplitsen van de functionaliteit in verschillende sub-machines/sub-applicaties. Gevoelige punten hierbij zijn het doorgeven van toestandsdata, en mogelijke code-duplicatie. Een opsplitsing van de student en docent functionaliteit lijkt een belangrijke kandidaat. Een andere mogelijkheid is het afsplitsen van basis/deel-functionaliteit in bibliotheken. De specificaties van de transities tussen toestanden zijn momenteel gecentraliseerd en 'hard-coded' voorzien op 1 locatie; de DefaultState klasse. Dit heeft als gevolg dat bij elke wijziging in de work-flow deze klasse dient aangepast. Eerder in dit document werden reeds mogelijke remediëringen gesuggereerd. De functionele kern van het systeem is een grote dispatch die de commando's (die de gebruiker via de gebruikersinterface naar het systeem stuurt) mapt op de verwerkende operators. De mapping is onvermijdelijk omdat de input van de gebruiker altijd geserialiseerd dient te worden als een (byte-)string om het over het netwerk naar de server te kunnen verzenden. Maar in het huidige ontwerp is deze mapping voorzien als een gecodeerde if-then-else constructie, wat niet flexibel en niet efficiënt is. Een betere aanpak zou kunnen bestaan uit het voorzien van een geavanceerde dispatcher. Deze zou voorzien zijn van een hash-tabel met als sleutels de geserialiseerde commando's, en als waarden commando-handler objecten. De dispatcher kan dan de handler opvragen uit de hash-tabel, de handle() method van de handler oproepen, die dan op zijn beurt de correcte operator oproept in de huidige toestand: een eenvoudige en efficiënte O(1) indirectie. De commandoparameters kunnen hierbij in een collectie doorgegeven worden aan de operator zodat deze de vereiste parameters kan opvragen (op naam!). Het zou beter geweest zijn indien een reeks operaties voorzien zou zijn in XMLGenerator voor het opbouwen van het resulterende XML-document door de toestanden. Hierbij zou voor elke concreet XML element een constructie-operatie voorzien moeten zijn. Deze operaties zouden kunnen voortbouwen op de standaard XML-DOM (document object model) interface. Het systeem is niet bestand tegen het gebruik van de back knop in browser. Dit probleem kan misschien eerder toegewezen worden aan de client applicatie. Logisch zou zijn dat de client de back/forward operaties niet toelaat.De kern van dit probleem is dat toestandsdata wordt bijgehouden op de server. Alternatief zou de toestandsdata in de gebruikersrepresentatie kunnen worden bijgehouden. Bijvoorbeeld door middel van verborgen velden in de forms in de HTML pagina's. Maar wat met andere presentatievormen? Dit lijkt dus geen bruikbaar alternatief. Een beter alternatief zou het integreren van het Command design pattern (Gamma et al. 1995). Deze laat 'undo/redo' toe, die rechtstreeks mappen op de 'back/forward' fucntionaliteit voorzien door de HTML-client. Een derde mogelijkheid is aan bod gekomen in DM12 (design meeting) maar werd niet geimplementeerd. Nadelen van het gebruik van de sessiefunctionaliteit voorzien in DvCGI Timeouts kunnen enkel tijdens de constructie van SessionServer-object ingesteld worden, en kan dus niet pe sessie bepaald worden en kan ook niet dynamisch aangepast worden. Het is niet evident de optimale waarde van timeout te bepalen. Enerzijds is langdurige time-out niet wenselijk met betrekking tot belasting van de server, maar anderzijds dient de timeout bij het afleggen van de toets op zijn minst langer te zijn dan de voorzien 'bedenktijd'. Momenteel dient de algemene time-out dus minstens langer te zijn dan de langste, voorziene bedenktijd. Bemerkingen betreffende beveiliging Er werd geen grondige studie uitgevoerd omtrent de veiligheidsaspecten van de SessionServer. Hoe kan je de SessionServer voor de gek houden? Kunnen cookies vervalst worden? In welke mate worden IP-adressen gecontroleerd? Kan SSL een sluitend soelaas bieden? Er is geen beveiliging voorzien voor bots die proberen een connectie met het systeem te maken. Moderne technieken verplichten de gebruiker de karakters die weergegeven staan op een chaotische afbeelding, in te tikken, om aldus te verifiëren dat het echt een mens betreft. Er werd geen beveiliging voorzien tegen paswoord generatoren. Iemand kan makkelijk een stuk software schrijven dat via trial-and-error probeert paswoorden te achterhalen. References Braude, Eric J. (2001) `\"{}Software Engineering: An Object-Oriented Perspective`\"{}. John Wiley & Sons, inc., New York. ISBN: 0471322083.