Stil-Frage - Propertys beobachten - OnPropertyChangedEvent

  • Allgemein

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von Kagurame.

    Stil-Frage - Propertys beobachten - OnPropertyChangedEvent

    Hallo, heute mal eine Stil-Frage, bzw. ein Best Practise:

    Ich habe eine Client-Server-Anwendung.

    Derzeit arbeite ich am Client, bzw. plane diesen genauer (Code, was ist notwendig, wie wird die Architektur des Clients aussehen usw. usw.).
    Logik und GUI werde ich strikt trennen.

    Ich habe die Anwendung im SysTray laufen, nur wenn nötig, ist eine Form sichtbar, mit welcher gewisse Einstellungen getätigt werden können.

    Die Inhalt der Form ist interaktiv, der Nutzer klickt irgendetwas, daraufhin wird das Business "angesprochen" und anhand der Rückgabe-Werte passen sich entsprechend die Felder an.
    Der SysTray dient zum einen der Steuerung (beschränkt => Konfigurieren - Form wird gerufen; Anmelden / Abmelden - Logik wird ausgeführt etc. etc.).
    Der SysTray zeigt aber auch (bspw. Anhand des Icons) gewisse Stati der Anwendung an (Server erreichbar, Service eingeschränkt / voll Nutzbar, bin ich angemeldet (man kann auch Server-Seitig abgemeldet werden) und so weiter).

    Diese Punkte entscheidet die Logik mittels CallBack-Funktionen vom Service aus oder eine Intervall-mäßige Prüfung bestimmter Punkte.

    Ich finde es nicht so gut, wenn ich alle x Sekunden / Millisekunden den SysTray (also die Klasse die diesen darstellt) fragen lasse, wie es bei den entsprechenden Properties im Business aussieht. Ich möchte ihn weitestgehend stateless halten, lediglich die im Business gehaltenen States darstellen (Texte, verfügbare Funktionen).

    Dazu habe ich mir gedacht, könnte ich doch einfach eine entsprechende Klasse "beobachten", welche bspw. meine Properties hält (die relevanten) oder die Business-Klasse selbst.

    So erspare ich mir hier entsprechende Timer, die ständig laufen müssen, und fange einfach ein OnPropertyChanged-Event der jeweiligen Business-Klasse ab.
    So weiß der SysTray, wann er einen Text ändern muss, eine Funktion ein / ausblenden muss, das Icon ändern muss... die Dinge eben.

    Was ich nicht will, ist, dass die GUI die Logik anspricht (sage mir dies, berechne das), und umgekehrt die Logik dann die GUI anspricht (Zeige die Funktion, zeige jenen Icon), denn dann hätte ich vom einen auf den anderen einen Verweis und umgekehrt. Die Logik soll die GUI nicht kennen, im Nachhinein habe ich dadurch Wartungsarbeit gespart.

    Nun die Frage, ist der Weg mit OnPropertyChanged-Events ein guter Weg oder habt ihr ganz andere Ansätze? Wie würdet ihr das regeln?

    Naja, würde mich über jede Art von Rückmeldung freuen... lg. Kagu

    (Ich hänge gleich noch eine Skizze an!)
    Ich denke, Dein Ansatz ist richtig.
    Ein Bauvorschlag auf CodeProject:
    Make OnPropertyChanged events safe for refactoring

    und auf StackOverFlow
    Better way to trigger OnPropertyChanged

    und noch eins auf Microsoft:
    INotifyPropertyChanged.PropertyChanged-Ereignis (System.ComponentModel)

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „us4711“ ()

    @picoflop: Klingt interessant,
    aber habe ich es richtig verstanden, wenn ich (vereinfacht ausgedrückt) einen Observer (Beobachter) habe (SysTray) und einen Observierten (Business)? Ich meine nun so, dass diese auch so definiert werden müssen (Durch entsprechende Interfaces)?

    Ich habe mir die Interfaces, welche an angesprochen werden, mal angesehen. Getestet nicht, aber wenn ich nichts falsch verstanden habe, muss ich dem observierten sagen, wer ihn Observiert (IObserverble( Of T)), oder nicht? Damit hätte ich ja, dass die Logik weiß, wer "unter" ihm liegt. Dies will ich ja vermeiden. Mit Basisklassen wäre es vielleicht noch denkbar, aber ansonsten müsste ich, wenn ich die GUI umbaue, auch in der Logik entsprechende Anpassungen unternehmen.

    Mit den von mir im Start-Post angesprochenen Events hätte ich ein ähnliches Szenario, mit dem Unterschied, dass nichts nach unten geht, sondern nur nach oben, ich würde auch "Observieren", nur wüsste die Logik nicht, von wem. Sie sagt nur: "Ich darf beobachtet werden".

    Oder was verstehe ich an dem ganzen falsch?
    So ganz verstehe ich das Problem nicht.

    Bei jedem "automatischen" Beobachtungsmodel (Events, Observer etc), muss der "Beobachtete" natürlich IMMER eines Bezug zum "Beobachter" haben. Wir sprechen ja immer vom "Bescheid sagen". Da ist es aber auch im wirklichen Leben so, dass man wissen muss, WEM man Bescheid zu sagen hat. Bei Events ist es schließlich genauso. Das "Abonieren" eines Events erfordert die Übergabe eines "passenden" Delegaten, der wiederum auf eine Methode in Irgendwo verweist. Der Event-Auslöser weiß also, DASS und im Prinzip auch WER ihn beobachtet. Im Normalfall wird ein Event nämlich auch nur dann "ausgelöst", wenn es jemand abonniert hat.

    Nur wenn man "pollt" (poll't, pollet,...?), dann weiß der "Beobachtete" nicht, wer oder was Informationen abgreift.
    @kagurume
    Verstehe ich Die Aufgabenstellung so richtig, dass die PropertyChanged auslösende Klasse (Die "Logik") in einem eigenen Prozess als eigenes Programm läuft, das als Selbstständige EXE gestartet wird?
    @us4711: Nein. Es geht darum, dass die Logik nichts mit der GUI zu tun hat, aber die GUI, genauer gesagt die Anzeige davon abhängig ist, welches State die Logik hat.

    Idealerweise soll es dann so aussehen, dass du in einer Relations-Skizze einen Pfeil von GUI zu Logik hast, aber umgekehrt nicht. So kannst du die GUI einfach austauschen, ohne die Logik anfassen zu müssen.
    Bilder
    • skizze.png

      21,04 kB, 1.132×562, 89 mal angesehen
    Entweder wenn ein Client irgendeinen Request schickt (Alarm geben z.B.) oder vom Service direkt (Datenbank grade nicht erreichbar z.B.). Wenn ein Client einen request schickt, könnte ich es noch Problemlos handlen, aber die anderen Clients sollen ja auch was davon haben...
    Also erstellst Du eine Anwendung, die auf Ereignisse aus dem Netzwerk reagieren soll (Server-Nachrichten, wie z.B. DB nicht vorhanden gehören dann mit dazu.). Läuft Deien SW auf einem Client oder auf dem Netzwerkserver?
    Die Frage der Kommunikation ist hier eigentlich vollkommen irrelevant. Es geht mir allein um die Architektur des Clients. Wie der kommuniziert, ist mir klar. Das erfrage ich hier auch nicht. Es geht mir nur darum, ob dieses Pattern, welches ich in meinem Startpost nenne, anwendbar ist oder ob man dies generell anders macht.

    Kagurame schrieb:

    So erspare ich mir hier entsprechende Timer, die ständig laufen müssen, und fange einfach ein OnPropertyChanged-Event der jeweiligen Business-Klasse ab.
    Kurz gesagt: Du verwendest Databinding :thumbsup: :thumbsup:
    Das ist der Königsweg, und in Wpf zB. wird angestrebt, dass zw. Oberfläche und Daten ühaupt keine annere Verbindung mehr besteht, als Databinding.
    Dort spricht man vom MVVM-Pattern (Model - View - ViewModel), und eine Klasse, die databindable Properties (INotifyPropertyChanged implementieren) bereitstellt, zur Bindung an die Oberfläche, so eine Klasse ist ein typisches ViewModel.
    Jetzt habich aber picoflops Link nicht nachgesehen, und daher keine Ahnung, ob dort im Grunde dasselbe Konzept verfolgt ist oder eine Alternative.

    Databinding ist aber natürlich auf die eigene Anwendung beschränkt. Also du kannst nicht im Client an eine Property auffm Server binden, sondern da muß eine annere Kommunikation her, die Daten iwie vom Server in den Client kriegt (wo dann dran gebunden wern kann).
    habich schon verstanden, dasses um Winforms geht.
    Aber der MVVM-Pattern ist nicht auf Wpf beschränkt.
    Ich hab Wpf nur angeführt, weil du frugst, ob das ein tragfähiges und modernes Konzept sei, und meine Antwort lautet zusammengefasst: "Ja natürlich - in Wpf zB. macht mans sogar ausschließlich so".
    (Letzteres ist natürlich übertrieben - auch in Wpf finden sich jede Menge Gurken-Coder ;))

    Dass man das hier DataBinding nennt, wusste ich nicht
    Das INotifyPropertyChanged - Interface ist die eigentliche Magie hinterm Databinding.
    OK :)
    Wusste eben nicht, dass es gerade dieses Interface ist, welches WPF zu dem macht, was es ist, bzw. das DataBinding (Hab mich eben vorher noch nicht mit auseinander gesetzt und ohne einen dieser Begriffe einfach nur gegooglet, ob´s so ein Event gibt und wie ich mitbekomme, wenn irgendwo ein Event geraist wird, um mir meinen Handler zu adden (WithEvents).

    Naja, dass hilft mir schon mal weiter, und stellt in Aussicht, dass ich meinen Kopf behalte wenn ich das ganze meinem Ausbilder vortrage ^^

    Danke nochmal... werde es denke ich dann auch so machen :)

    (Mir wurde WPF zwar schon gezeigt, Code und Ergebnis-Mäßig, aber dass erst letzte Woche... hab die Entscheidung WPF / Forms dann nur nach hinten geschoben und für ein für uns vernünftiges Update-System gesorgt ^.^)