Laden...

Trennung von Modell und GUI / MVC und 3-Schichten

Erstellt von equip vor 15 Jahren Letzter Beitrag vor 15 Jahren 3.992 Views
E
equip Themenstarter:in
4 Beiträge seit 2009
vor 15 Jahren
Trennung von Modell und GUI / MVC und 3-Schichten

Hallo Forum 😃

Ich beschäftige mich seit ca. einem halben Jahr mit C# und habe in den letzten Wochen viel Zeit mit dem Openbook von Galileopress verbracht. Das läuft soweit auch ganz gut, habe schon das ein oder andere Programm umgesetzt. Hätte nicht gedacht, dass man da so schnell Resultate sehen kann.

Ich lese hier im Forum immer wieder, dass man Logik von der GUI trennen sollte und versuche das auch strikt umzusetzen. Jedoch weiß ich nicht genau, auf welcher "Ebene" ihr das überhaupt meint:

Heißt das lediglich, dass ich in Logikklassen keine Variablen der GUI (wie z.B. label1.text) direkt ansprechen sollte, sondern z.B. lieber als Parameter an die Logikklasse übergeben sollte,
ODER
heißt das sogar, dass in der Form1.cs überhaupt keine Logikklasse erwähnt werden dürfen (nichtmal instanziert)?

Beispiel wie ich es bisher handhabe:
Ich will per Buttonklick eine XML-Datei von einem Server laden und anschließend Inhalte davon in der GUI anzeigen. Dafür habe ich eine Klasse mit den Methoden LoadXML() und GetString() geschrieben.
In der form1.cs liegt das Click-event des Buttons. In dessen Codeblock erstelle ich eine Instanz meiner Klasse, rufe die Methode LoadXML() auf und weise dann noch einer Textbox GetString() zu, damit sie den Inhalt der XML-Datei anzeigen kann. Das findet alles in der form1.cs im Click-event des Buttons statt!
Gut oder nicht gut?
Meine xml-Verarbeitungsklasse ist natürlich in einer eigenen Datei untergebracht.

Das Grundprinzip von MVC und das 3-Schichten Modell meine ich verstanden zu haben, was die beiden Modelle ausmacht.
Aber: stehen die beiden Modelle in Konkurrenz zueinander, oder können die in einem Programm auch eine Koexistenz führen?
Denn eigentlich sind die ja für die Trennung von Daten, Business und Präsentation zuständig, müssten also in Konkurrenz stehen.
Wie kann ich rausfinden, was für ein Projekt geeigneter ist? Was ist allgemein populärer?

Vielleicht will der ein oder andere ja was dazu schreiben, da wäre ich dankbar 😃

Grüße

6.862 Beiträge seit 2003
vor 15 Jahren

Hallo,

erstmal willkommen im Forum.

Zur Trennung von Modell und GUI: Joa, hört sich ordentlich an. So hast du ja die Möglichkeit deine Klasse die des XML lädt und dir nen String erzeugt auch ganz woanders zu verwenden. Das ist genau die Trennung die man anstrebt.

Zu MVC vs 3-Schichten:
Im Prinzip sind beide Denkweisen für eine gewisse Unterteilung des Programms in sinnvolle Bestandteile zuständig, so wie du es ja auch erkannt hast. Aber wenn du ne mehrschichtige Applikation hast, ist es ohne weiteres möglich ne Daten und ne Businessschicht zu haben und die folgende Präsentationsschicht ist nach dem MVC prinzip aufgebaut. Das Model von MVC kommt in dem Fall aus der Businessschicht.

Wie kann ich rausfinden, was für ein Projekt geeigneter ist? Was ist allgemein populärer? Bitte versuche nicht ein Programm zwangsweise nach einem bestimmten Pattern zu entwicklen, nur wegen dem Pattern wegen. Die Entwurfsmuster sind kein theoretisches Produkt das irgendwer sich mal erdacht hat, sondern sind in zig Jahren aus der Erfahrung unzähliger Entwickler entstanden. Genauso sollte sich in nem Programm von alleine die Pattern einstellen wenn der Entwickler die nötige Erfahrung hat. Man kann natürlich mit dem Wissen was für Entwurfsmuster es so gibt von vornherein fehler vermeiden. Aber man sollte jetzt nicht hingehen und sagen mein Programm muss jetzt genau so und so aufgebaut werden, und nicht anders.

Baka wa shinanakya naoranai.

Mein XING Profil.

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo equiq,

Willkommen auf www.mycsharp.de .
Die verschiedenen Schichten (z.B. GUI und Funktionsschicht) können nicht völlig getrennt werden. Um es sauber zu halten darf die Funktionsschicht niemals auf die GUI zugreifen. Am einfachsten ist es wenn man beide Schichten in getrennte Assemblies packt und nur das GUI-Assembly das Funktions-Assembly kennt aber nicht umgekehrt!

Gruß
Juy Juka

E
equip Themenstarter:in
4 Beiträge seit 2009
vor 15 Jahren

Hallo ihr,

sorry für die späte Rückmeldung, war leider verhindert. Danke auch an herbivore für das "Aufräumen" 😉

Okay, das mit den 3 Schichten und MVC lasse ich mal ne Weile ruhen. Habe nun auch selbst eingesehen, dass das ganze für ein paar kleine Tools auch oversized wäre.

Um es sauber zu halten darf die Funktionsschicht niemals auf die GUI zugreifen. Am einfachsten ist es wenn man beide Schichten in getrennte Assemblies packt und nur das GUI-Assembly das Funktions-Assembly kennt aber nicht umgekehrt!

Okay. Also um es noch mal zu konkretisieren: ich erstelle...

Gui-Assembly: formXY.cs
Funktions-Assembly: logik.cs

In der logik.cs dürfen keinerlei Objekte aus formXY verwendet werden.
formXY übergibt die zu verarbeitenden Daten per Parameter an die Klassen aus logik.cs und darf somit deren Klassen verwenden. Die Kommunikation 2er Logikklassen darf dann aber schon innerhalb der logik.cs stattfinden.

Ist es das, was du mit "...kennt aber nicht umgekehrt!" meinst, oder habe ich das falsch interpretiert? Vielleicht gibt es ja auch eine Möglichkeit das Ganze so zu strukturieren, dass die Logik die GUI schon rein technisch nicht kennen kann, selbst wenn man es wollte (evt. Namespaces?).
Bin mir nicht sicher, wie Stark man die Unkenntnis der Assemblies machen sollte. Also ob eine logische Abgrenzung ausreicht, oder ob man den technischen Riegel vorschieben sollte.

Grüße

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo equip,

In der logik.cs dürfen keinerlei Objekte aus formXY verwendet werden.

nicht mal Klassen und Objekte aus Window.Forms oder eine anderen GUI-Bibliothek, also auch kein MessageBox.Show, also schlicht überhaupt nichts, was mit GUI zu tun hat.

formXY übergibt die zu verarbeitenden Daten per Parameter an die Klassen aus logik.cs und darf somit deren Klassen verwenden. Die Kommunikation 2er Logikklassen darf dann aber schon innerhalb der logik.cs stattfinden.

Beides ja.

Vielleicht gibt es ja auch eine Möglichkeit das Ganze so zu strukturieren, dass die Logik die GUI schon rein technisch nicht kennen kann, selbst wenn man es wollte (evt. Namespaces?).

Klar kann man das. Einfach ein separates Projekt für die Logik (Klassenbibliothek) anlegen.

herbivore

2.187 Beiträge seit 2005
vor 15 Jahren

Hallo equip,

Ist es das, was du mit "...kennt aber nicht umgekehrt!" meinst, oder habe ich das falsch interpretiert? Vielleicht gibt es ja auch eine Möglichkeit das Ganze so zu strukturieren, dass die Logik die GUI schon rein technisch nicht kennen kann, selbst wenn man es wollte (evt. Namespaces?).
Bin mir nicht sicher, wie Stark man die Unkenntnis der Assemblies machen sollte. Also ob eine logische Abgrenzung ausreicht, oder ob man den technischen Riegel vorschieben sollte.

Genau das meinte ich und nicht nur .cs-Dateien sondern richtig verschiedene Assemblies (so wie herbivore das auch schrieb). Und wie herbivor noch hervor gehoben hat: die Klassenbibliothek hat keine Verweise auf System.Windows.Form oder System.Web. oder ein Windows Presentation Foundation Assembly (im normal fall nicht mal System.Drawing).

@herbivore: Das muss ich mir merken, dass man das mit keinem Verweis auf System. Windows.Forms extra noch hervor hebt.

Gruß
Juy Juka

T
60 Beiträge seit 2009
vor 15 Jahren

Hey Leute,

als ich mir diesen Thread durchgelesen habe bin ich ein bisschen ins grüblen gekommen. In einer meiner Klassen, welche Files abarbeitet, greife ich mit Invoke direkt aus einer Methode auf die GUI zu, die Controls auf die ich zugreifen muss sind in einer Singleton Klasse zwischengelagert, damit ich von dort aus zugreifen kann.

Eigentlich verstößt dann mein Ansatz hier gegen die "Sauberkeit" oder und ich sollte statt Invoke in der Methode, nur ein Event feuern welches dann im Form direkt die Controls aktualisiert?

3.003 Beiträge seit 2006
vor 15 Jahren

Eigentlich verstößt dann mein Ansatz hier gegen die "Sauberkeit" oder und ich sollte statt Invoke in der Methode, nur ein Event feuern welches dann im Form direkt die Controls aktualisiert?

Ganz genau. Invoke und Controls, die in einem Singleton gehalten werden, klingt sowieso schon recht abenteuerlich...

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

T
60 Beiträge seit 2009
vor 15 Jahren

Ganz genau. Invoke und Controls, die in einem Singleton gehalten werden, klingt sowieso schon recht abenteuerlich...

Das Singleton dient ja egtl. dazu, wenn ich auf ein Control von FormA auf ein Control von FormB zugreifen will, dass müsste ja dann wiederum konform sein schätze ich. Glaube bei dem Invoke hast du mich falsch verstanden, die Singleton Klasse hält nur die Controls, da passiert sonst garnix, Invoke findet schon in der Klasse direkt statt, halt hier z.B. Progressbar im Form aktualisieren.

Durch folgendes Beispiel bin ich auf diesen Ansatz gekommen: Klick

Hier werden ja auch aus der Klasse heraus Controls aktualisiert? Sorry wenn die Frage etwas nervig erscheint, aber mir ist es sehr wichtig, dass ich mir einen sauberen Programmierstil aneigne, da ich noch in den Anfängen stecke.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo TheMichi,

Hier werden ja auch aus der Klasse heraus Controls aktualisiert?

Das ist falsch. Die korrekte Alternative hast du ja schon selbst genannt:

Eigentlich verstößt dann mein Ansatz hier gegen die "Sauberkeit" oder und ich sollte statt Invoke in der Methode, nur ein Event feuern welches dann im Form direkt die Controls aktualisiert?

Das Singleton dient ja egtl. dazu, wenn ich auf ein Control von FormA auf ein Control von FormB zugreifen will, dass müsste ja dann wiederum konform sein schätze ich

Klinkt merkwürdig. Das Singleton-Pattern wird fast immer falsch verwendet. Es gibt kaum Fällen, in denen man es braucht. Wenn zwei Forms mit einander kommunizieren will, braucht man es sicher nicht.

herbivore

T
60 Beiträge seit 2009
vor 15 Jahren

Danke für die Tipps 😃 dann werd ich mich wohl gleich mal ans "umbauen" machen. Der Weg am Anfang ist echt steinig 😉, alle paar Tage darf ich meine Anwendung umbauen, weil ich merke, dass es viel einfachere bzw. "richtigere" 😉 Lösungen gibt.

Eine ganz kleine Frage hätte ich noch, den Vorschlag zwei Forms über eine dritte Klasse kommunizieren zu lassen habe ich aus diesem Thread: Kommunikation zwischen 2 Forms

Hauptzweck dieses Singletons war es, von einem UserControl aus auf die Controls des StatusStrips zuzugreifen, dachte bis jetzt das dies eine saubere Möglichkeit wäre? Nunja inzwischen hab ich ja gelernt das man das auch über Events lösen kann 😃

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo TheMichi,

Eine ganz kleine Frage hätte ich noch

hier im Forum kann ja jeder, der möchte mithelfen und Antworten geben, auch Anfänger. Daher finden sich im Forum gerade zu dem Thema "Kommunikation zwischen 2 Forms" auch eine Reihe von ungünstigen Lösungsvorschlägen. Inbesondere Singleton werden von vielen Anfängern als einfache, aber meistens eben unpassende Lösung vorgeschlagen. Daher kann man leider nicht unbesehen jedem Vorschlag im Forum vertrauen. Die Kennzeichnung eines Users als Poweruser oder Team-Mitglied sind aber ein gutes Indiz für gute Vorschläge. Völlige Unfehlbarkeit gibt es aber auch unter dieser User-Gruppe natürlich nicht.

herbivore

1.433 Beiträge seit 2006
vor 15 Jahren

Eigentlich verstößt dann mein Ansatz hier gegen die "Sauberkeit" oder und ich sollte statt Invoke in der Methode, nur ein Event feuern welches dann im Form direkt die Controls aktualisiert?

Ein Event abfeuern das vom verarbeitenden GUI Element abonniert wird. INotifyPropertyChanged denke, wäre hier sicherlich nicht verkehrt.

Grüsse
Daniel
Space Profile
Wer nicht fragt, der nicht gewinnt