Ich habe bemerkt, dass ich Probleme beim allgemeinen Code-Design bei GUIs habe.
Nun zu meinen Fragen.
Früher ist meine GUI von FIDER in fast nur einer einzigen Klasse gewesen, und der ganze GUI-Code in einer Methode…
Nachdem ich dann irgendwann die Übersicht verloren habe und ich es mit erweitern der GUI fast vergessen konnte, habe ich dann mal den GUI-Code auf mehrere Klassen verteilt.
Zur Verwaltung habe ich dann die Klasse GUIManager gebastelt, die mir Zugriff auf alle wichtigen GUI-Elemente wie Frame und Panels gibt. Das Fenster des Programms ist in einer Klasse, die von JFrame erbt. In ihr werden auch andere Instanzen von JPanel-Klassen erzeugt. Auf den Frame und die ganzen Panels habe ich alle mit dem GUIManager Zugriff, auch wenn diese eigentlich in meiner Frame-Klasse abgespeichert sind. 1. Frage: Ist das so richtig? Ist es auch so üblich, dass man dann über diesen „Manager“ Zugriff auf alle meist verwendeten Panels hat? Ist es dann auch sinnvoll, Methoden in z. B. der Frame-Klasse anzubieten, mit denen man auf die in der Frame-Klasse erzeugten Panels hat?
Jetzt kommt das Problem, wie denn der Frame und die ganzen Panels Zugriff auf den GUIManager bekommen. Bis jetzt habe ich immer eine Instanz über den Konstruktor mitgegeben, was allerdings sehr mühsam ist. 2. Frage: Wäre es besser, wenn GUIManager einen privaten Konstruktor hat und eine statische Methode getInstance() oder so?
3. Frage: Wenn jetzt jede Klasse eine Referenz auf den GUIManager bekommen kann, ist es dann nach „gutem“ Code-Design erlaubt, die Referenz in einer privaten Instanzvariablen abzuspeichern und ist es dann sinnvoll, eine private Methode getGUIManager() zu machen, um einfach Code zu „sparen“?
Das war’s erstmal, was mir auf den ersten „Denker“ einfällt
Das klingt eigentlich ganz gut, bei mir ist das etwas anders.
Jede Klasse kennt eigentlich nur sich selbst und einen Controller, der ist ein Singleton (wie deine Frage 2)
Nur die Dialoge/Frames kennen einige ihrer Panels die sie enthalten.
Einige wichtige Elemente werden dem Controller auch bekannt gegeben aber er kennt niemals alle.
Danke erstmal!
Dieser Controller, den du hast, erzeugt der auch den Frame? Oder geschieht das in der Main-Klasse?
Kennen auch die Panels, die die Frames usw. enthalten, auch ihr Elternelement (also z. B. den Frame)? Oder holen sie sich dann die Objekte, die sie brauchen, über den Controller?
Wie werden deinem Controller die Elemente bekannt gegeben? Gibt es bei dir Methoden wie setHeaderPanel(Panel p)?
Bei mir ist der „Aufruf-Stack“ ungefähr so, was ich allerdings noch nie so richtig gut fand…:
#**GUIManager**
##lädt die Frame-Klasse
##Jetzt gibt es im GUIManager Methoden wie **getHeaderPanel()**, usw., deren Code dann ungefähr so aussieht (Bsp.):
public UploadTable getUploadTable() {
return getFrame().getUploadPanel().getUploadTable();
}
#**Frame-Klasse**
##lädt die ganzen Panels usw.
##Methoden: z. B. **getHeaderPanel()**, ...
Ich denke, dass kann man geschickter lösen, aber da gibt es sicherlich mehrere Möglichkeiten.
Noch ein Frage, die richtet sich allerdings wohl doch eher an allgemeines „Code-Designing“: Ich vermute mal, die Klassen speichern sich in einer privaten Instanzvariablen eine Referenz auf den Controller (um Code zu sparen ;-)), wenn sie sie über Controller.getInstance() oder so bekommen haben. Machst du dann extra eine private Methode getController() oder so? Oder lässt du den Code direkt auf die Instanzvariable zugreifen? (Also Frage 3 im ersten Post)
Nein der Frame erzeugt in der Regel den Controler, wobei das ja auch egal ist da er ein Singleton ist.
Componenten kennen immer ihren Parent (getParent()) aber ich verwende ihn nie bzw. sehr sehr selten. Ich versuche eigentlich immer das alle Elemente möglichst unabhängig von einander sind. Wenn es Abhängigkeiten gibt löse ich das oft mit Listenern.
Jep das wird einfach über Setter gemacht.
Ne bei mir sieht das ungefähr so aus
- Frame erzeugen
-- Menu erzeugen
-- Toolbar erzeugen
-- Panels erzeugen
-- einzelne Elemente im Controller setzen
Ich geb dem Controller nur die Elemente die er für seine Arbeit braucht, z.B. das Menu wenn er Einträge de-/aktivieren soll. In der Regel kennt er nur das Menu und die Toolbar um dort Sachen zu de-/aktivieren und den Hauptframe um ihn als Parent für Fehlermeldungen zu nehmen.
Wieso eine private Methode getController?
Ich hab in den Klassen die den Controller brauchen immer eine statische Variable die den Controller enthält. private static final Controller controller = Controller.getInstance();
Kümmert sich dein Controller nur um die GUI-Elemente, oder auch um sonstige Sachen?
Leiht er auch nur Zugriff auf die Elemente, oder ist es auch der Verwalter der GUI? Oder hast du da was anderes?
Der Controller ist für viele (nicht alle) Steuerungen zuständig.
Einige Teile die klein und innerhalb eines Panels sind bleiben dort alles andere geht in den Controller.
Der Controller gibt bei mir niemals Objekte raus, er nimmt nur aufrufe entgegen und führt sie aus bzw. leitet sie weiter.
Wenn ich mal wieder Internet zuhause hab kann ich dir mal ein Beispiel zeigen (theoretisch bekomm ichs heute abend :D)
Und wie kommen dann ActionListener usw. an andere GUI-Objekte, die sie benötigen?
Was macht der Controller dann mit den per Settern übergebenen Objekten, wenn er ja keine Getter für sie hat?
Die kennen keine andere Objekte, wenn es kleine Aktionen sind und nur Objekte des gleichen Panels sind dann greifen sie direkt zu sonst heißt es nur controller.machdas() und der führt dann alles nötige aus.
In der GUI sollte so wenig wie möglich Logik stehen (eigentlich garkeine aber das geht einfach nicht)
[QUOTE=EagleEye]Naja darüber lässt sich streiten
Für ein Objekt Spring aufsetzen ist meiner Meinung nach etwas übertrieben.[/QUOTE]
zum einen gehts ja nicht um ein Objekt, sondern um ein Projekt… zum anderen muss man natuerlich nicht gleich Spring aufsetzen - Google Guice geht auch oder eben einfach selbst organisieren…
wollte eben nur anmerken, dass Singletons are evil
Danke erstmal! Ich denke, das Beispiel hat mir für das Grundkonzept für die Verwaltung eines Programms viel geholfen.
[QUOTE=deathbyaclown]Man sollte eher an Dependency Injection oder aehnliches nutzen (entweder selbst anleihern oder PICO oder Spring oder aehnliches verwenden )
)
zum einen gehts ja nicht um ein Objekt, sondern um ein Projekt… zum anderen muss man natuerlich nicht gleich Spring aufsetzen - Google Guice geht auch oder eben einfach selbst organisieren…[/QUOTE]
Was bringen diese ganzen Libs - ich vermute mal Libs, die einem helfen sollen, das Programm zu verwalten - bzw. was für Funktionen haben sie, dass sie Projekten verschiedener Arten „nützlich“ sein können?
Ich probiere jetzt erstmal EagleEyes Variante aus, nachdem ich einen blöden Bug gefixt habe…
Sometimes you see comments that are nothing but noise. The restate the obvious and provide no new information.
/**
* Default constructor
*/
public MyClass() {
}
no, really ? Or how about this:
/** The day of the month */
private int dayOfMonth
And then there is this paragon of redundancy
* Returns the day of the month
*
* @return the day of the month
*/
public int getDayOfMonth() {
return dayOfMonth
}
irgendwer hat mal irgendwann gesagt - „und kommentiere ja schoen ALLES aus“ - darausfolgerten immer unnuetze und unsinnige Kommentare… (Zitat uebrigens aus Clean Code - Robert C. Martin)
aber das hier sollte kein gespamme von Softwareentwicklung sein
verzeiht mein einschreiten - viel erfolg pcworld fuer das eigentliche problem !
[QUOTE=EagleEye]Hey immerhin hab ich Kommentare
Das ist eine riesen Steigerung zu früher wo es nie welche gab :D[/QUOTE] hust aber wie gesagt - noise comments… und die erschweren eher die lesbarkeit des codes…