Laden...

Private Properties vs. Private Fields

Erstellt von DaMoe80 vor 12 Jahren Letzter Beitrag vor 12 Jahren 2.516 Views
D
DaMoe80 Themenstarter:in
500 Beiträge seit 2007
vor 12 Jahren
Private Properties vs. Private Fields

Hallo *!

Wir haben in unserem Unternehmen ein Regelwerk etabliert, welches einem Entwickler aufzeigt wie dieser einheitlich Code entwickeln soll. Nun wird ueber eine Regel diskutiert, die ich momentan noch nicht vertreten kann:

  1. Benutze keine privaten Felder, benutze private Properties stattdessen
  2. Ausnahmefaelle sind Lazy Loading, NotifyPropertyChanged und Marshalling
  3. Wenn Du private Felder verwendest, dann duerfen diese nur ueber die entsprechenden Properties angesprochen werden.

Mich interessiert Eure Meinung dazu. Findet Ihr so eine Regelung sinnvoll?

Meiner Meinung nach schafft man durch die obige Regel explizite, private Felder mehr oder minder ab. Ohne Euch zu stark zu beeinflussen, ist ein Argument der Befuerworter, dass einige Entwickler mal die privaten Felder und dann mal wieder die Properties ansprechen, wodurch natuerlich Fehler entstehen koennen, weil bspw. durch den Zugriff auf ein privates Feld eventuell gewisse Logik eines Properties umgangen wird. Man moechte nun erreichen, dass einheitlich ueberall da, wo es moeglich ist, Properties einsetzt und diese nur anspricht.

Gruss,
DaMoe

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo DaMoe80,

Properties sind für den äußeren Zustand und daher in der Regel öffentlich. Felder sind für den inneren Zustand und daher in der Regel privat (oder protected). Private Properties machen m.E. nur in Ausnahmefällen Sinn, z.B. wenn der Setter mehr tut, als das Feld zu setzen.

Zu den Begriffen äußerer und innerer Zustand siehe Untersch. Behandlung der Objektdaten bzgl. Modifizierer bei Serialisierung in den versch. Formaten.

Die Argumentation der Befürworter kann ich bis zu einem gewissen Maße nachvollziehen. Überzeugen tut sie mich nicht. Der Implementierer der Klasse sollte seine Klasse schon kennen und daher wissen, ob ein ein Feld direkt ansprechen kann oder ob er ausnahmsweise eine (private) Property verwenden muss. Wenn die Klasse zu groß ist, um das zu überblicken, ist schon beim Design was schiefgelaufen und die Klasse sollte aufgeteilt werden.

herbivore

PS: Es macht an mehreren Stellen einen Unterschied, ob Felder oder Properties verwendet werden: Beim Serialisieren, bei Reflection, beim PropertyGrid usw. Deshalb ist es schon besser, dass man den inneren Zustand eines Objekts dort speichert, wo er konzeptionell hingehört: in private Felder.

F
10.010 Beiträge seit 2004
vor 12 Jahren

Diese Regeln machen auch Sinn, allerdings sollte man gleich verankern das in begründeten Fällen diese Regel gebrochen werden kann, damit nicht irgendwelche komischen Umgehungen Programmiert werden müssen.

Es sollte allerdings nur von einer eigens dafür geschriebenen Routine geschehen die dann auch dokumentiert werden muss.

Eine Resetfunktion wäre so eine ggf notwendige Routine.

5.742 Beiträge seit 2007
vor 12 Jahren

Mich interessiert Eure Meinung dazu. Findet Ihr so eine Regelung sinnvoll?

Nein - nicht in dieser generellen Form.

Ich sehe z.B. nicht ein, warum man statt:


private Random _random;

Plötzlich schreiben sollte:


private Random Random
{
  get;
  set;
}

IMHO bläht das (bei private-Membern) den Code nur unnötig auf.

Sinn machen kann diese Regelung IMHO zur Steigerung der Konsistenz, wenn bspw. bereits mehrere private Properties existieren, die Werte berechnen; wie in:


private Size ContentSize
{
  get { return this.ContentBounds.Size; } //+ evtl. Setter
}
private Point ContentLocation
{
  get { return this.ContentBounds.Location; } //+ evtl. Setter
}
//Hier würde ich jetzt definitiv schreiben:
private Rectangle ContentBounds
{
  get;
  set;
}

Somit sollte man in diesem Punkt IMHO auch etwas auf das "Gefühl" des jeweiligen Entwicklers setzen.
Meines Erachtens sind weder die durchdachtesten Codingguidelines ein Garant für guten Code, noch kann man durch sie Code erzwingen, der wirklich wie "aus einer Feder" wirkt.

Letztlich sollte eine derartige Regel auch immer dem Team dienen - und nicht umgekehrt das Team der Regel.
Es ist m.E. selten gut, wenn ich beim Schreiben von Code denken muss "Eigentlich könnte man das jetzt auch deutlich eleganter lösen, aber die Regel verbietet mir das".

S
269 Beiträge seit 2010
vor 12 Jahren

Aus meiner Sicht macht die Verwendung von privaten Properties nur wirklich Sinn, wenn diese zwingend einer besonderen Logik unterliegen müssen (Also wenn ein Wert in einem bestimmten Wertebereich liegen muss).

Dies hätte sogar den (möglichen) Vorteil, dass man zu einem späteren Zeitpunkt eine mögliche Validierung der Daten weglassen/schmälern könnte.

Aber das hat herbivore eigentlich auch schon gesagt:

Private Properties machen m.E. nur in Ausnahmefällen Sinn, z.B. wenn der Setter mehr tut, als das Feld zu setzen.

D
DaMoe80 Themenstarter:in
500 Beiträge seit 2007
vor 12 Jahren

Ich danke Euch fuer Eure Meinungen. Ich sehe das aehnlich wie Ihr. Mein Vorgehen, welches Eure Ansichten widerspiegelt, sah und sieht bis jetzt folgendermassen aus: Verwende da, wo lediglich Werte fuer den inneren Zustand benoetigt werden, private Felder. Sobald ich mehr "Funktionalitaet" benoetige, wie z.B. Lazy Loader, Kalkulationen etc. verwende ich private Properties.
Den Hinweis von winSharp93 finde ich noch interessant, der Einheitlichkeit halber an gewissen Stellen, dann doch private Properties zu verwenden.

Ich nehme aus dieser Thread mit, dass es mehr Sinn macht ein Best Practice (Empfehlung) herauszugeben, es aber nicht in einer festen Regel zu verzurren.

Danke und Gruss,
DaMoe

L
667 Beiträge seit 2004
vor 12 Jahren

Sobald ich mehr "Funktionalitaet" benoetige, wie z.B. Lazy Loader, Kalkulationen etc. verwende ich private Properties.

Ich würde Private Properties nicht mal hier verwenden. Was passiert wenn Du mehr als eine "Funktionalität" auf einem Feld durchführen musst ? Dann läufst Du Gefahr, eine Funktionalität in einem Property "versteckt" zu haben und eine andere in einer privaten Methode.

Ich sehe keinen Sinn in der Verwendung von privaten Properties. Interne Funktionalität zur Manipulation von Feldern sollte in entsprechenden privaten Methoden mit sprechenden Namen realisiert werden, damit man beim Arbeiten an der Klasse schon am Methodennamen erkennen kann, welche Funktionalität sie realisiert. Ein privates Property MeinObjekt sagt dagegen nichts darüber aus, welche Funktionalität darin versteckt ist.

EDIT: Durch die Verwendung von privaten Properties statt privaten Feldern schützt man die Entwickler keinesfalls vor sich selbst, im Gegenteil, man verleitet sie dazu Properties auf die genannte Art und Weise als verkappte Methoden zu missbrauchen.

"It is not wise to be wise" - Sun Tzu

D
DaMoe80 Themenstarter:in
500 Beiträge seit 2007
vor 12 Jahren

Hi Lynix!

Da hast Du mehr reininterpretiert, als was ich gemeint habe. Um das zu praezisieren: Mit Funktionalitaet meine ich grundlegende Dinge, wie bspw. eine einfache Multiplikation etc, die auch voellig legitim ist, diese in einem Property unterzubringen. Siehe hier z.B.: Properties (C# Programming Guide)

Gruss,
DaMoe

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo DaMoe80,

die Aussage von Lynix hat schon etwas bedenkenswertes. Wieviel Funktionalität man in einen Setter packen sollte, ist das eine, der Zweck von Properties das andere. Auf der Seite, die du verlinkst, finde ich nur eine einzige Aussage über den Zweck von Properties, nämlich:

Properties enable a class to expose a public way ...
(Über die Eigenschaften kann eine Klasse das Abrufen und Festlegen von Werten öffentlich verfügbar machen ...)

Das stützt, was ich oben schon geschrieben habe. Und führt zu der Frage, ob man private Properties überhaupt verwenden sollte oder nicht besser im Code der Klasse direkt auf die Felder zugreifen sollte. Ist dabei Funktionalität erforderlich, dann schreibt man den entsprechenden Code (immerhin ist man ja der Implementierer der Klasse) einfach direkt an die Stelle , an der der Zugriff erfolgt oder mal fasst diesen Code - wenn es mehrere solche Stellen gibt - in einer Methode zusammen.

herbivore

L
667 Beiträge seit 2004
vor 12 Jahren

Da hast Du mehr reininterpretiert, als was ich gemeint habe. Um das zu praezisieren: Mit Funktionalitaet meine ich grundlegende Dinge, wie bspw. eine einfache Multiplikation etc, die auch voellig legitim ist, diese in einem Property unterzubringen.

Hallo DaMoe,

ich denke ich verstehe Dich schon, aber selbst eine einfache Multiplikation kann zu Verwirrung führen, wenn jemand das Property aufruft und nicht weiß (und es anhand des Property-Namens auch nicht erkennen kann), dass dort mit dem Feld-Wert noch etwas getan wird. Wenn ich private Properties in einem Code fände, in denen noch Felder manipuliert werden, würde ich das für einen sehr schlechten Programmierstil halten. Selbst bei öffentlichen Properties sollte man vorsichtig sein und keine Aktionen im Getter oder Setter vollziehen, die der Aufrufer nicht erahnen kann. Die einzigen Szenarien in denen ich befürworten würde, dass in einem Property mehr als nur eine Rückgabe bzw. eine Zuweisung geschieht sind

a) Der Property-Name drückt das, was als Ergebnis geliefert wird bzw. was mit der Eingabe geschieht aus.
Z.B.


public int MultiplicationResult
{
   get { return input1 * input2; }
}

In diesem Fall liefert das Property nur einen errechneten Wert abhängig von zuvor getätigten Eingaben, dient also als Abkürzung für eine voll ausprogrammierte Methode, während es aber gleichzeitig den Eigenschaften-Charakter behält.

b) Bei Standard-Implementierungen, die allgemein verbreitet und bekannt sind wie z.B. das Abfeuern eines NotifyPropertyChanged Ereignisses bei einem Binding-Property.

"It is not wise to be wise" - Sun Tzu

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo zusammen,

wenn jemand das Property aufruft und nicht weiß ...

ich möchte nochmal daraufhinweisen, dass wir hier (es geht ja um private Member) über den Implementierer der Klasse (und nicht deren Benutzer) sprechen. Der Implementierer der Klasse sollte wissen, was die Klasse tut. Er hat Einblick in und Überblick über alle Details. Er kann und darf auf alle Member direkt zugreifen. Er unterliegt im Gegensatz zu den Benutzern der Klasse nicht der Kapselung. Mit anderen Worten: Der Implementierer der Klasse muss nicht vor sich selbst geschützt werden.

Hallo Lynix,

selbst eine einfache Multiplikation kann zu Verwirrung führen

jetzt gehst du zu weit. Natürlich sollte eine Property tun, was der Benutzer aufgrund des Namens erwartet. Aber ob dabei intern eine Multiplikation ausgeführt wird, kann ihm in aller Regel vollkommen egal sein. Dich hat es sicher noch nie gestört, dass in der Klasse Datetime die Properties Day, Month, usw. intern als GetDatePart (n) implementiert sind und in GetDatePart die interne Repräsentation des Datums erst in den gewünschten Wert umgerechnet werden muss. Und dafür ist sogar deutlich mehr als eine Multiplikation nötig. Sowas ist vollkommen legitim und daran ändert auch die Tatsache nichts, dass Möglichkeiten, Properties beliebig zu implementieren, auch irreführend eingesetzt werden könnte, denn jedes Feature der Sprache kann missbräuchlich eingesetzt werden.

... keine Aktionen im Getter oder Setter vollziehen, die der Aufrufer nicht erahnen kann

Für die Benutzung der (genannten DataTime-)Properties ist es vollkommen unerheblich, ob man weiß, wie sie implementiert sind. Man muss das nicht mal erahnen können (Stichwort: Abstraktion). Das ist ja gerade einer der Vorteile von Properties. Eine möglicherweise längere Ausführungszeit, spielt praktisch so gut wie nie eine Rolle.

Die einzigen Szenarien in denen ich befürworten würde, dass in einem Property mehr als nur eine Rückgabe bzw. eine Zuweisung geschieht sind ...

Deinen beiden Fällen a) und b) kann ich mich nicht anschließen. Ein Property-Name sollte weder auf die Implementierung Bezug nehmen (wieder: Abstraktion) noch sind Properties mit implementierungsneutralen Namen dazu verdammt, nur bekannte Muster zu implementieren (z.B. direkter Feldzugriff, NotifyPropertyChanged usw.).

Damit sind wir aber schon bei einer ziemlich grundsätzlichen Diskussion über Properties und ziemlich ab vom eigentlichen Thema "Private Properties vs. Private Fields", zu dem wir bitte wieder zurückkehren sollten.

herbivore

L
667 Beiträge seit 2004
vor 12 Jahren

Hallo herbivore,

vielleicht hast Du mich da missverstanden. Ein Property ist eine Eigenschaft, die einen Eigenschaftswert zurück liefert. Properties sollten aber nicht dazu missbraucht werden, zusätzlich zum Zurückliefern oder Setzen ihres Feldes noch weitere Zustände zu manipulieren. Schlimm wird es z.B. wenn ein Property Day neben dem Zurückliefern des (wie auch immer berechneten) Wertes noch die CultureInfo der Applikation oder das aktuelle Working Directory umsetzt.
Auch mit einer kleinen Multiplikation kann man Schindluder betreiben:


public int Value
{
  get { return mValue; }
  set { mValue = value * 5; }
}

myClass.Value = 7;
//...
//...
MessageBox.Show(myClass.Value); -> 35 -> häää?

Sowas ist einfach nicht intuitiv und kein Mensch kann das nach ein paar Wochen noch nachvollziehen.

Dass man alles missbrauchen kann ist klar, aber vielleicht ist es dem OP nicht klar, dass eine wie oben beschriebene Realisierung genau solch einen Missbrauch darstellt, deswegen denke ich der Hinweis sollte an dieser Stelle gestattet sein.

Ob es dabei um ein private oder public Property geht ist m.M. nach nebensächlich, denn selbst in dem Szenario, dass nur ein Entwickler an einem Projekt arbeitet (was bei dem OP ja nicht der Fall ist), weiß dieser Entwickler in 4 Wochen auch nicht mehr was sein Property intern tut.

Ein Beispiel welches aus dem Leben gegriffen ist, ist ein Property VoxelCoordinates, welches bei jeder Abfrage intern ein FixFPU aufrief. An anderer Stelle flogen dann sporadisch irgendwelche OverflowExceptions durch die Gegend und es dauerte mehrere Monate bis ich die Ursache des Fehlers durch Zufall gefunden hatte.

Hinweis von herbivore vor 12 Jahren

Sowas ist einfach nicht intuitiv

Von sowas war in diesem Thread überhaupt nicht die Rede. Es ging nicht darum, in privaten Properties etwas zu tun, was man in öffentlichen Properties auch nicht tun sollte.

Ob es dabei um ein private oder public Property geht ist m.M. nach nebensächlich,

Und genau deshalb ist die Diskussion offtopic.

"It is not wise to be wise" - Sun Tzu

A
350 Beiträge seit 2010
vor 12 Jahren

Hi Lynix,

was ist aber mit Properties , die bewusst eine Multiplikation machen ?
Oder Rabatte etc. ?

Ich habe einen Property Summe , welche mir zurückgibt _anzahl * _wert.
Das wäre deiner Meinung nach nicht legitim ?

Grüße

Hinweis von herbivore vor 12 Jahren

Natürlich ist das legitim, aber es ist eben nicht das Thema.

D
DaMoe80 Themenstarter:in
500 Beiträge seit 2007
vor 12 Jahren

@Lynix:

Ein Beispiel welches aus dem Leben gegriffen ist, ist ein Property VoxelCoordinates, welches bei jeder Abfrage intern ein FixFPU aufrief. An anderer Stelle flogen dann sporadisch irgendwelche OverflowExceptions durch die Gegend und es dauerte mehrere Monate bis ich die Ursache des Fehlers durch Zufall gefunden hatte.

Selbst mit einer privaten Methode bist Du nicht davor geschuetzt den Fehler, direkt ein privates Feld zu setzen als die entsprechende Methode zu verwenden, zu machen. ){gray}Leider wird in unserem Unternehmen das Argument in der Diskussion grundsaetzlich Properties zu verwenden (also private Properties anstatt private Felder) verwendet, um angeblich den Entwickler der Klasse vor sich selbst zu schuetzen und die Lesbarkeit zu erhoehen.

@Herbivore: Nebst des Ueberlicks zu Properties, zeigt der von mir gepostete Link auch eine einfach Multiplikation. Sicherlich handelt es sich dabei um ein oeffentliches Property, aber ich wollte lediglich darstellen, dass ich mir ein privates Property in der Art vorstellen kann.

Gruss,
DaMoe

Hinweis von herbivore vor 12 Jahren

Jetzt aber bitte wirklich wieder zurück zum Thema.