Einzelnen Beitrag anzeigen

BrightAngel

Registriert seit: 13. Mär 2007
130 Beiträge
 
#3

AW: Kontrollflussarchitektur bei Ereignissen: Geschmackssache?!?

  Alt 7. Feb 2017, 23:00
Vielleicht liegt es an der Uhrzeit, aber ich musste mehr als einmal lesen um es zu verstehen. Eine kleine Skizze vom Ablauf*hätte (mir zumindest) geholfen
Kann sein, dass es die Uhrzeit ist, aber ich habe auch ein bisschen gebraucht, um das auch nur zu formulieren... Ich wollte möglichst viel Detail schaffen, damit man die ganzen Ecken und Kanten unterwegs mitbekommt. Hab mich da wohl verzettelt. Vielen dank, dass du dich trotzdem damit befasst hast!

In einem Satz zusammengefasst: An einem OnClick-Event hängen mehrere Handler. Einer dieser Handler ändert z.B. eine Eigenschaft was wiederum ein OnChange-Event auslöst. Sollte man nun
  • Die Handler des OnChange-Events abarbeiten um danach die restlichen Handler von OnClick abzuarbeiten
  • Oder die Handler von OnChange erst nach dem vollständigen Abarbeiten aller Handler des "laufenden Events" (also OnClick) abarbeiten

Richtig verstanden?
Genau! Ich habe mir erlaubt, meinen ursprünglichen Post auf deinen verweisen zu lassen. Hilft vielleicht auch anderen Lesern

Vielleicht habe ich einfach noch nicht genug von der Welt gesehen, aber den "defer"-Ansatz habe ich weder irgendwo einmal gesehen, noch finde ich das in irgendeiner Weise intuitiv.
Ja, das "defer" sieht man normalerweise nicht. Es gibt ein paar Beispiele, die aber eher vereinzelt auftauchen: In Java gibt es mit der runLater-Methode die Möglichkeit die Ausführung auf dem UI-Thread zu verzögern.
In Javascript sieht man manchmal Codefragmente
Code:
setTimeout(function() { ... }, 0);
, die auch diesen Zweck des Verzögerns erfüllen. Aber genau diese Behelfsstellen haben mich dazu angeregt näher darüber nachzudenken und meinen Code mancherorts zu überdenken.
Das gruslige zur Intuition: Je länger ich mich damit beschäftige, desto interessanter finde ich eben auch diesen anderen Kontrollfluss.

Bei einem "Mach sofort"-Ansatz*könnte ich Events*deaktivieren, etwas tun und danach wieder aktivieren. Mit dem "defer"-Ansatz verliere ich das doch, oder?
Genau, das ist zum Beispiel ein Vorteil davon. Das Deaktivieren ist aber nicht so häufig und bei vielen EventListenern pro EventSource kann es vorkommen, dass das Entfernen und Hinzufügen vielleicht teurer wird. Zudem impliziert so eine Codestelle meistens, dass man zirkuläre Abhängigkeiten vermeiden möchte. Vielleicht findet man da manchmal mit ein bisschen Nachdenken schönere "Abbruchkriterien" als das temporäre deregistrieren des Listerners? Aber ganz von der Hand weisen kann man dein Argument eben auch nicht...

Ganz zu schweigen von dem Mehraufwand. Was z.B. wenn ich einen Handler entferne, der aber noch in irgendeiner "Mache später"-Queue steckt? Schwierig. Mir fehlt ein konkretes Beispiel wo der "defer"-Ansatz irgendeinen Vorteil hat. Was hierdurch einfacher wird.*
Thema Mehraufwand: Theoretisch ist eine zentrale Liste mit Ereignissen quasi genau das selbe wie beim Runloop von Betriebssystemereignissen. Auch die werden gecached, wenn der Faden noch nicht soweit ist. Eine LinkedList zusätzlich oder so reicht da vmtl.
Thema Handler entfernen: Ja, wenn man Handler entfernt und hinzufügt während der Eventbehandlung ist so ein Sonderfall den man bei beiden Implementierungen genau betrachten muss: Man will im Optimalfall das gerade laufende Ereignis allen Listenern zustellen, die zum Triggerzeitpunkt des Ereignisses registriert waren.
"defer" im Speziellen bildet sowas wie einen "ripple"-Effekt. Ein (zugegeben sehr synthetisches) Beispiel: zwei Listener auf ein und dem selben Event ändern je eine Eigenschaft von einem Rechteck.
ListenerWidth ändert die Breite des Rechtecks und triggert ein weiteres Event zur Berechnung des Flächeninhalts. ListenerHeight ändert die Höhe des Rechtecks und triggert auch das Flächeninhaltsereignis. Bei "defer" ändern sich die Dimensionen des Rechtecks zuerst und dann wird zwei Mal der selbe Flächeninhalt berechnet (wobei wenn die Flächeninhaltsberechnung weitere Ereignisse auslöst, sie das durch ein identisches, bei der ersten Berechnung gecachtes Ergebnis beim zweiten Mal gar nicht auslösen muss!), bei "immediate" werden die Ereignisse in anderer semantischer Reihenfolge aufgelöst (es wird dazwischen einmal ein Flächeninhalt berechnet, der vermutlich nicht wichtig ist).
Bei "defer" könnte man so zum Beispiel die Dimensionen ändern; ohne, dass der Flächeninhalt sich zwischendurch kurz "flackernd" auf einen Zwischenwert ändert (Beispiel: 3x6 wird zu 2x9 und der Flächeninhalt bleibt 18)

Außerdem sehe ich nicht was an einem Event so "besonders" ist dass man es aufstauen sollte. Warum wird ein Handler der ein internes Feld ändert sofort ausgeführt, ein anderer der z.B. auf eine Property geht (deren Setter ein Event auslöst) aber später? Bzw. der Setter würde ausgeführt, nur der Code hinter dem Event nicht? Jeder*Code der hinter dem bewussten Ausführen eines Events steht müsste fortan davon ausgehen müssen, dass die*Folgen noch nicht eingetreten sind.
Genau, aber wer sagt, dass Listener in der gleichen Reihenfolge aufgerufen werden? Wenn du beispielsweise zwei Listener hast und der erste sich kurz deregistriert und dann wieder registriert (und dann vielleicht damit an zweiter Stelle der Ausführung landet) und danach ein gleiches Ereignis ausgelöst wird, dann ändert sich die Ausführungsreihenfolge der Listener zwischen zwei Ereignissen...

Ziemlich verwirrend. Vielleicht aber auch nur für mich.
Nein, du hast es erfasst! Es IST ziemlich verwirrend. Wenn man da eine Weile drüber nachdenkt, wird es irgendwie komisch... Vielleicht wirklich die Uhrzeit.

PS: Mich haben deine "Beginnt mit"-Dinger verwirrt, vor allem da du erst ganz unten erklärst was du damit meintest. Lass die*Auflistung doch wie sie ist, das versteht denke ich trotzdem jeder.
Danke fürs Feedback; habe es angepasst!
Do you have the email of god??? --- I have to tell him that I'm happy to be born!

Geändert von BrightAngel ( 7. Feb 2017 um 23:17 Uhr)
  Mit Zitat antworten Zitat