Models EventHandling

G

Gast2

Gast
Hallo zusammen,

ich hätte mal eine Arichtekturfragen wie ihr das mit dem Eventhandling und der Businesslogik macht oder eventuell einen guten Blog dazu kennt.
Nehmen wir an wir haben 2 Models die abhängig voneinander sind. Es gibt eine update Methode in dem einige Modelwerte abhängig voneinander gesetzt werden.
Jetzt kann es sein das während dieser Methode die Daten inkosistent sind/werden. Und erst zum Schluss der Methode die Daten in einem konsistenten Zustand sind. Die Methode ruft andere Methoden auf die PropertyChangeEvents feuern. Die Beobachter, die auf das Model hören, könnten mittendrin Daten erhalten die nicht korrekt sind, jemand eine Idee wie man sowas umgeht oder besser macht?

Codebeispiel
Java:
public class Model1{

Model2 model2;

public void update(){
privateUpdate();
model2.update();

//doSth.
firePropertChangeEvent(event)
}

private void privateUpdate(){
// set Model werte
}


}

Java:
public class Model2{

public void update(){
privateUpdate();
firePropertChangeEvent(event)
}

private void privateUpdate(){
// set Model werte
}


}
 

ThreadPool

Bekanntes Mitglied
Nur zum Verständnis, du hast zwei Models A und B. A benötigt Daten aus B und B benötigt Daten aus A. Model A kann Model B und umgekehrt updaten. D.h. wenn Model A ein Update auf sich ausführt werden durch die Änderung Events ausgelöst die Model B dazu veranlassen sich mit Werten aus A zu versorgen. Ist das soweit ok?

Dann habe ich eine Frage, wenn Model B seine Werte updated werden dann Events ausgelöst damit A dazu veranlasst wird sich zu aktualisieren? Gibt das nicht eine Schleife?
 
G

Gast2

Gast
Das Beispiel ist ein wenig doof zu umschreiben.

Aber lassen wir es am Anfang so das ModelA -->ModelB updaten kann.
Model A setzt werte und schmeißt events und ModelB schmeißt events...
Aber Sie hören nicht gegenseitig aufeinander also keine Rekursion oder Endlosschleife...
Aber eventuell ein anderer Beobachter(GUI,anderes Model etc.) könnten inkosistente Daten erhalten.
 

Marco13

Top Contributor
Schwierig, an einem abstrakten Beispiel eine pauschale Regel zu definieren. Optionen könnten vielleicht package-Private update-Methoden, die nur die Modelle untereinander aufrufen (und die keine Events feuern), oder ein (ggf. auch package-privates) flag wie "currentlyUpdatingSoDontThrowEvents", die vom auslösenden Modell im anderen gesetzt werden sein....
 
G

Gast2

Gast
Schwierig, an einem abstrakten Beispiel eine pauschale Regel zu definieren. Optionen könnten vielleicht package-Private update-Methoden, die nur die Modelle untereinander aufrufen (und die keine Events feuern), oder ein (ggf. auch package-privates) flag wie "currentlyUpdatingSoDontThrowEvents", die vom auslösenden Modell im anderen gesetzt werden sein....

Ja ich weiß das es schwer ist, aber dachte vielleicht kommen die Probleme jemand bekannt vor ...
Auf die private Methoden ohne Events bin ich auch schon bekommen, das Problem hierbei ist dass das ziemlich viele Stellen zu ändern sind und das sehr aufwendig ist.
Deshalb bin auf der Suche nach möglichen Alternativen...
 

Marco13

Top Contributor
Bei dem Beispiel läge das Problem also darin, dass jemand von Modell2 einen Event bekommt, und erst danach von Modell1. Und das, was er da von Modell2 erfährt, wäre "falsch", solange er nicht auch das Update von Modell1 bekommen hat?

Wenn es diese "privateUpdate"-Methoden wirklich gäbe, wäre das ja schon die halbe Arbeit ;) Auf irgendwelche "Anwendungsspezischen" Lösungen bist du wahrscheinlich auch schon gekommen: Modell1 könnte den Event feuern, bevor es model2.update() ausführt - aber vielleicht passt das auch nicht... :bahnhof:
 
G

Gast2

Gast
Bei dem Beispiel läge das Problem also darin, dass jemand von Modell2 einen Event bekommt, und erst danach von Modell1. Und das, was er da von Modell2 erfährt, wäre "falsch", solange er nicht auch das Update von Modell1 bekommen hat?

Ja so wie es grad aufgebaut ist, ist es sogar noch krasser... Model 1 feuert Events beim update (wenn sich halt was ändert) und Model 2 feuert im update auch events und ganz am Schluß wird eben das "finale" event geworfen...

Eigentlich ist ein Verhalten wie bei Transaktionen gewünscht, erst am Schluß wenn alles feherfrei abgelofen ist kommt das commit und in dem Fall wird das event gefeuert.

Vielleicht nochmal ein Beispiel (ausgedacht):
Eine View (ViewZeichnen) macht aufwendige Zeichenoperationen und je nach Modeländerung muss diese sich neu aufbauen.
Eine andere View (ViewFormular) kann Modelattribute einzeln ändern.

Jetzt gibt es eine UserInteraktion die mehrere ModelWerte auf einmal ändern kann (changeModel)...

Jetzt muss ViewZeichnen auf alle "einzelne" Model changes des ViewFormular hören, um auf die einzelnen Änderungen einzugehen, stellt kein Problem dar.
Die ViewZeichnen registriert sich auf das Model und wertet die einzelnen propertyChanges aus.
SO jetzt das Problem:
Werden mehrere Werte in einer Methode geändert (siehe changeModel -->Controller)
sollen KEINE "zwischen Events" für jedes einzelene attribut geworfen werden, sondern quasi erst am schluß der change model methode...
1. Die ViewZeichnen macht alle aufwendigen Zeichenoperationen zu oft (Jedes mal wenn ein Attribut geändert wird)
2. Sind die Daten eventuell noch nicht korrekt, sondern erst am Schluß von changeModel.

Vielleicht ist das Beispiel nicht ganz so abstrakt :)

Folgender Code:
Java:
     public class Model{
    	public void setX(int x){
    		this.x = x;
    		fireChange(this,x,oldX)
    	}
    	
    	public void setY(int y){
    		this.y = y;
    		fireChange(this,oldY,y)
    	}
    	
    	public void setWidht(int width){
    		this.widht = widht;
    		fireChange(this,oldWidht, widht);

    	}
    	
    	//weitere
    }
    
    public class Controller{
    	public void changeModel(){
    		//geschäftlogik do sth.

                //setze ausgerechnete model werte
    		model.setX();
    		model.setWidht();
    		model.setY();
    		//weitere
    	}
    }

Wie würdet ihr sowas (besser) machen? Hoffe das Problem war verständlicher
 
Zuletzt bearbeitet von einem Moderator:

Marco13

Top Contributor
Hm ... so viele Alternativen zu den schon angedeuteteten (ein Flag oder eine "changeMultipleThings(x,y,z)" Methode) wüßte ich da jetzt auch nicht :bahnhof: ... wie gesagt, hängt auch vom konkreten Problem ab... eine spezifische Listener-Infrastruktur für das "finale Commit", oder irgendwelche "Filternden Listener" könnte man sich vielleicht auch vorstellen, aber eben ggf. nur mir höherem engineering-Aufwand...
 
G

Gast2

Gast
Ja so Abstrakt ist das Beispiel ja jetzt nicht mehr. Glaub nicht das ich der einzige bind der so ein Problem hat ... Deshalb ist jeder Vorschlaf interessant um es in Zukunft auf jeden Fall besser zu machen.Ich poste morgen mal ein kleines KSKB...
 
G

Gast2

Gast
Also im Anhang mal ein Beispiel mit Sourcen.
Über das Eingabe Forumular kann man einen einzelnen Wert setzen mit Enter.
Bei der Other view werden alle Attribute auf einmal gesetzt und es kommen zuviele Events an und zeichnen neu.

Wie gesagt das Model hat natürlich in echt viel mehr attribute... Vielleicht hat jemand damit noch Erfahrungen ;)...
 

Marco13

Top Contributor
OK, mit den Dialogen wird natürlich schön deutlich, warum das blöd sein kann :D
Aber mal ganz abstrakt nachgefragt: Wie und wo soll auf Basis welcher Information entschieden werden, ob ein Event gefeuert werden soll, oder nicht? (Ich wüßte da nichts, was nicht schon erwähnt wurde ... aber vielleicht hat ja jemand eine Idee...)
 
G

Gast2

Gast
OK, mit den Dialogen wird natürlich schön deutlich, warum das blöd sein kann :D
Ja dachte mir ist vielleicht doch viel viel besser vorzustellen als der 1. Post ;)...

Aber mal ganz abstrakt nachgefragt: Wie und wo soll auf Basis welcher Information entschieden werden, ob ein Event gefeuert werden soll, oder nicht? (Ich wüßte da nichts, was nicht schon erwähnt wurde ... aber vielleicht hat ja jemand eine Idee...)

Hab ja auch nicht gesagt, dass die Ideen schlecht waren ;). Haben intern auch so ähnliche Ideen gehabt, aber mich interessiert ob es noch jemand mit solchen Probleme gibt und noch eine zündende Idee hat =)... Ich wollte mit dem Beispiel nur nochmal klar machen, dass es notwendig ist so granulare (jeder setter methode im model) Events zu haben, da es ein Formular mit allen Attributen gibt und auf der anderen Seite aber sch*** ist da zuviele Events kommen^^...

Eine Idee war eventuell ein Eventbus anzulegen indem eventuell auch der Controller events feuern kann. Und der Bus für die richtige Event verteilung zuständig ist so, dass es nur noch eine zentrale Stelle gibt.
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
Was ich auch sehr unrpraktisch finde ist, dass man in dem PropertyChangeSupport mehrmals den GLEICHEN Listener adden kann, ABER beim removen nur einer davon rausfliegt^^...
 

ThreadPool

Bekanntes Mitglied
Mir ist mal Folgendes untergekommen, jedes Model erbt von einer abstrakten Model-Klasse die stellte auch eine einfache Art PropertyChangeSupport als Member zur Verfügung. Neben anderen nützlichen Methoden gabs noch public Methoden setModifiziert() setUnmodifiziert() und der Member also das "Observable" konnte man an- oder abschalten. D.h. bei solchen Verbundoperationen hat man sich vom Model das "Observable" geholt, hat dann gesagt setAktiv(false), alle Werte geändert, wieder setAktiv(true) und als Letztes setModifiziert() aufgerufen.
 
G

Gast2

Gast
Mir ist mal Folgendes untergekommen, jedes Model erbt von einer abstrakten Model-Klasse die stellte auch eine einfache Art PropertyChangeSupport als Member zur Verfügung. Neben anderen nützlichen Methoden gabs noch public Methoden setModifiziert() setUnmodifiziert() und der Member also das "Observable" konnte man an- oder abschalten. D.h. bei solchen Verbundoperationen hat man sich vom Model das "Observable" geholt, hat dann gesagt setAktiv(false), alle Werte geändert, wieder setAktiv(true) und als Letztes setModifiziert() aufgerufen.

Wäre quasi der Vorschlag von oben ein boolean zu setzen...
 

Ähnliche Java Themen

Neue Themen


Oben