Upload
artur-straub
View
219
Download
3
Embed Size (px)
Citation preview
Ein Textadventure AIP Aufgabe 2 14.05.2009
Fabian BergfeldPatrick BoeckhovenChristian Haberland Benjamin Jochheim
Liem Nguyen
Entwürfe Dr.Little schlecht,besser Unterschiede schlecht ->besser Erweiterung um oben,unten
Erweiterung Stories 1.0 Statische Sicht Dynamische Sicht Verteilungssicht Fachliche Sicht
Erweiterung Stories 2.0 Unterschiede zu Stories 1.0
Feste Eingänge -> Erweiterungen sind schwierig
Verwendung öffentlicher Attribute
class Raum {
public String beschreibung;public Raum nordausgang;public Raum suedausgang;public Raum ostausgang;public Raum westausgang
Verletzung -> InformationHiding
Private wird verwendet -> Attribute versteckt
Attribute nur über Getter und Setter zu erreichengibKurzbeschreibung()gibLangeBeschreibung()setzeAusgang()
class Raum { private String beschreibung; private HashMap ausgaenge; // die Ausgänge dieses Raums
Nicht alle Parameter werden verwendet -> Interface zu breit
Schlecht für Erweiterungen -> Parameterliste müsste erweitert
Bei mehrmaligen Setzten eines Raumes, kann kein Null mehr für einen Raum gesetzt werden
public void setzeAusgaenge(Raum norden, Raum osten, Raum sueden, Raum westen) {
if(norden != null) nordausgang = norden; ...
-> InformationHiding-> hohe Kopplung
Ausgang Norden und Osten bleiben beim zweiten Aufruf erhalten!!!
// Aufruf 1:setzeAusgaenge(ausgangNorden,ausgangOsten, ausgangSueden, ausgangWesten) // Aufruf 2:setzeAusgaenge(null,null, ausgangSueden, ausgangWesten);
...
Fehler beim wiederholten Aufrufen. Beispiel:
alle Parameter werden verwendetAusgaenge nur durch Setter zu setzenBeliebige Richtung können eingegeben
werden(-) Keine Absicherung der Richtung
(Dubbleten)
public void setzeAusgang(String richtung, Raum nachbar) { ausgaenge.put(richtung, nachbar); }
Ausgänge werden als HashMap implementiert
-> mehrere Ausgänge möglichNachteile:
(-) richtung als String ->Eingabe falscher Ausgänge
Abgeschwächt bei Verwendung von StringKonstanten
private HashMap ausgaenge; // die Ausgänge dieses Raums.... ausgaenge.put(richtung, nachbar);...
draussen.setzeAusgang("east", hoersaal);draussen.setzeAusgang(“East", labor);Besser: draussen.setzeAusgang(EAST, labor);
Direkter Zugriff auf Klassen-Attribute Man muss das innere von Raum kennen Es kann die Abfrage eines Attributs vergessen werden
private void willkommenstextAusgeben(){...if (aktuellerRaum.nordausgang != null) System.out.print("north ");if (aktuellerRaum.ostausgang != null) System.out.print("east ");if (aktuellerRaum.suedausgang != null) System.out.print("south ");if (aktuellerRaum.westausgang != null) System.out.print("west ");
-> Information Hiding-> hohe Kopplung
Redundanter CodeGenauso wie in willkommenstextAusgeben()Gefahr bei Änderungen
private void wechsleRaum(Befehl befehl) {...System.out.println("Sie sind " + aktuellerRaum.gibBeschreibung());System.out.print("Ausgänge: ");if (aktuellerRaum.nordausgang != null) System.out.print("north ");if (aktuellerRaum.ostausgang != null) System.out.print("east ");if (aktuellerRaum.suedausgang != null) System.out.print("south ");if (aktuellerRaum.westausgang != null) System.out.print("west ");
Spiel greift über gibLangeBeschreibung() auf Raum, um Ausgänge auszugeben
Spiel braucht keine Interna von Raum wissen
public String gibLangeBeschreibung() { return "Sie sind " + beschreibung + ".\n" + gibAusgaengeAlsString(); }
private String gibAusgaengeAlsString() { String ergebnis = "Ausgänge:"; Set keys = ausgaenge.keySet(); for(Iterator iter = keys.iterator(); iter.hasNext(); ) ergebnis += " " + iter.next(); return ergebnis; }
Greift direkt auf interne Attribute Codeänderung bei Erweiterung von Richtung
private void wechsleRaum(Befehl befehl){.....Raum naechsterRaum = null;if (richtung.equals("north")) naechsterRaum = aktuellerRaum.nordausgang;if (richtung.equals("east")) naechsterRaum = aktuellerRaum.ostausgang;if (richtung.equals("south")) naechsterRaum = aktuellerRaum.suedausgang;if (richtung.equals("west")) naechsterRaum = aktuellerRaum.westausgang;.....
Information Hiding
Ermittlung des nächsten Raumes liegt jetzt in Raum Spiel braucht keine Interna von Raum wissen Spiel greift über aktuellerRaum.gibAusgang(richtung) auf
nächsten Raum zu
class Raum {.... private HashMap ausgaenge; // die Ausgänge dieses Raums... public Raum gibAusgang(String richtung){ return (Raum)ausgaenge.get(richtung); }
Feste Befehlsliste -> Feste Bestandteile von Veränderlichen trennen
Schlecht für Erweiterung Ausgabe auslagern -> trennen von Logic
private void hilfstextAusgeben() {System.out.println("Sie haben sich verlaufen. Sie sind allein.");System.out.println("Sie irren auf dem Unigelände herum.");System.out.println();System.out.println("Ihnen stehen folgende Befehle zur Verfügung:");System.out.println(" go quit help");}
(Open Closed Principle)
Ausgabe aller gültigen Befehle wurde an Parser übergeben
Parser besitzt alle Befehlswoerter Gültige Befehle werden einer Stelle definiert (in
Befehlswoerter)
private void hilfstextAusgeben() { .... System.out.println("Ihnen stehen folgende Befehle zur Verfügung:"); parser.zeigeBefehle(); }class Parser {
public void zeigeBefehle() { befehle.alleAusgeben();
}
Wird nur von verarbeiteBefehl() aufgerufen, daher sollte die Schnittstelle kleiner sein (nur den Raum übergeben)
private void wechsleRaum(Befehl befehl) {
„Look“ wird angenommen, obwohl es nicht spezifiziert ist.
Dadurch dass „look“ nicht erwartet wird, wird es nicht abgefangen
Unerwartete Funktionalität
class Befehlswoerter{ // ein konstantes Array mit den gültigen Befehlswörtern private static final String gueltigeBefehle[] = { "go", "quit", "help", "look" };
"Das Befehlswort sollte 'null' sein, wenn dieser Befehl als nicht vom Spiel erkannt gekennzeichnet werden soll.
Schlecht: Datenparameter haben eine Doppelbedeutung
public Befehl(String erstesWort, String zweitesWort) { befehlswort = erstesWort; this.zweitesWort = zweitesWort;}....public boolean istUnbekannt() { return (befehlswort == null); }
Single Responsibility Principle
Liefert das Befehlswort (das erste Wort) dieses Befehls.
Wenn der Befehl nicht verstanden wurde, ist das Ergebnis 'null'.
Schlecht: Datenparameter haben eine Doppelbedeutung
Verbesserung: Exceptions im Fehlerfall
public String gibBefehlswort() { return befehlswort; }
Ausgaben (hier via println) sowie das einlesen via Buffered Reader sollten von dem eigentlichen Parsen entkoppelt werden.
public Befehl liefereBefehl() {... System.out.print("> "); // Eingabeaufforderung..... BufferedReader eingabe = new BufferedReader(new InputStreamReader(System.in));.....eingabezeile = eingabe.readLine();...
Single Responsibility PrincipleTrennung von Funktion und Interaktion
Dr.Little schlecht und besser werden um oben+unten erweitert
class Raum {... public Raum oberausgang; public Raum unterausgang;....public void setzeAusgaenge(Raum norden, Raum osten, Raum sueden, Raum westen, Raum oben, Raum unten, Raum oben, Raum unten) { if(oben != null) oberausgang = oben; if(unten != null) unterausgang = unten;...public void setzeAusgaenge(Raum norden, Raum osten, Raum sueden, Raum westen) { this.setzeAusgaenge(norden, osten, sueden, westen, null, , null, nullnull); }
Class Spiel {...private void raeumeAnlegen(){ Raum aussichtsturm, keller; //Erweiterung oben+unten ....aussichtsturm = new Raum("im Aussichsturm der Uni");keller = new Raum("im Keller der Uni");....draussen.setzeAusgaenge(null, hoersaal, labor, cafeteria);hoersaal.setzeAusgaenge(null, null, null, draussen);cafeteria.setzeAusgaenge(null, draussen, null, null);labor.setzeAusgaenge(draussen, buero, null, null, null, keller);buero.setzeAusgaenge(null, null, null, labor, aussichtsturm, null);keller.setzeAusgaenge(null, null, null, null, labor, null);aussichtsturm.setzeAusgaenge(null, null, null, null, null, buero);
Class Spiel {...private void willkommenstextAusgeben() {...if (aktuellerRaum.oberausgang != null) System.out.print("upstairs ");if (aktuellerRaum.unterausgang != null) System.out.print("downstairs ");....private void wechsleRaum(Befehl befehl) {if (richtung.equals("upstairs")) naechsterRaum = aktuellerRaum.oberausgang;if (richtung.equals("downstairs")) naechsterRaum = aktuellerRaum.unterausgang;...if (aktuellerRaum.oberausgang != null) System.out.print("upstairs ");if (aktuellerRaum.unterausgang != null) System.out.print("downstairs ");
Class Spiel {...private void raeumeAnlegen(){...aussichtsturm = new Raum("im Aussichsturm der Uni");keller = new Raum("im Keller der Uni");....
labor.setzeAusgang("north", draussen); labor.setzeAusgang("east", buero); labor.setzeAusgang("downstairs", keller); //Erweiterung; oben+unten
buero.setzeAusgang("west", labor); buero.setzeAusgang("upstairs", aussichtsturm); //Erweiterung; oben+unten
//Erweiterung; oben+untenkeller.setzeAusgang("upstairs", labor);aussichtsturm.setzeAusgang("downstairs", buero);
Erweiterung von Dr. Little-besser um Stories 1.0
Demonstration
Erweiterung von Dr. Little-besser um Stories 2.0
Demonstration
Stories 2.0: GUI
Vielen Dank!