Sollten Eigenschaften in C # neben der Benachrichtigung über eine Änderung des Status auch Nebenwirkungen haben?
Ich habe Eigenschaften gesehen, die auf verschiedene Arten verwendet wurden. Von Eigenschaften, die den Wert beim ersten Zugriff auf sie laden, zu Eigenschaften, die massive Nebenwirkungen haben, z. B. das Verursachen einer Weiterleitung auf eine andere Seite.
Antworten:
Ich nehme an, Sie sprechen von Nur - Lese- Eigenschaften oder zumindest Eigenschaft Getter , da eine Eigenschaft Setter ist, in fast allen Fällen gehen Nebenwirkungen haben. Ansonsten ist es nicht sehr nützlich.
Im Allgemeinen folgt ein gutes Design dem Prinzip der geringsten Überraschung . Tun Sie keine Dinge, von denen Anrufer nicht erwarten, dass Sie sie tun, insbesondere wenn diese Dinge die zukünftigen Ergebnisse verändern könnten .
Im Allgemeinen bedeutet dies, dass Property Getter keine Nebenwirkungen haben sollten.
Seien wir jedoch vorsichtig mit dem, was wir unter "Nebeneffekt" verstehen .
Ein Nebeneffekt ist technisch jede Zustandsänderung. Das könnte ein öffentlich zugänglicher Staat sein, oder ... es könnte ein völlig privater Staat sein.
Lazy / Deferred Loader sind ein Beispiel für einen fast ausschließlich privaten Staat. Solange es nicht die Verantwortung des Anrufers ist, diese Ressource freizugeben, reduzieren Sie tatsächlich die Überraschung und die Komplexität im Allgemeinen, indem Sie eine verzögerte Initialisierung verwenden. Ein Aufrufer erwartet normalerweise nicht, explizit die Initialisierung einer internen Struktur signalisieren zu müssen . Eine verzögerte Initialisierung verstößt also nicht gegen das obige Prinzip.
Ein weiteres Beispiel ist eine synchronisierte Eigenschaft. Damit eine Methode threadsicher ist, muss sie häufig durch einen kritischen Abschnitt oder Mutex geschützt werden. Die Eingabe eines kritischen Abschnitts oder der Erwerb eines Mutex ist ein Nebeneffekt. Sie ändern den Status, normalerweise den globalen Status. Dieser Nebeneffekt ist jedoch erforderlich , um eine viel schlimmere Art von Überraschung zu verhindern - die Überraschung, dass Daten von einem anderen Thread geändert (oder teilweise geändert) werden.
Daher würde ich die Einschränkung ein wenig auf Folgendes lockern: Eigenschaftslesevorgänge sollten keine sichtbaren Nebenwirkungen oder Nebenwirkungen haben, die ihre Semantik ändern .
Wenn es keine Möglichkeit gibt, dass ein Anrufer jemals von einer Nebenwirkung betroffen ist oder diese überhaupt wahrnimmt , ist diese Nebenwirkung nicht schädlich. Wenn es für Sie unmöglich ist, einen Test zu schreiben, um das Vorhandensein einer bestimmten Nebenwirkung zu überprüfen, ist dieser so lokalisiert, dass er als privates Implementierungsdetail und somit für die Außenwelt nicht als legitim anzusehen ist.
Aber sei vorsichtig; als Faustregel gilt : Sie sollten versuchen , Nebenwirkungen zu vermeiden, weil oft das, was Sie vielleicht denken, unerwartet auslaufen und öffentlich zu einer privaten Detail - Implementierung zu sein.
quelle
Ich beantworte Ihre Frage mit einer Frage: Was passiert, wenn Sie die Width-Eigenschaft eines Formulars ändern?
Direkt von meinem Kopf aus wird dies:
(Haftungsausschluss: Ich bin ein Delphi-Entwickler und kein .NET-Entwickler. Für C # ist dies möglicherweise nicht 100% genau, aber ich wette, es ist ziemlich nah, besonders wenn man bedenkt, wie viel des ursprünglichen .NET-Frameworks auf Delphi basierte.)
Alle diese "Nebenwirkungen" treten auf, wenn Sie die Width-Eigenschaft in einem Formular ändern. Scheint einer von ihnen unangemessen oder irgendwie falsch?
quelle
Schauen Sie sich die Microsoft Design Rules an , insbesondere eine davon:
CA1024: Verwenden Sie gegebenenfalls Eigenschaften
quelle
Ich glaube, Eigenschaften sollten keine Nebenwirkungen haben. Es gibt jedoch eine Ausnahme von dieser Regel: verzögertes Laden. Wenn Sie in einer Eigenschaft etwas faul laden möchten, ist das in Ordnung, da der Client nicht sagen kann, dass das faulen Laden stattfindet, und es im Allgemeinen egal ist.
EDIT : Oh, noch eine Sache - Auslösen eines Ereignisses mit der Aufschrift "PropertyXYZ Changed!" (zB
INotifyPropertyChanged
) - ist gut für Setter.quelle
Zusätzlich zu dem zuvor erwähnten verzögerten Laden gibt es auch den Fall von Protokollierungsfunktionen. Dies wäre selten, aber nicht ausgeschlossen.
quelle
Es gibt kaum Absolutes in der Programmierung. Um Ihre Frage zu beantworten, müssen wir einige wünschenswerte Eigenschaften von Objekten untersuchen und prüfen, ob dies für unseren Fall zutreffend ist
Wenn wir einige dieser Fragen mit Ja beantworten, ist es wahrscheinlich eine gute Idee, über Eigenschaften und deren Nebenwirkungen sehr sorgfältig nachzudenken. Ich gehe davon aus, dass Sie mit Nebenwirkungen sekundäre Nebenwirkungen meinen, da die Aktualisierung des Werts eine Nebenwirkung für sich ist.
Je mehr Nebenwirkungen im Allgemeinen auftreten, desto schwieriger wird es sein, eine Klasse zu testen. Je mehr sekundäre Nebeneffekte auftreten, desto schwieriger wird es, die Parallelität zu bewältigen, aber das ist ein schwieriges Problem, das wahrscheinlich ohnehin einige grundlegende Konstruktionsüberlegungen erfordert.
Das große Problem ist wahrscheinlich für Leute, die Ihre Klasse als "Black Box" behandeln. Es wäre nicht ohne weiteres möglich, dass sich ein Zustand geändert hat, nur weil sie eine Eigenschaft gelesen haben, oder dass sich eine andere Eigenschaft ändert, weil sich eine andere ändert (was dazu führen könnte) zu kaskadierenden Updates).
Nein, im Allgemeinen möchten wir, dass Eigenschaften so einfach wie möglich und verständlich sind. Dies ist in der Entwurfsentscheidung impliziert, andernfalls handelt es sich um eine Methode. Ein guter Programmierer kann immer gegen die Regeln verstoßen, aber sei dir sicher, dass du einen wirklich guten Grund hast :)
quelle