Laden...

Designfrage: "interaktives" CommandPattern

Erstellt von zommi vor 15 Jahren Letzter Beitrag vor 15 Jahren 2.215 Views
zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren
Designfrage: "interaktives" CommandPattern

Hallo an alle,

in meiner Anwendung soll es die Möglichkeit geben per Drag'n'Drop Objekte in eine Zeichenfläche zu ziehen, verschieben, verbinden...
(quasi Diagramme zeichnen)

Natürlich mit Undo/Redo, weshalb ich auch das CommandPattern verwende.
Aber diese Commands versetzen mein Diagramm von einem "statischen" Zustand in einen anderen.
(Also wenn ich was verschoben hab und Undo mache, dann isses wieder an der alten Stelle.)

Nun will ich aber auch dynamische Interaktionen ermöglichen und (analog zum CommandPattern) als "Interactions" implementieren.
Also eine Art "temporärer" Zustandsspeicher.
Temporär deshalb, weil (bsp. bei Movement) der genaue Verschiebungsweg nirgends gespeichert werden soll.
(Wär natürlich cool, wenn sich die Objekte bei einem Undo auf dem selben Weg, wie ich es gezogen hab, rückwärts bewegen, aber das is Schnulli 😉 )

Aber jetzt ist meine Frage: Wie mach ich das am besten?
Und ist die Grundidee überhaupt gut?

Commands sind halt: Move, Add, Remove, ...
Und Interactions wären: Moving, Resizing, ...
(Wie man an der Namensgebung sieht, eher dynamische als statisch)

Wie bau ich das nun in Klassen um?

Oder findet ihr: Interactions sind auch Commands?
Fänd ich auf den ersten Blick nicht, diese beinhalten auch ja noch mehr Information die für das Command später irrelevant sind.

Sollte anderseits jede Interaktion (wie Moving) dann in einem Command (Move) resultieren?
Beispielsweise:

class Interaction
{
  ...
  public void StartInteraction() {...}
  public Command EndInteraction(){...}
}

Wie würdet ihr sowas lösen?
Und natürlich wie ist es elegant und gut ?

beste Grüße
zommi

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo zommi,

hm, so ganz ist es mir noch nicht klar.

Im Prinzip ist doch der Verschiebungsweg nicht anders als ein Parameter eines Commands. Natürlich ist bei Interaktionen das Kommando zu dem Zeitpunkt, zu dem mal alle Informationen hat, schon ausgeführt. Aber das lässt sich ja bei der Implementierung des Commands berücksichtigen.

Oder übersehe ich noch was?

herbivore

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

ich dachte immer, Commands sollten von Hause aus _immutable _ sein.
Also ein einmal erzeugtes


Command cmd = new CommandMove(actualObject, startPoint, endPoint);

sollte ich nich mehr verändern, und damit auch den "endPoint" nicht mehr.

Ich empfand da son rumfummeln drin, wie ein manipulieren der History - unschön oda nich?

Deshalb die Idee der Interactions, die ich mit _Start _ enleite und mit _End _beende. Die kann ich dann auch ständig manipulieren.
(oder mit _Abort _abbreche)
Aber eine einmal abgeschlossene Interaktion erzeugt wieder ein immutable Command.

Is doof ?

//Edit:
Aber wenn du nicht findest, dass das "ins Command mir reinpacken" schlechter Stil is, is ja auch schonmal gut 🙂 Und eine Meinung, die ich mir merken werde 😉

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo zommi,

ich dachte immer, Commands sollten von Hause aus immutable sein.

ja, so würde ich das auch sehen.

Mein Vorschlag war das Command zu erzeugen, nachdem die Interaktion abgeschlossen ist.

Natürlich ist bei Interaktionen das Kommando zu dem Zeitpunkt, zu dem mal alle Informationen hat, schon ausgeführt. Aber das lässt sich ja bei der Implementierung des Commands berücksichtigen.

Ich hätte besser schreiben sollen:

Natürlich ist bei Interaktionen die eigentliche Aktion zu dem Zeitpunkt, zu dem mal alle Informationen hat und mit diesen das Command-Objekt erzeugen kann, schon ausgeführt. Aber das lässt sich ja bei der Implementierung der entsprechenden Command-Klasse berücksichtigen.

herbivore

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

aah, du meinst mit:

Natürlich ist bei Interaktionen das Kommando zu dem Zeitpunkt, zu dem mal alle Informationen hat, schon ausgeführt. Aber das lässt sich ja bei der Implementierung des Commands berücksichtigen.

dass es auch möglich sein sollte ein Command zu erzeugen, OHNE es zeitgleich auszuführen. (Da ja das eigentliche Verschieben bereits getätigt wurde)
(Ok, beim Verschieben sollte es nun gerade doch hinhauen, weil es ja keinen stört, wenn ich das Objekt nochmal an die jetzt aktuelle Stelle positioniere...)

Aber die Informationen die ich sammel (und dann später für die Erzeugung des Commands benötige) könnte man doch in eigene Klassen kapseln ???

Oder is mein "in eigene Klassen packen"-Wahn hier doch übertrieben?
und ich sollte die temporären Informationen... (Anfangsposition, aktuelle Position) einfach als Felder in meiner Diagramm-Klasse, oder besser gesagt, der zugehörigen GUI-DiagramViewer-Klasse einbauen ?

beste Grüße
zommi

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo zommi,

aah, du meinst [...], dass es auch möglich sein sollte ein Command zu erzeugen, OHNE es zeitgleich auszuführen.

Ich meine, ohne es überhaupt auszuführen, weil es die Aktion ja schon durchgeführt ist. Das Command-Objekt dient also nicht für das Ausführen der eigentlichen Aktionen, sondern nur für das Undo und das Redo (da muss die Aktion allerdings echt ausgeführt werden; insofern kann man sich die Implementierung der ExecuteCore-Methode nicht sparen, sondern muss nur verhindern, dass der erste Aufruf von ExecuteCore was tut).

Aber die Informationen die ich sammel (und dann später für die Erzeugung des Commands benötige) könnte man doch in eigene Klassen kapseln ???

Hm, das Command-Objekt ist ja schon die Kapsel. Eine weitere Kapsel brauchst du m.E. nicht.

herbivore

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo zommi,

ich muss das mit dem Immutable etwas differenzieren. Bevor Excecute aufgerufen wird, ist das Objekt nicht Frozen. Insofern kann man es als vor der Interaktion erzeugen, während der Interaktion ändern und nach der Aktion ausführen (Execute). Das spricht noch mehr dafür das Command-Objekt als Kapsel zu verwenden.

herbivore

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Hallo herbivore,

dann werd ich das wohl versuchen alles im Command unterzubringen.

Ich denke ja, dass egal welche Heransgehensweise, der Programmieraufwand ähnlich ist. Aber gerade dann kann man sich ja an den Allgemeinwillen halten, oder zumindest gebräuchliche Patterns. Das macht schließlich das Verständnis von anderer Seite einfacher.

Wenn ich auf grobe Schwierigkeiten und Ungereimtheiten stoße, meld ich mich nochmal.

Das einzige, was mir momentan etwas Unbehagen bereitet:
Bisher hatte ich im Move-Command nicht die Start-Position + End-Position (4 Zahlen) abgespeichert, sondern immer lediglich die relative Verschiebung (2 Zahlen).
Schließlich können die Commands alle inkrementell aufeinander aufbauen, sodass relative Angaben ja reichen.
Auch bei einem Resize reicht ja : "um 20 Pixel breiter" und nicht "von 10 auf 30"

Will ich aber nun die "laufende" Aktion des Verschiebens mit reinnehmen, muss ich ja die Startposition mit abspeichern + die aktuelle (bzw. Endposition).
Nicht dass es mir um Performance/Speichergründe ging, aber Redundanz kann ich nich leiden 😉

beste Grüße
zommi

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Eigener Nachtrag:

Mhh... aber vielleicht ist es doch nicht schlecht Start+Endposition zu speichern.
Momentan arbeite ich zwar mit Int-Werten,
aber wenn die Zukunft mich in die 3d-Wert verschlägt und ich irgendwie gezwungen bin mit Float-Werten zu rechnen, dann kommts durch das "aufsummieren" beim verschieben ja zu Rechenfehlern, die sich bei aneinandergereihten Commands vervielfachen können. Also schlecht !
Man sollte deshalb wohl doch lieber die "exakte" Position speichern und einfach auf diese setzen!

Also Rechengenauigkeit bezwingt Redundanz 😉

beste Grüße
zommi

915 Beiträge seit 2006
vor 15 Jahren

Hrm, beim CommandPattern sollten immer alle Daten Redundant gespeichert werden. Spätestens beim Undo/Redo, wenn dir Adobe Photoshop mit den Aktionen vorstellst, dort hast ja ebenso die Möglichkeit zu sagen ich möchte von Aktion 20 alle Rückgängigmachen bis wieder hin zu aktion 15. Und somit macht es Sinn wirklich alle Daten wie bei dir nun End + Startposition zu merken. Der Witz am CommandPattern ist ja das es so erweitenr kannst wie du Lust hast. Du könntest dir statt nur Punkte wie X und Y vom Start wie Endpunkt zu merken das gesammte Object als solches merken z.B. via Serialisierung. Der Vorteil hierbei wäre, selbst wenn du Vorhast zusätzliche Aktionen einzubauen könntest du beim Undo / Redo direkt auf das gewählte Undo / Redo Command hin und herspringen ohne das irgendwelche Berechnungen anfallen oder Commands die dazwischen lagen / liegen wiederholt ausführen musst.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Tja,
Photoshop is ja auch geil 😉

Aber das klingt sehr logisch und gut.

Noch eine Geschmacksfrage:
Wenn ich mehrere Objekte verschieben will.
Sollte ich eurer Meinung nach:

  1. Ein Makro-Command (Als Liste von einzelnen Move-Commands) verwenden
    oder
  2. Das Move-Command dahingehen erweitern, dass es direkt mehrere Objekte aufnehmen kann (also ne Liste einbauen)
    ?

beste Grüße
zommi

915 Beiträge seit 2006
vor 15 Jahren

Hrm, das kommt ganz darauf an.

1.) Eine einzelne Liste wäre für Undo / Redo ausreichend also sprich das Makro-Command reicht. Stell dir dazu einfach wieder Adobe Phoroshop vor. GUi Technisch würdest du evtl. 5 mal Move-Command sehen und vielleicht 3 mal ein anderes Command usw. Jedes Command würde einzeln dastehen in einer für den Benutzer ersichtlichen und logischen Reihenfolge.

2.) Wenn du jede Aktion mit einer Liste versiehst bräuchtest (Move-Command) sähe das wie folgt aus. Du hättest eine Liste mit allen Command's also Move-Command und andere Commands die du so hast. Wenn man nun Move-Command anklickt sieht man zwar in einer logischen reihenfolge die einzelnen Move-Commands. Aber man würde nicht mehr sehen wurde zuerst Move-Command ausgeführt oder irgend ein andere Command. Hier hätte der Benutzer selber keine Chance mehr zu verstehen was er rückgängig machen müsste um seine z.B. letzte Aktion rückgängig zu machen.

Wenn kein UI Pflegst und kein Undo / Redo direkt verwenden möchtest für den Benutzer ersichtlich its, wäre es egal was du machst - hier käme es darauf an was dein Programm den mit der Liste anstellt. Ansonsten rate ich dir lieber zu Punkt 1.) - denn in den meisten Fällen tut's das allemale und selten muss man innerhalb eines Commands eine einzelne Aktion rückgängig machen bzw. wiederherstellen.

Vorallem wenn eh das ganze zu behandelnde Object serialisierst. Denk dran, eine Singleton wird sogut wie immer beim CommandPattern gebraucht, dort hast du dann auch deine Macro-Liste.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Hallo Andreas,

neinnein, ich meinte das anders 🙂

Ich wähle mit soner art Rechteck als User gleich mal mehrere Objekte im Diagramm aus. (Dann erscheint da son gestricheltes Rechteck, was alle markierten einschließt, oder so)

Und jetzt verschiebe ich diese gesamte "Gruppe" als User.

Wie sollte ich das auf Code seite implementieren?

  1. Für jedes einzelne Objekt in dieser Gruppe ein einzelnes Move-Command,
    diese dann aber in einem Makro-Command kapseln. (schließlich soll mein Rückgängig machen jetzt nicht erst eins nach dem andern zurückhüpfen, sondern wieder alle als Gruppe)
    (Und das Makro-Command sorgt natürlich dafür, dass die Unter-Commands alle ausgrührt werden, also sogesehen mehr ein Command-Group-Command)

oder

  1. Das Move-Command kann gleich mehrere Objekte aufnehmen, also auch eine ganze Gruppe von Objekten und diese quasi "gleichzeitig" bewegen.

Was ist denn eurer meinung nach vorteilhafter ?
(ich weiß Geschmacksfrage wahrscheinlich, aber was schmeckt denn so nem C#-Entwickler ?)

beste Grüße
zommi

PS: wo brauch ich denn bei den Commands ne Singleton-Klasse?

915 Beiträge seit 2006
vor 15 Jahren

Ah, da habe ich das falsch verstanden. Da eher Punkt 2.) nur noch etwas ausführlicher gegliedert.

Na würde sagen das folgende Commands dabei ausgeführt werden.
In einer Asgabe sähe das ca. wie folgt aus:

1 SelectCommand GrafischesObj 1 -> Serialize Grafische Ansicht - BubleEvent Bevore
2 SelectCommand GrafischesObj 1 -> Serialize Grafische Ansicht - BubleEvent After
3 SelectCommand GrafischesObj 2 -> Serialitze Grafische Ansicht - BubleEvent 4 Bevore
5 SelectCommand GrafischesObj 2 -> Serialitze Grafische Ansicht - BubleEvent After
6 SelectCommand GrafischesObj 3 -> Serialize Grafische Ansicht - BubleEvent Bevore
7 SelectCommand GrafischesObj 3 -> Serialize Grafische Ansicht - BubleEvent After
8 SelectCommand GrafischesObj 4 -> Serialize Grafische Ansicht - BubleEvent Bevore
9 SelectCommand GrafischesObj 4 -> Serialize Grafische Ansicht - BubleEvent After
10 GroupCommand List<CurrentSelectCommandItems> Array[] {GrafischesObj 1, GrafischesObj 2, GrafischesObj 3 , GrafischesObj 4}; -> Serialize Grafische Ansicht - BubleEvent Bevore
11 GroupCommand List<CurrentSelectCommandItems> Array[] {GrafischesObj 1, GrafischesObj 2, GrafischesObj 3 , GrafischesObj 4}; -> Serialize Grafische Ansicht - BubleEvent After
12 MoveCommand object -> Serialize Grafische Ansicht - BubleEvent Bevore
13 MoveCommand object -> Serialize Grafische Ansicht - BubleEvent After

Soo, was ist passiert.

Zuerst wurde das Grafische object selectiert die Ansicht wurde serialisiert wie sie unselectiert dann wie sie selectiert aussieht - daher BubelEvent Bevore und After Event. Dannach wird sich die Ansicht gemerkt wie sie vor dem gruppieren aussah, dann wie sie nach dem gruppieren aussieht. Zuletzt wird die Ansicht serialisiert bevor die Gruppierung das schlussendlich auch wieder nur irgend ein object hier vom Typ Array ist vor dem verschieben und im anschluss nach dem verschieben aussieht.

Schreib lieber viele Commands als wenige, das zahlt sich später aus. Lieber mal eine Komposition zuviel als zu wenige.

/PS
Sollte alles eigentlich BubbleEvent heissen.. bin zu Faul das nun zu korrigieren 😉

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

T
243 Beiträge seit 2006
vor 15 Jahren
  1. Für jedes einzelne Objekt in dieser Gruppe ein einzelnes Move-Command,
    diese dann aber in einem Makro-Command kapseln. (schließlich soll mein Rückgängig machen jetzt nicht erst eins nach dem andern zurückhüpfen, sondern wieder alle als Gruppe)
    (Und das Makro-Command sorgt natürlich dafür, dass die Unter-Commands alle ausgrührt werden, also sogesehen mehr ein Command-Group-Command)

Hi,
ich würde diese erste Variante bevorzugen, weil du dieses Command-Group-Command dann nicht nur verwenden könntest, um die gleiche Aktion für mehrere Objekte zu gruppieren, sondern evtl. auch, um verschiedene Aktionen für ein Objekt zu kapseln, die in einem Command ausgeführt werden sollen, also eben so wie ein Makro.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo Andreas.May,

Hrm, beim CommandPattern sollten immer alle Daten Redundant gespeichert werden.

das ist eine deutlich zu pauschale Aussage. Es gibt im Gegenteil keine Präferenz das so zu machen, sondern es unterliegt ganz normal der Speed-vs.-Memory-Abwägung. Gerade bei Photoshop kann ich mir nun überhaupt nicht vorstellen, dass bei jeder Aktion das ganze Bild gedoppelt wird. Dein Photoshop-Beispiel ist also eher ein Gegenbeispiel für deine insgesamt unhaltbare These.

Hallo zommi,

ich würde Variante zwei nehmen. Es ist ja nur eine Aktion. Aus Sicht des Programms genauso wie aus Sicht des Benutzers. Das diese Aktion mehrere Objekte betreffen kann, ist von vorneherein klar. Das gehört also auch ganz klar alles in ein Command-Objekt.

Hallo typhos,

deine Argumentation kann ich nicht nachvollziehen. Die Möglichkeit MacroCommands einzuführen oder nicht, ist doch unabhängig von der Frage, die zommi gestellt hat. Egal wie man sich da entscheidet, kann man immer auch MacroCommands verwenden, wenn man das aus verschiedenen Gründen braucht. Aber das ist kein Argument für Variante 1 und ich sehe auch sonst keinen Grund für Variante 1. Im Gegenteil.

herbivore

915 Beiträge seit 2006
vor 15 Jahren

Ich glaube kaum das Photoshop via Entropie die Daten immer wieder neu visualisiert.
Zumindest wäre das ziemlich komplex auf dauer, für einfache Pinseleien die der Benutzer macht würde ich das ganze noch nachvollziehen können. Aber wenn Effekte rückgängig gemacht werden sollen, kann der Effekt als solches ja nicht nochmals in umkehrvor verwendet werden.

Angenommen der Effekt Weichzeichnen wird verwendet, so kann ich diesen Effekt nicht als umkehrfunktion (Starkzeichnen) Verwenden und das Bild sieht wieder aus wie zuvor.

Das Wort "immer" hätte ich allerdings weglassen sollen - es kommt wirklich darauf an, da stimme ich dir zu.

Wie vernichtet stand Andreas unter den flammenden Augen seiner Kunden.
Ihm war's, als stünde des Schicksals dunkle Wetterwolke über seinem Haupte X(

I
1.739 Beiträge seit 2005
vor 15 Jahren

Ich verstehe den Begriff Interaction nicht.

Ansonsten gilt: Command < Activity < State

Ich würde raten: Interaktion = Zustand?
Wäre dann aber falsch, da Interaktivitäten nur Ereignisse für den Zustandswechsel sein können.

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Hi,

mit Interactions meinte ich vorallem bestimmte Dinge, die bewusst NICHT in der History abgebildet werden, weil es keine sinnvollen/vollendeten Zustandsänderungen sind.

Beispielsweise den genauen Weg um den ich ein Objekt verschiebe.
Die Tatsache, dass ich vielleicht gerade ein objekt "überfahre" und es dadurch seine Farbe ändert .
(auch diese Information sollte ja irgendwo gespeichert sein, und das wollte ich eben in "Interactions" machen)

Und speziell beim Hover gibt es ja quasi kein resultierendes Command.
Deshalb meine gesamte Überlegung.

beste Grüße
zommi

I
1.739 Beiträge seit 2005
vor 15 Jahren

Dann sind "Interactions" einfach nur Zustände.
Zustände sind durchaus aktiv, sie führen Aktivitäten aus die keine Commands sein müssen... Beispiel für den Zustand Select wäre ein Listen auf die Mauskoordinaten(Ereignis: Mousemove führt zur Aktivität CheckIfObjectUnderMousePointer, bei Treffer löst die Activität ein Ereignis aus, das in diesem Fall nicht zum Zustandswechsel führt sondern nur das Contextobject benachrichtigt(das die Nachricht nur weitergibt. Das beinahe Gleiche gilt bei Klick: Es wird geprüft ob ein Objekt unter dem Mauszeiger liegt oder nicht, es wird benachrichtigt. Das selektierte Objekt wechselt(bei Treffer zu einem Objekt sonst null), die Nachricht wird weitergeben. Bei Treffer werden mögliche Folgezustände freigeschaltet, ansonsten blockiert.
Beim Zustand Move würde ähnliches passieren, mit der Ausnahme das Mousedown ein Command auslöst, das Ding würde bei MouseDown beginnen und bei MouseUp aufhören(ich würde das von der Maus entkoppeln, gibt ja Leute die nehmen die Tastatur oder anderes).
Move wäre Subzustand von Select(Die Transition benötigt also 2 Ereignisse (bei Maus: Down & Move) zur Transition zu Move dessen Aktivitäten ein(oder mehr) Commands enthalten.
Ich hoffe das war verwirrend genug.
ikaros

zommi Themenstarter:in
1.361 Beiträge seit 2007
vor 15 Jahren

Und wie sollte ich dann demnach solche aktiven Zustände umsetzen?

Würde ich in der Komponenten-Klasse dann ein ActualState-Enum einbauen, sodass ich bei jedem OnMouse.../OnKey... einfach überprüfe, welche "Aktion" gerade läuft und die dementsprechende Funktion aufrufe?

Oder das ganze dann in ne extra Klasse packen?
Ich hab ja schon die Command-Klassen, da gehörts eher nich rein?
Also noch ne zweite (oder viele dieser Sorte) für die Zustände?

Btw: wo würdet ihr die Methode CheckIfObjectUnderMousePointer wenn dann hintun?
(//Edit: Anstatt Methode stand hier erst Klasse)
gehört die eher ins Datenobjekt (die Diagram-Klasse) oder die dazugehörige GUI?
Oder sollte ich analog zum ModelViewControler-Konzept noch ne Kontroller-Klasse dazwischenhaun, die genau für sowas zuständig ist ?

Wie gesagt, es ist ein Editor für Diagramme (so wie UML)

Da fand ich eigentlich... das manipulieren des Benutzers ist so direkt mit dem Datenobjekt gekoppelt, da brauchts keine zwischenschicht. Schließlich ist ja ne Hauptaufgabe eines Diagrams, konstruiert zu werden.

beste Grüße
zommi

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo zommi,

also ich bin nach wie vor der Meinung, dass du nur Commands brauchst und keine zusätzlichen Zustand-, Aktivitäts-, Interaktions- oder sonst was Objekte. Das Command spiegelt ja auch nur das Ergebnis der z.B. Verschiebeoperation wieder, ohne die Zwischenschritte. Insofern ist es ohnehin unabhängig von der Akt und Weise ihrer Ausführung (Tastatur, Maus, ...). Die von ikaros gewünschte Entkoppelung ist also ohnehin gegeben. Weiterer Klassen bedarf es nicht.

CheckIfObjectUnderMousePointer ist ein Methoden und kein Klassenname. Es sollte also eine Methode der Klasse sein. Wenn deine Objekte grafische Objekte (also letztlich GUI-Objekte) sind, dann könnte das einfach eine Methode der Klasse MyGraphicObject sein. Davon abgesehen gibt ja ja mit Graphics.IsVisible schon eine fertige Methode dafür. In [Tutorial] Gezeichnete Objekte mit der Maus verschieben kannst du deren Verwendung anschauen.

Oder sollte ich analog zum ModelViewControler-Konzept noch ne Kontroller-Klasse dazwischenhaun, die genau für sowas zuständig ist ?

CheckIfObjectUnderMousePointer ist ganz klar eine GUI-Methode.

Da fand ich eigentlich... das manipulieren des Benutzers ist so direkt mit dem Datenobjekt gekoppelt, da brauchts keine zwischenschicht. Schließlich ist ja ne Hauptaufgabe eines Diagrams, konstruiert zu werden.

In dem Fall sicher eine sinnvolle Designentscheidung. Natürlich kannst du innerhalb der Klassen versuchen, alles so gut wie möglich nach GUI und nicht GUI zu trennen.

herbivore

I
1.739 Beiträge seit 2005
vor 15 Jahren

MVC sehe ich erst mal noch nicht, obwohl Visualisierung duraus eine Rolle spielt.
Ein Command würde ich für Unzureichend halten.

CheckIfObjectUnderMousePointer ist ganz klar eine GUI-Methode.

Das war ein Beispiel - streiche das MousePointer und ersetze es durch ActualPosition.

Die Konstruktion selbst sollte ein Builder übernehmen.

Design ist teuer - ja. Kein Design ist aber teurer.