Angewandte Informatik Dr. Martin Gieseking Universität Osnabrück, 10.2.2005 Zeit: 16:0018:00 Uhr Klausur zur Vorlesung Informatik C Wintersemester 2004/2005 Musterlösung Name: Matrikel-Nr.: Hinweise: Tragen Sie zu Beginn der Klausur auf diesem Blatt Ihren Namen und Ihre Matrikelnummer ein. Alle anderen Seiten versehen Sie bitte oben rechts mit Ihrem Namen. Lassen Sie die Klausurbögen während der gesamten Zeit zusammengeheftet. Lesen Sie die Texte aufmerksam durch! Schreiben Sie Ihre Lösungen bitte direkt unter die jeweilige Aufgabe. Sollten Sie mehr Platz benötigen, können Sie die Rückseiten oder weitere leere Blätter verwenden. Vergessen Sie in diesen Fällen nicht, die Nummer der zugehörigen Aufgabe und ggf. Ihren Namen dort zu vermerken. Aufgaben, die Änderungen an vorgegebenem Programmtext erfordern, können durch Eintragungen in den abgedruckten Quellcode gelöst werden, sofern dort ausreichend Platz vorgesehen ist. Sie können insgesamt 100 Punkte erreichen. Zum Bestehen der Klausur sind mindestens 50 Punkte erforderlich. Es sind keine Hilfsmittel zugelassen! Viel Erfolg! 1 20 2 18 3 16 4 16 5 15 6 15 P 100 Klausur zu Informatik C Name: Aufgabe 1: Prozessmodelle und Testverfahren (4+5+5+3+3 Punkte) (a) Was versteht man unter Extreme Programming (XP) ? Nennen und erläutern Sie drei zentrale Thesen und geben Sie sechs XP-Praktiken an, mit denen die angestrebten Ziele erreicht werden sollen. XP ist ein Vorgehensmodell der Softwareentwicklung. XP verzichtet auf starre Anforderungskataloge und vorgegebene Projektphasen, wie z.B. beim Wasserfallmodell. In sehr kurzen Zyklen werden alle Phasen eines Entwicklungsprozesses durchlaufen, wobei nur die für den aktuellen Iterationschritt relevanten Merkmale implementiert werden. Thesen: • wenn Tests die Softwarequalität verbessern, wird viel und regelmäÿig getestet • wenn Code-Reviews die Softwarequalität verbessern, wird der Code ständig begutachtet • wenn einfacher Code die Softwarequalität verbessert, wird immer die einfachste Lösung gewählt Praktiken: kleine Releases, kontinuierliche Tests, einfacher Entwurf, regelmäÿiges Refactoring, 40-Stunden-Woche, Einbeziehung des Kunden (b) Die Java-Klassenbibliothek enthält die Klasse java.util.Stack, die einen LIFO-ADT repräsentiert. Die Klasse implementiert unter anderem die folgenden Methoden: public class Stack extends Vector { public synchronized Object peek() throws EmptyStackException; public synchronized Object pop() throws EmptyStackException; public Object push(Object item); public int size(); } Geben Sie umgangssprachlich mindestens sechs sinnvolle Testfälle an, um die oben angegebenen Methoden zu testen (andere Methoden der Klasse müssen nicht getestet werden). • pop mit leerem Stack wirft Exception • peek mit leerem Stack wirft Exception • peek liefert zuletzt gepushtes Element • push liefert eigenes Argument • size liefert 0 bei leerem Stack • pop invertiert push 2 Klausur zu Informatik C Name: (c) Erstellen Sie zu zwei der in Aufgabenteil (b) genannten Testfälle einen JUnit Test (als Java-Methode), der diese Testfälle abdeckt. Wählen Sie dabei die beiden Testfälle so aus, dass aus den in JUnit verfügbaren Assertions mindestens einmal eine Variante von assert... und einmal fail verwendet wird. Wählen Sie die assert -Variante so, dass JUnit beim Scheitern eine möglichst präzise Fehlermeldung ausgibt. public void testEmptyStack () { Stack stack = new Stack(); try { stack.pop(); fail("pop() wirft bei leerem Stack keine Exception"); } catch (EmptyStackException e) { } } public void testEmptySize () { Stack stack = new Stack(); assertTrue("size() liefert bei leerem Stack nicht 0", stack.size() == 0); } (d) Sowohl bei Unit-Tests als auch beim Design by Contract kommen Assertions zum Einsatz. Welche Gemeinsamkeiten gibt es bzw. wodurch unterscheiden sie sich? Gemeinsamkeiten: Assertions prüfen, ob ein bestimmter Programmzustand an der angegebenen Stelle eingehalten wird. Ist dies der Fall, passiert nichts, ansonsten wird eine Fehlermeldung produziert. Unterschiede: DBC-Assertions sind Bestandteil des zu prüfenden Programms und beschreiben Invarianten des Codes. Unit-Tests sind kein Bestandteil des Programms. Die Assertions prüfen hier, ob ein Testfall zu ausgewählten Daten das erwartete Ergebnis liefert. (e) Was versteht man unter einem Regressionstest ? Die wiederholte Anwendung von Tests nach Code-Änderungen wird Regressionstest genannt. Mit ihrer Hilfe wird festgestellt, ob das Verhalten des Codes bezüglich der Testdaten stabil bleibt. 3 Klausur zu Informatik C Name: Aufgabe 2: Entwurfsmuster und UML (4+4+10 Punkte) (a) Beschreiben Sie die zentrale Idee des Entwurfsmusters Proxy und stellen Sie die Struktur in Form eines UML-Diagramms grasch dar. Das Proxy-Pattern ermöglicht den kontrollierten Zugri auf die Methoden eines Objekts über einen vorgeschalteten Stellvertreter. Subjekt Client operation() EchtesSubjekt Proxy echtesSubjekt operation() operation() echtesSubjekt.operation() (b) Bei Verwendung des Singleton -Patterns kann es in Verbindung mit Threads zu unerwartetem Verhalten kommen. Beschreiben Sie kurz das Problem und erläutern Sie, wie in Java das korrekte Verhalten sicher gestellt werden kann. Welche Rolle spielt dabei das Double Checked Locking ? Wenn mehrere Threads getInstance() eines Singletons aufrufen, kann es passieren, dass mehrere Instanzen der Singleton-Klasse erzeugt werden. Das korrekte Verhalten kann z.B. durch Synchronistion der getInstance -Methode erfolgen. Das Double Checked Locking spielt dabei keine Rolle. Diese Technik garantiert in Java nicht das korrekte Verhalten. (c) Ein Sinfonieorchester besteht aus 56 Musikern, die sich auf drei Instrumentengruppen verteilen: 33 Streicher, 12 Holzbläser, 11 Blechbläser. Jeder dieser Musiker hat einen Namen und spielt genau ein Instrument (Streichinstrument, Holz- bzw. Blechblasinstrument). Alle Streichinstrumente sind mit jeweils vier Saiten bespannt und werden mit einem Bogen gespielt. Zu jedem Blasinstrument gehört ein geeignetes Mundstück. Geleitet wird das Orchester von einem Dirigenten, der ebenfalls Musiker aber kein Mitglied des Orchesters ist. Der Dirigent muss mindestens ein Instrument spielen können und einen Taktstock besitzen. Erstellen Sie zu dem beschriebenen Szenario ein UML-Klassendiagramm, das möglichst alle aufgeführten Zusammenhänge in geeigneter Weise widerspiegelt. 4 Klausur zu Informatik C Name: Aufgabe 3: JavaBeans und JavaServer Pages (3+3+4+6 Punkte) (a) Gegeben ist folgende JavaBean: public class MyBean implements java.io.Serializable { private int a, b, c; private boolean d; public void setA(int a) {this.a = a;} public int getA() {return a;} public boolean getD() {return d;} } Wie heiÿen die von der Bean angebotenen Properties? Handelt es sich dabei um read/write - oder readonly -Properties? Die einzige Property (read/write) heiÿt a . Fügen Sie der Bean ein Indexed Property mit Schreib- und Lesezugri hinzu. private int[] e; public int getE (int n) {return e[n];} public int[] getE () {return e;} public void setE (int n, int v) {e[n] = v} public void setE (int[] v) {e = v;} Was versteht man unter einer Constrained Property ? Jede Änderung einer solchen Property kann durch ein Veto eines Listeners verhindert werden. (b) Das folgende unvollständige HTML-Dokument beinhaltet ein Formular mit drei Eingabefeldern. Durch Drücken des Absende-Buttons sollen die eingegebenen Werte per POST-Request an eine JSP namens result.jsp gesendet werden. Vervollständigen Sie das HTML-Dokument und beseitigen Sie die Fehler. <html> <body> <h1>Compute the median of three values</h1> <form action="result.jsp" method="post"> First value: <input name="value1" type="text" size="30"> <br> Second value: <input name="value2" type="text" size="30"> <br> Third value: <input name="value3" type="text" size="30"> <br> <input type="submit" value="OK"> </form> </body> </html> Tags mit leerem Body, wie <br> werden nicht in der Form <.../> notiert (anders als bei XML-Dateien). 5 Klausur zu Informatik C Name: (c) Erstellen Sie eine JavaBean, die drei Properties vom Typ double besitzt und eine Möglichkeit bietet, den Median dieser Properties zu ermitteln. Hinweis: Das zweite (oder mittlere) Element einer aufsteigend sortierten Folge dreier Zahlen wird Median genannt. Der Median von 5, 2 und 9 ist also 5. public class MedianBean implements java.io.Serializable { private double a, b, c; } public void setA (double a) public void setB (double b) public void setC (double c) public double getA () public double getB () public double getC () public double getMedian { return a < b ? (b < c ? b : (a < c ? a } {this.a {this.b {this.c {return {return {return = a;} = b;} = c;} a;} b;} c;} : (a < c ? c : a)) : (b < c ? c : b)); (d) Entwickeln Sie die JSP-Seite result.jsp, die vom HTML-Dokument aus aufgerufen wird und den Median der übergebenen Werte ausgibt. Verwenden Sie zum Ermitteln des Medians Ihre zuvor entwickelte JavaBean. Wie lange lebt Ihre Bean? Warum haben Sie gerade diese Lebensdauer gewählt? Wie kann man die toString -Methode der Bean aufrufen? <jsp:useBean id="medianBean" class="Median" scope="page"/> <jsp:setProperty name="medianBean" property="*"/> <html> <body> Median: <jsp:getProperty name="medianBean" property="median"/> </body> </html> Die Bean-Instanz wird nach Abarbeitung der JSP-Seite gelöscht. Da die Bean nur auf dieser Seite benötigt wird (kein include, forward und keine sessions) reicht page-Scope aus. Aufruf der toString -Methode: z.B. mit <%= medianBean.toString() %> 6 Klausur zu Informatik C Name: Aufgabe 4: Swing (6+5+5 Punkte) (a) Skizzieren Sie das von folgendem Java-Programm erzeugte Fenster. public class LayoutExample { public LayoutExample() { JFrame frame = new JFrame(getClass().getName()); JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); JPanel p1 = new JPanel(); JPanel p2 = new JPanel(new GridLayout(3, 3)); JPanel p3 = new JPanel(new BorderLayout()); pane.add(p1); pane.add(p3); p1.setLayout(new BoxLayout(p1, BoxLayout.Y_AXIS)); p1.add(p2); p1.add(new JScrollPane(new JList(new String[]{"one", "two", "three", "four"}))); p2.add(createEmptyButton()); p2.add(new JButton("1")); p2.add(createEmptyButton()); p2.add(new JButton("2")); p2.add(createEmptyButton()); p2.add(new JButton("3")); p2.add(createEmptyButton()); p2.add(new JButton("4")); p2.add(createEmptyButton()); p3.add(new JTextArea("Welcome!", 5, 20), BorderLayout.CENTER); p3.add(new JTextField("north"), BorderLayout.SOUTH); } frame.getContentPane().add(pane); frame.pack(); frame.setVisible(true); private JButton createEmptyButton() { JButton result = new JButton(); result.setEnabled(false); return result; } } public static void main (String args[]) { new LayoutExample(); } 7 Klausur zu Informatik C Name: (b) Wo und wie werden die Design Patterns Composite, Command und Template Method in der Swing-Klassenbibliothek verwendet? Nennen Sie jeweils ein Beispiel. Composite: Die add -Methode einer Swing-Komponente erwartet ein Component - Objekt. JComponent ist eine Spezialisierung von Component und eine ContainerKomponente. Auf diese Weise können einer JComponent sowohl einfache als auch Container-Komponenten hinzugefügt werden. Command: Programmcode, der nach Auswahl eines Menüpunkts ausgeführt werden soll, kann in Action-Objekte (vgl. Klasse AbstractAction) verpackt und so z.B. zur Laufzeit ausgetauscht werden. Template Method: Die paint -Methode von JComponent ruft u.a. die TemplateMethode paintComponent auf, die zum Zeichnen eigener Komponenten überschrieben werden muss. (c) Welche Probleme können sich bei der gleichzeitigen Nutzung von Swing und Threads ergeben? Wie werden diese Probleme gelöst? Welche Rolle spielen dabei InvocationEvents ? Swing ist nicht Thread-fest, d.h. sowohl das Event-Handling als auch das Zeichnen einer Komponente muss im AWT-Thread erfolgen, andernfalls kann es zu inkonsistenten Komponentenzuständen und Deadlocks kommen. Wenn Swing-Komponenten aus einem anderen Thread heraus gezeichnet werden sollen, muss der zugehörige Code in ein Runnable verpackt und in Form eines InvocationEvents in die AWT-Event-Queue eingereiht werden. 8 Klausur zu Informatik C Name: Aufgabe 5: Verteilte Anwendungen (RMI, CORBA) (5+5+5 Punkte) (a) Zeichnen Sie den groben Aufbau einer Architektur mit verteilten Objekten auf. Welche Aufgabe erfüllen die einzelnen Bestandteile? Wozu benötigt man eine Registry bzw. einen Naming Service ? Server: entferntes Objekt stellt Funktionalität für Clients bereit Client: nutzt die vom Server angebotenen Methoden Stub: lokaler Stellvertreter des Servers; übernimmt Netzwerkkommunikation auf Client-Seite Skeleton: übernimmt Netzwerkkommunikation auf Server-Seite Registry: Zentraler Dienst, bei dem die Server-Objekte angemeldet werden. Die Clients können sich über die Registry eine Referenz auf das Server-Objekt besorgen, ohne deren Host kennen zu müssen. (b) Denieren Sie die drei IDL-Schnittstellen Key, Lock und LockFactory für eine CORBA-Anwendung. Die Schnittstellen sollen in einem gemeinsamen Modul enthalten sein und folgende Anforderungen erfüllen: • Jeder Schlüssel stellt eine Methode zum Erzeugen eines entsprechenden Duplikats bereit. • Jedes Schloss bietet eine Methode, die prüft, ob das Schloss mit einem angegebenen Schlüssel geönet werden kann. • Eine Schlossfabrik enthält eine Methode zum Erzeugen eines neuen Schloss/SchlüsselPaares sowie eine Methode zum Erzeugen eines Schlüssels zu einem gegebenen Schloss. Falls eine der beiden Methoden nicht ordnungsgemäÿ ausgeführt werden kann, wird eine FactoryException geworfen. module locks { interface Key { Key clone (); }; interface Lock { boolean open (in Key k); }; exception FactoryException {}; }; interface LockFactory { void createLockAndKey (out Lock l, out Key k) raises(FactoryException); Key createKey (in Lock l) raises (FactoryException); }; 9 Klausur zu Informatik C Name: (c) Gegeben seien die beiden folgenden Klassen A und B sowie das Interface R: public interface R extends java.rmi.Remote { public void m (A a, R r) throws java.rmi.RemoteException; } public class A implements java.io.Serializable { public void main (String[] args) { try { R obj = (R)Naming.lookup("B"); obj.m(new A(), new B()); } catch (Exception e) { e.printStackTrace(); } } } public class B extends java.rmi.server.UnicastRemoteObject implements R { public B () throws java.rmi.RemoteException { super(); } public void m (A a, R r) { System.out.println(getClass()); // (1) System.out.println(a.getClass()); // (2) System.out.println(r.getClass()); // (3) } } public static void main (String[] args) { try { Naming.rebind("B", new B()); } catch (Exception e) { e.printStackTrace(); } } Nachdem die Registry gestartet wurde, sollen die main-Methoden auf demselben Rechner in separaten virtuellen Maschinen ausgeführt werden. Der aktuelle Code lässt sich allerdings noch nicht übersetzen bzw. wirft verschiedene Exceptions. Ergänzen Sie die fehlenden Code-Bestandteile so, dass die Methode mit den drei gekennzeichneten println -Anweisungen (1), (2) und (3) fehlerfrei ausgeführt werden kann. Welche Ausgabe wird vom Server produziert? Es reicht, wenn sie beschreiben, welche Ausgabe sinngemäÿ zu erwarten ist. (1) Klasse B (2) Klasse A (3) Referenz auf (Stub von) B 10 Klausur zu Informatik C Name: Aufgabe 6: XML, XPath und XSLT (4+6+5 Punkte) (a) Skizzieren Sie zur folgenden XML-Datei die zugehörige Baumstruktur: <?xml version="1.0"?> <!-- first comment --> <a> <b> <c> / <d type="a" /> <d type="b" /> <d name="d1" /> first comment second comment a <e /> </c> </b> b c <c> <d /> c d d d e <d name="d2"> <e /> </d> name id d d d e e e <d id="b"> <e /> type type name <d /> </d> <e /> </c> </a> <!-- second comment --> d (b) Erstellen Sie zu der in (a) angegebenen XML-Datei eine DTD, welche die Elementund Attributstruktur des Dokuments inkl. Anzahl und Reihenfolge möglichst genau beschreibt. <?xml version="1.0"?> <!ELEMENT a (b,c)> <!ELEMENT b (c)> <!ELEMENT c (d,d,d,e)> <!ELEMENT d (e?, d?)> <!ELEMENT e EMPTY > <!ATTLIST d type CDATA #IMPLIED name CDATA #IMPLIED id CDATA #IMPLIED > Wie wird die XML-Datei genannt, wenn sie den Vorgaben der DTD genügt? Die XML-Datei wird in diesem Fall valide genannt. 11 Klausur zu Informatik C Name: (c) Geben Sie zu folgenden umgangssprachlich beschriebenen Knotenmengen jeweils einen passenden XPath-Ausdruck an. Die Ausdrücke sollten für beliebige XMLDateien korrekte Resultate liefern (u.a. auch für die XML-Datei aus (a)). Beschreibung XPath-Ausdruck Wähle alle Elementknoten aus. //* Wähle alle Kommentare und alle type Attribute aus. Wähle alle d-Elemente aus, die genau drei Vorfahren haben. Wähle alle d-Elemente aus, die ein Attribut mit dem Wert b besitzen. Wähle alle e-Elemente aus, deren vorangehende Geschwisterelemente ein Attribut besitzen. Wähle alle d-Elemente aus, die entweder ein vorletzter Kindknoten sind oder mehr als ein Kind besitzen. //comment() | //@type /*/*/*/d //d[@* = 'b'] //e[preceding-sibling::*[@*]] //d[position()= last() - 1 or count(*)] (d) Was versteht man im Zusammenhang mit XSLT unter Push Processing ? Welche Rolle spielt dabei das Element <xsl:apply-templates/>? Werden alle Knotentypen von dieser Anweisung erfasst? Falls nicht, welche werden ausgelassen und wie kann man sie in die Menge der berücksichtigten Knoten einbeziehen? Ausgehend von der Wurzel wird versucht, rekursiv auf alle Kindknoten ein passendes Template anzuwenden. Damit die Rekursion nicht vorzeitig nach Anwendung eines Templates abbricht, muss es <xsl:apply-templates/> aufrufen. <xsl:apply-templates/> bewirkt, dass auf alle Kindknoten auÿer auf Attributknoten ein passendes Template angewendet wird. Templates für Attributknoten können durch <xsl:apply-templates select=nodes()"/> einbezogen werden. 12