EXAMEN SOFTWAREONTWIKKELING II 2 DE BA. INFORMATICA EERSTE EXAMENPERIODE ACADEMIEJAAR 2012 2013, SESSIE 1 Vrijdag 7 juni, 2012, 8u30 Naam : Opmerkingen vooraf (i) (ii) Je wordt niet verondersteld de Java-API uit het hoofd te kennen. Indien je niet zeker bent van een methodenaam of signatuur, mag je dit zeker vragen aan de begeleiders op het examen. Bij een aantal vragen wordt je antwoord gevraagd in de vorm van een UML klassendiagram. Zorg dat deze diagrammen duidelijk (werk dus verzorgd!) en zo volledig mogelijk zijn. V1 V2 V3 V4 V5 Vraag 1: Software Levenscyclus a. Om software onderhoudbaar te maken, bestaan er verschillende technieken in software-engineering. Geef en beschrijf kort 5 verschillende technieken. Techniek 1: Beschrijving: Techniek 2: Beschrijving: Examen Softwareontwikkeling (II) 1
Techniek 3: Beschrijving: Techniek 4: Beschrijving : Techniek 5: Beschrijving: b. Waarom mag een snel prototype niet als eerste versie van het product door de klant in dienst genomen worden? Examen Softwareontwikkeling (II) 2
c. Wat verstaat men onder incrementele ontwikkelmodellen. Illustreer met een figuur. Geef enkele voordelen van een dergelijk model. Wat? Figuur: Voordelen: d. Wat is een contract tussen subsystemen en waarom is dit afsluiten van contracten belangrijk? Wat? Waarom belangrijk? Examen Softwareontwikkeling (II) 3
Vraag 2: Object-geörienteerd Programmeren: Testen De methode teldna() heeft 1 argument van het type String, en geeft als resultaat een rij van vier gehele getallen. Het is de bedoeling dat de argumentstring enkel de karakters A, C, T en G bevat, en dat het resultaat het aantal keer bevat dat een karakter voorkomt (r[0] geeft weer hoeveel keer het karakter A voorkomt, r[1] hoeveel keer het karakter C, r[2] hoeveel keer het karakter T en r[3] hoeveel keer het karakter G.). Noemen we dna de argumentstring, dan moet de methode het onderstaande gedrag vertonen: - indien s op de waarde null staat, wordt een exceptie van het type NullArgumentException opgegooid - indien de String dna de lengte 0 heeft (geen karakters bevat), dan is het resultaat een gehele rij met lengte 4, waarbij elke teller op 0 staat ( [0,0,0,0]) - indien de String dna een lengte heeft strikt groter dat 0: o indien een karakter voorkomt dat verschilt van A, C, G en T, dan wordt een exceptie van het type InvalidCharacterException opgegooid o indien de String s enkel toegelaten karakters bevat, dan bevat het resultaat van de methode een rij van 4 gehele getallen. Noemen we de rij r, dan bevat r[0] het aantal keer dat A voorkomt in s, r[1] het aantal keer dat C voorkomt in s, r[2] het aantal keer dat T voorkomt in s en r[3] het aantal keer dat G voorkomt in dna. Voor de volledigheid, vind je hieronder een mogelijke implementatie van die methode. class InvalidCharacterException extends Exception { class NullArgumentException extends Exception { // public int[] teldna(string dna) throws InvalidCharacterException,NullArgumentException { int[] r=new int[4]; if(dna==null) throw new NullArgumentException(); else { for(int i=0;i<dna.length();i++) { char c=dna.charat(i); switch(c) { case 'A':r[0]++;break; case 'C':r[1]++;break; case 'T':r[2]++;break; case 'G':r[3]++;break; default : throw new InvalidCharacterException(); return r; Examen Softwareontwikkeling (II) 4
a. Geef een minimaal stel testvectoren om deze methode via de black-box-aanpak te testen. Argumenteer. b. Als bijkomend gegeven is dat de lengte van de String dna hoogstens N bedraagt, hoeveel testvectoren heb je dan minimaal nodig om padbedekking te realiseren? Argumenteer. Examen Softwareontwikkeling (II) 5
c. Schrijf voor 2 testcases die je in onderdeel a. beschreven hebt, de JUnit-versie uit, namelijk een testcase waarvoor het opgooien van een exceptie het verwachte resultaat is, en een testcase waarvoor de methode een zinvol (d.w.z. verschillend van een exceptie) resultaat geeft. @Test public void testnormaal() throws InvalidCharacterException,NullArgumentException { String s="actgactg"; int[] r=teldna(s); Assert.assertTrue(r[0]==2); Assert.assertTrue(r[1]==2); Assert.assertTrue(r[2]==2); Assert.assertTrue(r[3]==2); @Test(expected=InvalidCharacterException.class) public void testillegalcharacter() throws InvalidCharacterException,NullArgumentException{ String s="actgactx"; int[] r=teldna(s); @Test(expected=NullArgumentException.class) public void testnullstring() throws InvalidCharacterException,NullArgumentException{ String s=null; int[] r=teldna(s); Ook goed: @Test(expected=InvalidCharacterException.class) public void testillegalcharacter() throws InvalidCharacterException,NullArgumentException{ try { teldna( ACTGACTX ); fail(); catch(invalidcharacterexception e){ Assert.assertTrue(true) Fail(); @Test(expected=NullArgumentException.class) public void testnullstring() throws InvalidCharacterException,NullArgumentException{ try { teldna( ACTGACTX ); fail(); catch(invalidcharacterexception e){ Assert.assertTrue(true) Fail(); Examen Softwareontwikkeling (II) 6
Test Case 1: Test Case 2: Examen Softwareontwikkeling (II) 7
Vraag 3: Ontwerppatronen a. Probleem 1: Sorteerbare collecties Beschouw onderstaand klassendiagram, waarbij een Collectie een reeks objecten bevat die van het type Sortable zijn. De default-implementatie van de klasse slaat deze objecten op in de volgorde waarin ze toegevoegd werden. Van deze default-implementatie worden twee klassen afgeleid, die gesorteerde versies implementeren: dit houdt in dat voor het lezen van een object via get() of getfirst() de Collectie eerst gesorteerd wordt. Twee varianten worden geïmplementeerd, namelijk een sortering via bubble sort en een sortering via quick sort. We wensen dat die sorteeralgoritmen in een bredere context (dus buiten de context van Collecties) bruikbaar zijn, en dat het sorteeralgoritme at runtime kan vastgelegd worden. Welk ontwerpspatroon wordt hier best ingezet en geef de principiële oplossing in een UML klassendiagram. Patroon: Oplossing: Examen Softwareontwikkeling (II) 8
b. Probleem 2: nieuwe sockets Een Toepassing is geschreven gebruik makend van de klasse Socket om netwerkfunctionaliteit te realiseren (zie onderstaand UML klassendiagram). Er komt een nieuwe, interessante klasse NewSocket beschikbaar, die wat functionaliteit toevoegt (namelijk eenvoudiger creatie van een verbinding, en de mogelijkheid om berichten al dan niet gecomprimeerd te versturen). We wensen de Toepassing gebruik te laten maken van deze nieuwe klasse, waarbij enkel de klasse Socket aangepast mag worden (de broncode van de klasse NewSocket is niet beschikbaar). Welk patroon gebruik je om dit met zo weinig mogelijk aanpassingen te realiseren? Geef je oplossing in de vorm van een UML klassendiagram. Geef voor 1 van de methoden van de klasse Socket een implementatie. Patroon: Oplossing: Implementatie: Examen Softwareontwikkeling (II) 9
c. Probleem 3: plannen van taken Om Jobs op een processor in te plannen, wordt gebruik gemaakt van een object dat de interface Scheduler implementeert. Verschillende planningsalgoritmen zijn voorhanden (namelijk gebaseerd op prioriteit, gebaseerd op een preëmptieve aanpak of gebaseerd op time slicing). Anderzijds maakt een scheduler ook gebruik van primitieven aangeboden door het onderliggend besturingssysteem (in dit geval Linux en Windows). We gaan ervan uit dat de primitieven aangeboden door de verschillende besturingssystemen qua betekenis gelijk zijn, maar qua oproepsyntax (i.h.b. methodenaam) kunnen verschillen. Dit resulteert in een ontwerp zoals weergegeven in onderstaand UML klassendiagram. Als er dus een besturingssysteem bijkomt, moeten we 3 nieuwe klassen voorzien, wat uiteraard veel werk is. We wensen dit te vermijden, en zoveel mogelijk logica en implementatie te splitsen. Welke patronen (1 of meerdere) kan je hiervoor inzetten? Geef je oplossing in de vorm van een UML klassendiagram. Patroon: Oplossing: Examen Softwareontwikkeling (II) 10
d. Wat is een dynamische proxy en welk probleem wordt hiermee opgelost? Wat? Welk probleem? e. Uitvoer Beschouw onderstaande Java-code. Welke uitvoer wordt hier gegenereerd? Argumenteer. class B { void g(a a) {System.out.print("0"); void g(a1 a) {System.out.println("1"); void g(a2 a) {System.out.println("2"); class A { void f(b b){ b.g(this); class A1 extends A { class A2 extends A { void f(b b){ b.g(this); class Main { public static void main(string[] args){ A[] a={new A(),new A1(),new A2(); for(a i:a) i.f(new B()); Uitvoer: Argumentatie: Examen Softwareontwikkeling (II) 11
Vraag 4: Multithreading Beschouw onderstaande code, die als doel heeft een GUI te starten, waarbij het indrukken van een knop een taak opstart. Tijdens het uitvoeren van deze taak worden tussenresultaten gerapporteerd aan MyFrame. class MyFrame extends JFrame { private JButton button=new JButton("(Re)start."); private JLabel label=new JLabel("#5 : 0 "); private volatile int n5=0; private volatile boolean done=false; public MyFrame(String title){ super(title); GridLayout layout=new GridLayout(1,2); Container cp=getcontentpane(); cp.setlayout(layout); cp.add(button); cp.add(label); button.addactionlistener(new ActionListener() { public void actionperformed(actionevent e) { Incrementor inc= new Incrementor(MyFrame.this); n5=0; button.setenabled(false); inc.start(); while(!(done=inc.isdone())); System.out.println("######### n5 = "+n5); label.settext("#5 : "+n5); button.setenabled(true); ); public void increment(){ n5++; // druk het tussenresultaat af voor logging if(n5%100==0) System.out.println(" -> n5="+n5); class Incrementor extends Thread { private MyFrame frame; private boolean done=false; public Incrementor(MyFrame frame){ this.frame=frame; public void run() { // complexe code die lang rekent for(int i=0;i<10000;i++) { int r=(int)(10*math.random()); if(r==5) frame.increment(); done=true; public boolean isdone(){ return done; Examen Softwareontwikkeling (II) 12
a. Waarom vormt de callback frame.increment() vanuit het object van het type Incrementor een probleem? Hoe los je dit op (geef een Java-fragment dat duidelijk deze oplossing weergeeft)? Waarom een probleem? Oplossing: b. De code bevat een busy-wait. Waarom is dit een probleem? Hoe los je dit op (geef opnieuw een Java-codefragment dat duidelijk deze oplossing weergeeft)? Waarom een probleem? Oplossing Examen Softwareontwikkeling (II) 13
c. Leg het Producer-Consumer paradigma uit. Examen Softwareontwikkeling (II) 14
Vraag 5 : Componenten Gegeven onderstaande code die de klassen voor een verkeerslicht en een bijhorende controller (die bedoeld is om de hardware effectief aan te sturen, maar hier geïmplementeerd is als logger). class InvalidArgumentException extends Exception { class TrafficLight { protected String color,title; protected Controller controller; public TrafficLight(String title){ color="red"; this.title=title; public void setcontroller(controller controller){ this.controller=controller; public void setcolor(string color) throws InvalidArgumentException { boolean valid=color.equals("red") color.equals("orange") color.equals("green"); if(!valid) throw new InvalidArgumentException(); this.color=color; controller.notify(color); public String getcolor() { return color; public String tostring(){ return title; class Controller { protected int ID; public Controller(int ID){ this.id=id; public void notify(string color){ System.out.println(" "+ID+" : -> "+color); We wensen deze code aan te passen, gebruik makend van het JavaBeansmodel, zodat - de logica die nagaat of de nieuwe toestand van een object van het type TrafficLight al dan niet geldig is, afgsplitst wordt van de klasse TrafficLight - de koppeling tussen TrafficLight en Controller niet hard gecodeerd wordt - er bijkomend verkeerslichten kunnen gecoördineerd worden, zodanig dat nagekeken kan worden of ze logisch tot hetzelfde kruispunt behoren. Hierbij moet Examen Softwareontwikkeling (II) 15
geverifieerd worden dat, indien het kruispunt N verkeerslichten bevat er steeds minstens N-1 op rood staan. a. Teken een UML-diagram dat zo nauwkeurig mogelijk je oplossing hiervoor weergeeft. Maak zoveel mogelijk gebruik van de in Java beschikbare Beans-mechanismen (zie bijgevoegde documentatie i.v.m. het JavaBeans-model) Examen Softwareontwikkeling (II) 16
b. Geef een Java-implementatie van de aangepaste Trafficlight-klasse. Examen Softwareontwikkeling (II) 17
Examen Softwareontwikkeling (II) 18
Examen Softwareontwikkeling (II) 19