Servus,
momentan stehe ich vor einem größeren Design-Problem. Ich hatte ja neulich auch schonmal einen Thread über meine Listener-Problematik eröffnet, aber da ist glaub nicht so ganz rübergekommen, worum es eigentlich geht. Daher versuche ich nochmal, zu beschreiben, worüber ich mir momentan den Kopf zerbreche und hoffe auf ein paar gute Vorschläge und Ideen.
Ich habe bisher hauptsächlich Spiele programmiert, und da ist der interne Programm-Ablauf nicht direkt vergleichbar mit "normalen" GUI-Anwendungen. Hier wird erstmal alles berechnet und zum Schluß gezeichnet, und das 60x in der Sekunde. Auf jeden Berechnungsschritt / Update-Vorgang erfolgt immer ein völlig neues Bild, und das Spiel darf sich auch herausnehmen, die CPU voll zu belasten.
Nun programmiere ich in unserer Firma gerade einen visuellen Audio-Player mit einigen Editor-Funktionen, und da läuft die Sache natürlich etwas anders ab. Mein Hauptproblem ist das Event-Handling.
Im Moment habe ich verschiedene Listener, je nach Aufgabe bzw. je nach Hauptklasse, und es gibt einige Klassen, die sich dort registrieren. Allerdings ist das manchmal schon sehr kompliziert, weil Listener über mehrere Klassen hinweg "weitergegeben" werden müssen, z.B. weil eine bestimmte Klasse den eigentlichen Player gar nicht kennt oder so. Und das wird dann sehr schnell ungemütlich, weil auf einmal Code in den Klassen steht, der dort eigentlich gar keine richtige Funktion hat und logisch gesehen da auch gar nicht hingehört.
Richtig schlimm ist es geworden, als die GUI kam. Diese war für mich zunächst nur ein Aufsatz auf die Backend-Logik, allerdings wird auch hier stark hin- und herkommuniziert. Ein gutes Beispiel: Man ändert per Mausklick die aktuelle Position im Audio-Sample, wodurch die GUI dann natürlich den Player benachrichtigt, welcher die Position entsprechend ändert. Auf der anderen Seite muß sich aber wiederum die GUI ändern, wenn der Player z.B. von allein die Position ändert (im einfachsten Fall passiert das z.B. dann, wenn das Stück abgespielt wird). Das heißt, es gibt viele Wechselbeziehungen, wo zwar einerseits eine Aktion in der GUI das Backend informieren muß, und andererseits passieren auch im Backend einige Dinge, die dann wieder der GUI bescheid sagen müssen. Hierbei muß man dann auch aufpassen, daß keine Zyklen entstehen, welche zum Deadlock führen können (was ich im Moment löse, indem ich immer den "Auftraggeber" mitschicke).
Die Position ist deshalb auch noch ein gutes Beispiel, weil sie sich beim Abspielen tatsächlich ständig ändert. In dem Fall erscheint es mir wieder unnötig, jedesmal der GUI bescheid zu sagen, daher hat die GUI einen Thread, der alle 50 ms nachfragt, wo die Position gerade ist. Aber auch das ist wieder recht unsauber.
Gibt es für diese Problematik saubere Lösungen? Speziell diese Wechselbeziehungen und die Zyklen sind schlimm, aber auch das Weiterreichen der Listener. Da bei mir die Hauptlogik eher "fest verdrahtet" ist, aber immer wieder erweitert wird, habe ich bereits über ein zentrales Signalsystem nachgedacht, wo sich jede Klasse für bestimmte Ereignisse registrieren kann, allerdings immer bei einer zentralen "Postdienststelle", um es mal so auszudrücken. Das könnte einiges vereinfachen, aber vielleicht kennt hier jemand auch Gründe, die gegen solch ein System sprechen. Falls es dennoch eine gute Wahl sein könnte, ist die nächste Frage, wie man diese zentrale Stelle implementiert - eigentlich möchte ich möglichst auf Singletons verzichten.
momentan stehe ich vor einem größeren Design-Problem. Ich hatte ja neulich auch schonmal einen Thread über meine Listener-Problematik eröffnet, aber da ist glaub nicht so ganz rübergekommen, worum es eigentlich geht. Daher versuche ich nochmal, zu beschreiben, worüber ich mir momentan den Kopf zerbreche und hoffe auf ein paar gute Vorschläge und Ideen.
Ich habe bisher hauptsächlich Spiele programmiert, und da ist der interne Programm-Ablauf nicht direkt vergleichbar mit "normalen" GUI-Anwendungen. Hier wird erstmal alles berechnet und zum Schluß gezeichnet, und das 60x in der Sekunde. Auf jeden Berechnungsschritt / Update-Vorgang erfolgt immer ein völlig neues Bild, und das Spiel darf sich auch herausnehmen, die CPU voll zu belasten.
Nun programmiere ich in unserer Firma gerade einen visuellen Audio-Player mit einigen Editor-Funktionen, und da läuft die Sache natürlich etwas anders ab. Mein Hauptproblem ist das Event-Handling.
Im Moment habe ich verschiedene Listener, je nach Aufgabe bzw. je nach Hauptklasse, und es gibt einige Klassen, die sich dort registrieren. Allerdings ist das manchmal schon sehr kompliziert, weil Listener über mehrere Klassen hinweg "weitergegeben" werden müssen, z.B. weil eine bestimmte Klasse den eigentlichen Player gar nicht kennt oder so. Und das wird dann sehr schnell ungemütlich, weil auf einmal Code in den Klassen steht, der dort eigentlich gar keine richtige Funktion hat und logisch gesehen da auch gar nicht hingehört.
Richtig schlimm ist es geworden, als die GUI kam. Diese war für mich zunächst nur ein Aufsatz auf die Backend-Logik, allerdings wird auch hier stark hin- und herkommuniziert. Ein gutes Beispiel: Man ändert per Mausklick die aktuelle Position im Audio-Sample, wodurch die GUI dann natürlich den Player benachrichtigt, welcher die Position entsprechend ändert. Auf der anderen Seite muß sich aber wiederum die GUI ändern, wenn der Player z.B. von allein die Position ändert (im einfachsten Fall passiert das z.B. dann, wenn das Stück abgespielt wird). Das heißt, es gibt viele Wechselbeziehungen, wo zwar einerseits eine Aktion in der GUI das Backend informieren muß, und andererseits passieren auch im Backend einige Dinge, die dann wieder der GUI bescheid sagen müssen. Hierbei muß man dann auch aufpassen, daß keine Zyklen entstehen, welche zum Deadlock führen können (was ich im Moment löse, indem ich immer den "Auftraggeber" mitschicke).
Die Position ist deshalb auch noch ein gutes Beispiel, weil sie sich beim Abspielen tatsächlich ständig ändert. In dem Fall erscheint es mir wieder unnötig, jedesmal der GUI bescheid zu sagen, daher hat die GUI einen Thread, der alle 50 ms nachfragt, wo die Position gerade ist. Aber auch das ist wieder recht unsauber.
Gibt es für diese Problematik saubere Lösungen? Speziell diese Wechselbeziehungen und die Zyklen sind schlimm, aber auch das Weiterreichen der Listener. Da bei mir die Hauptlogik eher "fest verdrahtet" ist, aber immer wieder erweitert wird, habe ich bereits über ein zentrales Signalsystem nachgedacht, wo sich jede Klasse für bestimmte Ereignisse registrieren kann, allerdings immer bei einer zentralen "Postdienststelle", um es mal so auszudrücken. Das könnte einiges vereinfachen, aber vielleicht kennt hier jemand auch Gründe, die gegen solch ein System sprechen. Falls es dennoch eine gute Wahl sein könnte, ist die nächste Frage, wie man diese zentrale Stelle implementiert - eigentlich möchte ich möglichst auf Singletons verzichten.