Discussion:
Designfrage zu Timer-Objekten
(zu alt für eine Antwort)
Michael Peters
2004-06-05 14:27:18 UTC
Permalink
Hallo,

ich entwickle derzeit eine Applikation nach MVC-Muster. Dabei geben
verschiedene Clients (Views) ab und an mal Befehle an den Controller ab,
der daraufhin das Model verändert. Allerdings sind diese Änderungen
zeitlich beschränkt, nach Ablauf dieser Zeit soll das Model wieder
"zurück-verändert" werden.

Jetzt habe ich mir überlegt, dass ich beim Verändern Timer-Objekte
starten kann, die zuerst schlafen (z.B. per Thread.sleep()) und sich
nach Ablauf der Zeit wieder zurückmelden.

Aber wer sollte diese Timer-Objekte starten und vorhalten? Etwa das
Model, weil ja auch nur das Model selbst wissen kann, dass es wieder
verändert gehört? Oder der Controller, obwohl der ja ansonsten keine
Informationen speichert?


Das ist übrigens eine ähnliche Frage, wie ich mir in dem Zusammenhang
auch noch stelle: Das Model ist persistent (DB), aber wer übernimmt den
Speicherungsanstoß? Das Model selbst, sobald Setter aufgerufen werden,
oder der Controller, da dieser weiß, welche Model-Objekte beteiligt
waren und somit gespeichert werden müssen?

ciya
Michael
Sebastian Scheid
2004-06-06 22:21:16 UTC
Permalink
Post by Michael Peters
ich entwickle derzeit eine Applikation nach MVC-Muster. Dabei geben
verschiedene Clients (Views) ab und an mal Befehle an den Controller ab,
der daraufhin das Model verändert. Allerdings sind diese Änderungen
zeitlich beschränkt, nach Ablauf dieser Zeit soll das Model wieder
"zurück-verändert" werden.
Jetzt habe ich mir überlegt, dass ich beim Verändern Timer-Objekte
starten kann, die zuerst schlafen (z.B. per Thread.sleep()) und sich
nach Ablauf der Zeit wieder zurückmelden.
Aber wer sollte diese Timer-Objekte starten und vorhalten? Etwa das
Model, weil ja auch nur das Model selbst wissen kann, dass es wieder
verändert gehört? Oder der Controller, obwohl der ja ansonsten keine
Informationen speichert?
Das gehört in den Controller. Dieser ruft nach Ablauf des Timers entweder
setter des Models mit den richtigen Werten auf, falls nur dem Controller und
nicht dem Model diese Werte bekannt sind. Oder er ruft eine reset()-Methode
auf, sodass das Model sich wieder in den richtigen Zustand bringt.

Das ist ja gerade der Sinn des Controllers. Du kannst ihn gegen einen
anderen ersetzen. Der eine Controller ruft alle x Sekunden nach einer
Änderung die Model#reset() Methode auf und ein anderer Controller tut das
nicht oder irgendetwas anderes eben. Das Verhalten der ganzen Konstruktion
liegt im Controller.
Post by Michael Peters
Das ist übrigens eine ähnliche Frage, wie ich mir in dem Zusammenhang
auch noch stelle: Das Model ist persistent (DB), aber wer übernimmt den
Speicherungsanstoß? Das Model selbst, sobald Setter aufgerufen werden,
oder der Controller, da dieser weiß, welche Model-Objekte beteiligt
waren und somit gespeichert werden müssen?
Kommt drauf an:
1. Es kann ja sein, dass durch eine Veränderung im View oder durch einen
Anstoß von außen mehrere setter Methoden des Models aufgerufen werden müssen
bevor es im richtigen Zustand ist. Würde bei jedem Aufruf einer setter
Methode gespeichert, könnte es sein, dass du die Integritätsregeln der DB
verletzt. Außerdem entstünden zu viele DB Zugriffe. Dann empfiehlt sich eine
save() Methode im Model, die vom Controller aufgerufen wird.

Bei einer einzelen save() Methode musst du dich vielleicht noch fragen, ob
es sinnvoll ist, nur veränderte Felder in die DB zu schreiben. Dann müsstest
du für jedes Feld ein dirty Flag mitschleppen.

2. Einfacher ist das, wenn du bei jedem setter Aufruf speicherst. Dann weißt
du ja, welches Feld dirty ist.
Wenn du dir sicher bist, dass du o.g. Probleme nicht hast (es wird also nur
ein Feld geändert bevor gespeichert werden soll / du hast keine
Integritätsbedingungen in der DB und die vermehrten Zugriffe sind dir auch
egal), kannst du frei nach XP diesen einfachsten Weg wählen. Wenn sich die
Situation irgendwann ändert, musst du refactorn, um in Richtung 1. zu gehen.


Schöne Grüße
Sebastian
Michael Peters
2004-06-07 07:21:26 UTC
Permalink
Hi Sebastian,

vielen Dank für deine Anregungen. Aber ich muss ja doch nochmal nachfragen:

Sebastian Scheid wrote:
[snip]
Post by Sebastian Scheid
1. Es kann ja sein, dass durch eine Veränderung im View oder durch einen
Anstoß von außen mehrere setter Methoden des Models aufgerufen werden müssen
bevor es im richtigen Zustand ist. Würde bei jedem Aufruf einer setter
Methode gespeichert, könnte es sein, dass du die Integritätsregeln der DB
verletzt. Außerdem entstünden zu viele DB Zugriffe. Dann empfiehlt sich eine
save() Methode im Model, die vom Controller aufgerufen wird.
[snip]
Post by Sebastian Scheid
2. Einfacher ist das, wenn du bei jedem setter Aufruf speicherst. Dann weißt
du ja, welches Feld dirty ist.
Wenn du dir sicher bist, dass du o.g. Probleme nicht hast (es wird also nur
ein Feld geändert bevor gespeichert werden soll / du hast keine
Integritätsbedingungen in der DB und die vermehrten Zugriffe sind dir auch
egal), kannst du frei nach XP diesen einfachsten Weg wählen. Wenn sich die
Situation irgendwann ändert, musst du refactorn, um in Richtung 1. zu gehen.
Sagen wir ich definiere, dass alle Zugriffe von außen auf das Model
immer über den Controller laufen müssen, insbesondere die Veränderungen.
Würdest du dann auch die Möglichkeit ausschließen, dass der Controller
Speicherungsanstöße gibt? Wäre ja praktisch, weil ich dann auch nur die
DB-Zugriffe mache, die notwendig sind (der Controller weiß was sich
verändert hat).
Damit aber der Controller mit keinen Datenbank-Objekten oder soetwas in
Berührung kommt, könnte ich für jedes Objekt eine save()-Methode
anbieten, die der Controller aufrufen kann um nur das betreffende Objekt
zu speichern. Dabei werden aber nur die nativen Datentypen
berücksichtigt, die Assoziationen zu anderen Objekten muss der
Controller selbst wieder speichern.

Wenn das generell keine gute Idee ist, den Controller sowas machen zu
lassen, muss ich mich wohl für die erste Variante entscheiden, da
Performance durchaus eine Rolle spielt. Ich merke es auch jetzt wieder,
für die Erstellung eines Models geht man immer nach Schema X vor, sobald
man erstmal einen guten Weg entdeckt hat. Da sollte man mal einen
Generator für basteln, das würde einem 60% der Arbeit ersparen...

ciya
Michael
Sebastian Scheid
2004-06-07 09:53:14 UTC
Permalink
Post by Michael Peters
[snip]
Post by Sebastian Scheid
1. Es kann ja sein, dass durch eine Veränderung im View oder durch einen
Anstoß von außen mehrere setter Methoden des Models aufgerufen werden müssen
bevor es im richtigen Zustand ist. Würde bei jedem Aufruf einer setter
Methode gespeichert, könnte es sein, dass du die Integritätsregeln der DB
verletzt. Außerdem entstünden zu viele DB Zugriffe. Dann empfiehlt sich eine
save() Methode im Model, die vom Controller aufgerufen wird.
[snip]
[undo snip]
Post by Michael Peters
Post by Sebastian Scheid
Bei einer einzelen save() Methode musst du dich vielleicht noch fragen, ob
es sinnvoll ist, nur veränderte Felder in die DB zu schreiben. Dann müsstest
du für jedes Feld ein dirty Flag mitschleppen.
Hiermit meinte ich ein Flag im Model. Sag ich nochmal, weil ích den Eindruck
hatte, dass das zu einem Missverständis geführt hat.
Post by Michael Peters
Post by Sebastian Scheid
2. Einfacher ist das, wenn du bei jedem setter Aufruf speicherst. Dann weißt
du ja, welches Feld dirty ist.
Wenn du dir sicher bist, dass du o.g. Probleme nicht hast (es wird also nur
ein Feld geändert bevor gespeichert werden soll / du hast keine
Integritätsbedingungen in der DB und die vermehrten Zugriffe sind dir auch
egal), kannst du frei nach XP diesen einfachsten Weg wählen. Wenn sich die
Situation irgendwann ändert, musst du refactorn, um in Richtung 1. zu gehen.
Sagen wir ich definiere, dass alle Zugriffe von außen auf das Model
immer über den Controller laufen müssen, insbesondere die Veränderungen.
Würdest du dann auch die Möglichkeit ausschließen, dass der Controller
Speicherungsanstöße gibt? Wäre ja praktisch, weil ich dann auch nur die
DB-Zugriffe mache, die notwendig sind (der Controller weiß was sich
verändert hat).
Du meinst, in diesem Fall weiß der Controller welche Veränderungen gemacht
wurden, weil nur er sie gemacht hat und niemand anders? Dann müsste der
Controller dem Model mit Parametern der save Methode sagen, welche Felder
gespeichert werden sollen?
Das würde ich eher vermeiden, denn erstens würde ich diese Einschränkung
nicht machen (nur Controller verändert Model). Das Model sollte auch von
außerhalb dieses MVC veränderbar sein. Wenn du immer den Umweg über den
Controller gehst, hast du jede Menge Methoden im Controller, die einfach nur
ans Model forwarden. Ich sehe das als unnötigen Ballast an.
Zweitens müsste dann der Controller die Aufgabe übernehmen, sich die dirty
Felder zu merken und diese dirty Felder beim speichern auch noch ans Model
übergeben. Die Übergabe ist zu aufwändig (bool Parameter in der save Methode
für jedes Feld oder verschiedene save()-Methoden für jedes Feld... ne warte
da bekommt man es mit Kombinatorik zu tun, gar nicht gut). Außerdem sollen
die Controller ja austauschbar sein. Dann müsstest du dich in jedem
Controller Typ drum kümmern.

Also: WIE gespeichert wird (Berücksichtigung von dirty Feldern oder nicht)
gehört ins Model. WANN gespeichert wird haben wir ja oben schon besprochen.
Post by Michael Peters
Damit aber der Controller mit keinen Datenbank-Objekten oder soetwas in
Berührung kommt, könnte ich für jedes Objekt eine save()-Methode
anbieten, die der Controller aufrufen kann um nur das betreffende Objekt
zu speichern.
Für jedes Objekt (du meinst damit doch die Felder deines Models, oder?) eine
save Methode ist das gleiche wie bei jedem setter Aufruf zu speichern. Damit
sparst du keine DB Zugriffe und mit der Integrität der Daten in der DB
bekommst du die o.g. Probleme.
Post by Michael Peters
Dabei werden aber nur die nativen Datentypen
berücksichtigt, die Assoziationen zu anderen Objekten muss der
Controller selbst wieder speichern.
Nein, nein. Siehe oben. WIE gespeichert wird, muss das Model wissen.
Post by Michael Peters
Wenn das generell keine gute Idee ist, den Controller sowas machen zu
lassen, muss ich mich wohl für die erste Variante entscheiden, da
Performance durchaus eine Rolle spielt.
Du solltest auch überdenken, ob der Controller für dich wirklich sinnvoll
ist. Du musst nicht ganz starr an einem Pattern festhalten. Gerade MVC wird
oft diskutiert. Es gibt es verschiedene Abarten davon. Oft werden Controller
und Model in einer Klasse abgebildet. Bei Swing ist es zum Beispiel oft so.
Wenn es bei dir z.B. gar keine verschiedenen Controller gibt, die du
austauschen möchtest, reduziert sich der Sinn des Controllers auf eine
Trennung zwischen Daten (im Model) und Vehalten (im Controller. Na gut, ein
bisschen Speicherungs Logik steckt auch im Model). Wie wir ja wissen, macht
das aber eine Klasse aus. Das Model könnte also durchaus ein bisschen
Intelligenz mitbringen und muss nicht nur ein Datencontainer sein.
Verschiedenes Verhalten (also Austauschen des Controllers) kannst du auch
durch ein Strategy Pattern im Model nachbilden.
Das geht halt dann nicht mehr, wenn du verschiedene Views hast und jeder
View einen anderen Controller bekommen soll. Aber wenn du aussschließlich an
der Trennung von Daten/Logik und View interessiert bist (was schon mal sehr
gut ist), dann bauchst du kein extra Controller Objekt.


Schöne Grüße
Sebastian
Michael Peters
2004-06-07 10:38:11 UTC
Permalink
Sebastian Scheid wrote:

[snip]
In dem Teil hatte ich grad ne Menge Kamm-Quoting, kam das von mir (hab
erst seit kurzem Thunderbird als Newsreader)?
[snap]

Um es mal vorwegzunehmen:
Beim Schreiben dieses Posts bin ich zu dem Schluss gekommen, dass deine
Dirty-Flag-Methode tatsächlich die beste ist.
Das ist jetzt die Kurzfassung, wenn du wissen willst, warum, dann kannst
du auch weiterlesen ;)
Post by Sebastian Scheid
Post by Michael Peters
Sagen wir ich definiere, dass alle Zugriffe von außen auf das Model
immer über den Controller laufen müssen, insbesondere die Veränderungen.
Würdest du dann auch die Möglichkeit ausschließen, dass der Controller
Speicherungsanstöße gibt? Wäre ja praktisch, weil ich dann auch nur die
DB-Zugriffe mache, die notwendig sind (der Controller weiß was sich
verändert hat).
Du meinst, in diesem Fall weiß der Controller welche Veränderungen gemacht
wurden, weil nur er sie gemacht hat und niemand anders?
Genau.
Post by Sebastian Scheid
Dann müsste der
Controller dem Model mit Parametern der save Methode sagen, welche Felder
gespeichert werden sollen?
Das meinte ich etwas anders:
Der Controller verändert im Zuge einer Arbeit ein paar Objekte oder legt
neue an. Diese Objekte bieten alle eine save()-Methode an. Dann könnte
der Controller nach getaner Arbeit diese Objekte abspeichern, und zwar
nur diese und nur in ihrer Gesamtheit (beispielsweise über eine
Transaction), so dass also auch die DB-Konsistenz gewahrt bleibt. Wenn
ich dem gesamten Model sage: "speicher dich mal" und mit den Dirty-Flags
arbeite, würden zwar auch nur die Objekte gespeichert, die sich
verändert haben, aber dafür müsste das gesamte Model durchgeforstet
werden, was bei vielen Objekten evtl. langsamer sein könnte.
Post by Sebastian Scheid
Das würde ich eher vermeiden, denn erstens würde ich diese Einschränkung
nicht machen (nur Controller verändert Model). Das Model sollte auch von
außerhalb dieses MVC veränderbar sein. Wenn du immer den Umweg über den
Controller gehst, hast du jede Menge Methoden im Controller, die einfach nur
ans Model forwarden. Ich sehe das als unnötigen Ballast an.
Das stimmt. Allerdings frage ich mich, ob ein Dirty-Flag zu jedem
Attribut (was die Anzahl der nativen Daten-Attribute verdoppelt) nicht
auch solch ein Ballast ist.
Post by Sebastian Scheid
Zweitens müsste dann der Controller die Aufgabe übernehmen, sich die dirty
Felder zu merken und diese dirty Felder beim speichern auch noch ans Model
übergeben.
Nein er müsste sich nur die _Objekte_ merken, die verändert wurden,
nicht welche Felder (Attribute) in den Objekten. Bzw. muss er sich die
Objekte nichtmal merken, weil er sie ja bei der Benutzung schon hat.
Dann kann er diesen Objekten sagen, dass sie sich speichern sollen.
Dirty-Flags hätte ich in dem Fall nirgendwo. Dabei speichere ich zwar
auch Objekte, die im Zuge der Arbeit zwar benutzt aber nicht verändert
wurden, aber das sollten eher weniger sein, denn irgendwas will man ja
immer verändern.
Post by Sebastian Scheid
Die Übergabe ist zu aufwändig (bool Parameter in der save Methode
für jedes Feld oder verschiedene save()-Methoden für jedes Feld... ne warte
da bekommt man es mit Kombinatorik zu tun, gar nicht gut). Außerdem sollen
die Controller ja austauschbar sein. Dann müsstest du dich in jedem
Controller Typ drum kümmern.
Das mit der Kombinatorik fällt dann flach (s.o.). Es stimmt aber, dass
die Controller sich alle darum kümmern müssten. Obwohl es ja nicht viel
Aufwand ist, wenn jeder Controller allen Objekte, die er grad benutzt
hat, noch .save() sagt.
Post by Sebastian Scheid
Also: WIE gespeichert wird (Berücksichtigung von dirty Feldern oder nicht)
gehört ins Model. WANN gespeichert wird haben wir ja oben schon besprochen.
Würde bei mir auch hinhauen:
WAS: Nur die veränderten Objekte.
WIE: Wissen die Objekte in ihrer save()-Methode (also das Model)
WANN: Weiß der Controller, nämlich nach getaner Arbeit. Und zwar ganz
oder gar nicht (Konsistenz).
Post by Sebastian Scheid
Post by Michael Peters
Damit aber der Controller mit keinen Datenbank-Objekten oder soetwas in
Berührung kommt, könnte ich für jedes Objekt eine save()-Methode
anbieten, die der Controller aufrufen kann um nur das betreffende Objekt
zu speichern.
Für jedes Objekt (du meinst damit doch die Felder deines Models, oder?) eine
save Methode ist das gleiche wie bei jedem setter Aufruf zu speichern. Damit
sparst du keine DB Zugriffe und mit der Integrität der Daten in der DB
bekommst du die o.g. Probleme.
Mit Objekt meinte ich eine Instanz einer Klasse des Models. Also bietet
jede Klasse die save()-Methode zu ihren Objekten. Somit kann ich erst
alle Setter setzen und dann hinterher einmal save() sagen.
Post by Sebastian Scheid
Post by Michael Peters
Dabei werden aber nur die nativen Datentypen
berücksichtigt, die Assoziationen zu anderen Objekten muss der
Controller selbst wieder speichern.
Nein, nein. Siehe oben. WIE gespeichert wird, muss das Model wissen.
Da hast du Recht und damit wären wir bei dem gewichtigen Problem,
welches ich sehe. Bis hier hin ist alles klar, nur nicht wie ich mit den
Assoziationen verfahre. Eigentlich müsste ich auch jeder Ass. sagen,
"speicher dich mal". Aber dann wär ich wieder beim Durchforsten des
gesamten Models unterhalb des Objektes (wenn ich mir alle Instanzen des
Models als Baum vorstelle; wenns ein Busch ist, muss ich sogar das ganze
Model speichern).

Wenn ich das eh nicht vermeiden kann, wäre die Dirty-Flag-Variante
wieder diejenige meiner Wahl.
Post by Sebastian Scheid
Das geht halt dann nicht mehr, wenn du verschiedene Views hast und jeder
View einen anderen Controller bekommen soll. Aber wenn du aussschließlich an
der Trennung von Daten/Logik und View interessiert bist (was schon mal sehr
gut ist), dann bauchst du kein extra Controller Objekt.
Ich hab den Controller sogar noch aus einem anderen Grund. Und zwar gibt
es viele Views, die ich sogar selbst noch nichtmal alle kenne. Alle
Views wollen vom Model Informationen bekommen und auch Veränderungen
durchführen. Würde ich die Methoden, die dafür verantwortlich sind,
nicht alle im Controller haben, würden die Views viele Klassen und ihre
Struktur kennen müssen, was es natürlich umständlicher macht. Außerdem
kann ich so sicherstellen, dass keine View etwas macht, was sie nicht darf.

Viele Grüße
Michael
Michael Peters
2004-06-07 11:04:03 UTC
Permalink
Post by Michael Peters
Beim Schreiben dieses Posts bin ich zu dem Schluss gekommen, dass
deine Dirty-Flag-Methode tatsächlich die beste ist.
Das ist jetzt die Kurzfassung, wenn du wissen willst, warum, dann
kannst du auch weiterlesen ;)
Wenn ich das mit Dirty-Flags mache, habe ich das Problem, dass der
Vorgang der Speicherung des kompletten Models unterbrochen wird. Und
dann wäre der Datenhaushalt in der DB doch wieder inkonsistent.

Lösung wäre, dass ich in der globalen save()-Methode, die vom Controller
aufgerufen wird, eine Transaction erstelle und diese an alle anderen
save()-Methoden mitübergebe. Dann reihen sich da die Objekte ein, die
geändert wurden, und zum Schluss mache ich dann einen Commit.

Wäre das korrekt?
Sebastian Scheid
2004-06-07 14:54:43 UTC
Permalink
Post by Michael Peters
Post by Michael Peters
Beim Schreiben dieses Posts bin ich zu dem Schluss gekommen, dass
deine Dirty-Flag-Methode tatsächlich die beste ist.
Das ist jetzt die Kurzfassung, wenn du wissen willst, warum, dann
kannst du auch weiterlesen ;)
Wenn ich das mit Dirty-Flags mache, habe ich das Problem, dass der
Vorgang der Speicherung des kompletten Models unterbrochen wird. Und
dann wäre der Datenhaushalt in der DB doch wieder inkonsistent.
Lösung wäre, dass ich in der globalen save()-Methode, die vom Controller
aufgerufen wird, eine Transaction erstelle und diese an alle anderen
save()-Methoden mitübergebe. Dann reihen sich da die Objekte ein, die
geändert wurden, und zum Schluss mache ich dann einen Commit.
Wäre das korrekt?
Richtig.
Sebastian Scheid
2004-06-07 14:53:59 UTC
Permalink
[snip]
Post by Michael Peters
Post by Sebastian Scheid
Zweitens müsste dann der Controller die Aufgabe übernehmen, sich die dirty
Felder zu merken und diese dirty Felder beim speichern auch noch ans Model
übergeben.
Nein er müsste sich nur die _Objekte_ merken, die verändert wurden,
nicht welche Felder (Attribute) in den Objekten. Bzw. muss er sich die
Objekte nichtmal merken, weil er sie ja bei der Benutzung schon hat.
Dann kann er diesen Objekten sagen, dass sie sich speichern sollen.
Dirty-Flags hätte ich in dem Fall nirgendwo. Dabei speichere ich zwar
auch Objekte, die im Zuge der Arbeit zwar benutzt aber nicht verändert
wurden, aber das sollten eher weniger sein, denn irgendwas will man ja
immer verändern.
Das ist eine Frage der Granularität der dirty Flags. Es kann ja sein, dass
von den hundert Feldern deines Objekts nur eins verändert wurde. Wenn man
möchte, könnte man halt für jedes Feld ein Flag halten. Und das sollte dann
nicht mehr der Controller machen. Der kann sich merken, welche Objekte er
geändert hat, was einer gröberen Granularität entspräche.
Die Frage ist halt, ob sich der Aufwand performancetechnisch lohnt. Wenn
nicht, macht es natürlich Sinn, das ganze Objekt zu speichern.

[snip]
Post by Michael Peters
Post by Sebastian Scheid
Post by Michael Peters
Dabei werden aber nur die nativen Datentypen
berücksichtigt, die Assoziationen zu anderen Objekten muss der
Controller selbst wieder speichern.
Nein, nein. Siehe oben. WIE gespeichert wird, muss das Model wissen.
Da hast du Recht und damit wären wir bei dem gewichtigen Problem,
welches ich sehe. Bis hier hin ist alles klar, nur nicht wie ich mit den
Assoziationen verfahre. Eigentlich müsste ich auch jeder Ass. sagen,
"speicher dich mal". Aber dann wär ich wieder beim Durchforsten des
gesamten Models unterhalb des Objektes (wenn ich mir alle Instanzen des
Models als Baum vorstelle; wenns ein Busch ist, muss ich sogar das ganze
Model speichern).
Wenn ich das eh nicht vermeiden kann, wäre die Dirty-Flag-Variante
wieder diejenige meiner Wahl.
Naja, du könntest zwei verschiedene Arten zu speichern anbieten. Einmal
flach (save(), ohne Ass.) und einmal tief (saveAll()).
So kannst du deinem Wurzel Objekt sagen saveAll() und es erledigt alles
selbst, samt Durchforsten des Objektbaums. Und wenn der Controller sich
einzelne Kinder oder Enkel aus der Wurzel geholt und verändert hat bzw. wenn
nur Standard-Typen in einem Knoten deines Baums verändert wurden, dann rufst
du auf dem veränderten Objekt save() auf und vermeidest, dass Ass.
mitgespeichert werden.
Ob du dann noch dirty Flags in den Model Klassen für die einzelnen Felder
hältst, ist eine andere Entscheidung.
saveAll() wäre dann nur eine convenient Methode.
Post by Michael Peters
Post by Sebastian Scheid
Das geht halt dann nicht mehr, wenn du verschiedene Views hast und jeder
View einen anderen Controller bekommen soll. Aber wenn du
aussschließlich an
Post by Michael Peters
Post by Sebastian Scheid
der Trennung von Daten/Logik und View interessiert bist (was schon mal sehr
gut ist), dann bauchst du kein extra Controller Objekt.
Ich hab den Controller sogar noch aus einem anderen Grund. Und zwar gibt
es viele Views, die ich sogar selbst noch nichtmal alle kenne. Alle
Views wollen vom Model Informationen bekommen und auch Veränderungen
durchführen. Würde ich die Methoden, die dafür verantwortlich sind,
nicht alle im Controller haben, würden die Views viele Klassen und ihre
Struktur kennen müssen, was es natürlich umständlicher macht. Außerdem
kann ich so sicherstellen, dass keine View etwas macht, was sie nicht darf.
Das klingt alles nach einer recht komplexen Struktur. Bist du sicher, dass
du das nicht noch aufteilen und mehrere MVCs draus machen kannst?
Zusätzlich könntest du eine kleine Fassade draus machen und hast auch nicht
das Problem mit deinen Ass. Der Controller kennt dann nur ein Model Objekt
mit verschiedenen Zugriffsmethoden. Diese werden dann vielleicht teilweise
an Ass. geforwardet.
Das macht Sinn, wenn die Anzahl an Zugriffsmethoden nicht ausufert.

Schöne Grüße
Sebastian
Michael Peters
2004-06-07 15:09:04 UTC
Permalink
Post by Sebastian Scheid
Naja, du könntest zwei verschiedene Arten zu speichern anbieten. Einmal
flach (save(), ohne Ass.) und einmal tief (saveAll()).
Gute Idee! :)
Post by Sebastian Scheid
Das klingt alles nach einer recht komplexen Struktur. Bist du sicher, dass
du das nicht noch aufteilen und mehrere MVCs draus machen kannst?
Zusätzlich könntest du eine kleine Fassade draus machen und hast auch nicht
das Problem mit deinen Ass. Der Controller kennt dann nur ein Model Objekt
mit verschiedenen Zugriffsmethoden. Diese werden dann vielleicht teilweise
an Ass. geforwardet.
Das macht Sinn, wenn die Anzahl an Zugriffsmethoden nicht ausufert.
Wenn der Controller nur ein Model-Objekt kennen würde, wäre dieses
Model-Objekt ja wieder selbst eine Art Controller. Aber diese
zusätzliche Abstraktionsschicht brauche ich gar nicht, denn es reicht
IMHO vollkommen, wenn der derzeitige Controller der einizige Controller ist.
So kompliziert, wie es vielleicht klingt, ist es auch gar nicht, denn
zum Glück weiß ich jetzt schon, was _alle_ Views vom Controller wollen.
D.h. es wird 100%ig nie einen Fall geben, in der eine View vom
Controller etwas anderes will als eine andere. Es kann nur mal so sein,
dass eine View mehr Funktionen braucht als eine andere, aber sonst nix.
So brauch ich nur diesen einen Controller und alle Views können ihn
nutzen :)

ciya
Michael
Martin Heibel
2004-06-09 16:28:19 UTC
Permalink
Hi,

ich habe den Thread oben nur ansatzweise verfolgt, da er sich schnell in für
Deine Frage irrelevanten Details verliert.
Post by Michael Peters
ich entwickle derzeit eine Applikation nach MVC-Muster. Dabei geben
verschiedene Clients (Views) ab und an mal Befehle an den Controller ab,
der daraufhin das Model verändert. Allerdings sind diese Änderungen
zeitlich beschränkt, nach Ablauf dieser Zeit soll das Model wieder
"zurück-verändert" werden.
Jetzt habe ich mir überlegt, dass ich beim Verändern Timer-Objekte
starten kann, die zuerst schlafen (z.B. per Thread.sleep()) und sich
nach Ablauf der Zeit wieder zurückmelden.
Nimm doch java.util.Timer.
Post by Michael Peters
Aber wer sollte diese Timer-Objekte starten und vorhalten? Etwa das
Model, weil ja auch nur das Model selbst wissen kann, dass es wieder
verändert gehört?
Das weiß es nicht. Ein Model ist "dumm" es kann seine Konsistenz
gewährleisten und Observer (=Views) über Änderungen benachrichtigen, sonst
nix.
Post by Michael Peters
Oder der Controller, obwohl der ja ansonsten keine
Informationen speichert?
Jein.

Mach Dir eine besondere (unsichtbare) View, deren "Eingabefelder" die zu
verändernden Daten sind und die nach Ablauf der Zeit die Daten ändert.
Angestoßen werden die Timer über Änderungen am Modell. Diese View hat
natürlich auch einen Controller (wobei ich mich hier nicht sklavisch an MVC
halten würde), der auf die Timer-Events reagiert.

Wenn sehr viele Daten zu ändern sind, dann kann man einen Timer nehmen, der
in regelmäßigen Abständen eine Liste bearbeitet, in der die Änderungen
(z.B. als Command-Objekte) nach fälligkeit sortiert liegen. Wenn die Zeit
für alle gleich ist, entfällt die Sortierung, da sie ja automatisch in der
richtigen Reihenfolge eingefügt werden.
Post by Michael Peters
Das ist übrigens eine ähnliche Frage, wie ich mir in dem Zusammenhang
auch noch stelle: Das Model ist persistent (DB), aber wer übernimmt den
Speicherungsanstoß? Das Model selbst, sobald Setter aufgerufen werden,
Das hat meistens zu viele Speichervorgänge zur Folge. Außerdem will man ja
oft größere Datenmengen zusammen speichern (->Transaktionen).
Post by Michael Peters
oder der Controller, da dieser weiß, welche Model-Objekte beteiligt
waren und somit gespeichert werden müssen?
Ja. Ein klassisches Bsp. wäre ein Dialog zum Eingeben von Daten: wenn der
Controller den "OK"-Klick verarbeitet, speichert er die Daten im Model, das
sie dann in die DB schreibt.

Das Model kann auch eine Schnittstelle anbieten, die nur Größere Datenpakete
in Empfang nimmt (Value-Object-Pattern, ursprünglich für den Datentransfer
zu entfernten Objekten entwickelt). Dann gibt es gar keine Setter, die
einzelne Attribute im Modell ändern.

Gruß,
Martin

Loading...