2010-07-07 5 views
26

Ich lese das Buch "Clean Code" und kämpfe mit einem Konzept. Bei der Erörterung von Objekten und Datenstrukturen gibt es Folgendes an:Clean-Code: Sollten Objekte öffentliche Eigenschaften haben?

  • Objekte verbergen ihre Daten hinter Abstraktionen und stellen Funktionen offen, die mit diesen Daten arbeiten.
  • Data Structures legen ihre Daten offen und haben keine sinnvollen Funktionen.
  • Also, was ich davon bekomme, ist, dass ich keine öffentlichen Eigenschaften auf meinem Objekt haben sollte, ich sollte nur Methoden haben, die Operationen auf den Eigenschaften ausführen. Wenn ich auf Eigenschaften zugreifen muss, sollten sie sich auf einer Datenstruktur befinden, die von einer Methode für mein Objekt zurückgegeben werden könnte? Mit diesem Ansatz scheint es, dass ich eine GetHeight() - und SetHeight() -Methode für meine Height-Eigenschaft für mein Objekt benötige, anstatt nur get und der Eigenschaft zu verwenden.

    Vielleicht verstehe ich nicht genau, was vorgeschlagen wird, aber das ist mein Verständnis von "Objekte verstecken ihre Daten." Wenn Sie mir helfen könnten, dies zu verstehen, würde ich es sehr zu schätzen wissen!

    Vielen Dank im Voraus!

    +2

    auf das Hinzufügen auf Die Verwirrung ist wahrscheinlich auf die Tatsache zurückzuführen, dass viele Sprachen keine Eigenschaften unterstützen. In diesem Fall haben Sie die Wahl zwischen Zugriffsmethoden und öffentlichen Feldern, und die richtige Auswahl sind immer Zugriffsmethoden. C# hat dieses Problem nicht, da es Eigenschaften unterstützt. –

    Antwort

    17

    Öffentliche Eigenschaften sind in Ordnung. Nicht über die expliziten Methoden GetHeight() und SetHeight() schreiben zu müssen, ist was Eigenschaften sind. Eine Eigenschaft in C# ist nicht Daten; Es wird am besten als ein Paar von Getter/Setter-Methoden angesehen. (Eigenschaften werden tatsächlich in Methoden in der generierten IL kompiliert.)

    Das Verstecken von Daten ist möglich, da Sie die Implementierung ändern können, ohne die Schnittstelle zu ändern.Zum Beispiel könnten Sie

    public int Height { get; set; } 
    

    in

    public int Height { get { return m_width; } set { m_width = value; } } 
    

    ändern, wenn Sie sich entschieden, dass Ihr Objekt immer Platz sein sollte. Der Code, der Ihre Klasse verwendet, benötigt keine Änderungen.

    Wenn also Ihr Objekt öffentliche Eigenschaften freigibt, "verbirgt es trotzdem Daten hinter Abstraktionen und macht Funktionen verfügbar, die mit diesen Daten arbeiten", wie das Buch empfiehlt.

    4

    Eigenschaften sind in der Tat Methoden.
    Der Compiler kompiliert Eigenschaften zum Abrufen/Setzen von MIL-Methoden.

    30

    Tatsächlich ist eine C# Eigenschaft keine Daten, ist ein Accessor, also ist es eine Funktion, die mit Daten arbeitet.

    Sie sollten öffentliche Felder vermeiden, nicht öffentliche Eigenschaften.

    +3

    ja, aber öffentliche Felder sind OK auf Datenverkehr Objekte –

    +2

    Ich vermeide DTOs, aber in bestimmten Kontexten. Wenn ich sie benutzen muss, bevorzuge ich Auto-Eigenschaften. – onof

    +0

    Für fast alle Projekte gibt es keinen Grund, Eigenschaften über Felder zu bevorzugen, und mehrere Gründe, Felder vorzuziehen. Felder sind: [1] garantiert behavioureless (die Änderung zu einer Eigenschaft, um Verhalten hinzuzufügen, erfordert eine Neukompilierung, das ist * gut *); [2] manchmal schneller und nie langsamer; [3] haben einen kürzeren Code; [4] kann "readonly" sein, das ist eine viel stärkere Garantie als nur "bekommen". Verwenden Sie Eigenschaften nur dann, wenn Sie eine öffentliche API schreiben, die Eigenschaften aufweist, die Verhalten in zukünftigen Versionen zulassen müssen, die binärkompatibel sind oder einen privaten Setter benötigen (aber stattdessen "readonly" berücksichtigen). –

    2

    Durch die Erstellung öffentlicher Accessoren mit privaten Feldern wird ein Vertrag zwischen dem Benutzercode und Ihrer Klasse erstellt. Im Idealfall sollte dieser Vertrag keine Änderungen an Codeänderungen vornehmen.

    In C# ist die Einhaltung der Vertragskonformität mit einem interface. Mit Schnittstellen können Sie erforderliche Methoden- und Eigenschaftenimplementierungen angeben, jedoch keine Felder zulassen.

    Darüber hinaus werden in verschiedenen Punkten von .NET Eigenschaften oft über Felder bevorzugt. z.B. PropertyGrid Steuerelement nur enumeriert Eigenschaften, ASP.NET MVC-Modellklassen erfordern Eigenschaften usw.

    3

    Eigenschaften sind im Wesentlichen kurze Hand für Getter und Setter-Methoden. Der Sinn der Getter- und Setter-Methoden besteht darin, dass das Objekt alle Operationen mit Variablen behandelt, so dass Sie zusätzliche Operationen ausführen können (z. B. Datenvalidierung), ohne unerwünschte Konsequenzen zu verursachen.

    Ich denke, dass Sie auf automatische Eigenschaften hängen, die keine Hintergrundvariablen haben und als Ergebnis selbst wie Variablen aussehen.

    0

    Tatsächlich unter Verwendung einer Eigenschaft z.

    Sie verbergen ihre Daten, da eine implizite Variable zum Speichern des von der SomeValue-Eigenschaft zurückgegebenen Wertsatzes vorhanden ist.

    Wenn Sie

    public class Temp 
    { 
        private int someValue; 
        public int SomeValue 
        { 
        get{ return this.someValue;} 
        set{ this.someValue = value;} 
        } 
        public void SomeMethod() 
        { 
        this.someValue++; 
        } 
    } 
    

    Dann haben Sie werden sehen, was ich meine. Sie verbergen die Daten des Objekts someValue und beschränken den Zugriff darauf mithilfe des SomeValue-Properties.

    3

    Das Buch versucht zu beschreiben, die Theorie, dass ein Objekt nicht offen legen sollte, wie die Klasse tatsächlich implementiert ist. In komplizierteren Objekten liefern viele der internen Variablen nicht unbedingt die richtige Information von außen und sollten nur Methoden haben, die auf sie einwirken.

    Jedoch fällt diese harte Regel schnell auseinander, wenn Sie einfache Objekte haben. Im Fall eines Rechtecks ​​sind Höhe und Breite grundlegende Eigenschaften, die der Benutzer wissen möchte. Und da die Implementierung dieses Prinzips einfach ist, macht die Verwendung von get und set Ihren Code nicht komplizierter, als er sein muss.

    10

    Es ist meistens eine andere Definition des Begriffs "Eigentum". Eine Eigenschaft in C# ist nicht das, was die meisten anderen Sprachen als Eigenschaften bezeichnen.

    Beispiel:
    A C++ öffentliches Eigentum ist:

    class foo 
    { 
        public: 
        int x; 
    }; 
    

    Der entsprechende Begriff in C# ein öffentliches Feld sein würde:

    class foo 
    { 
        public int x; 
    } 
    

    Was wir in C# nennen als Eigenschaften Setter wäre und Getters in anderen Sprachen:

    C#:

    class foo 
    { 
        public int X { get; set; } 
    } 
    

    entsprechend C++:

    class foo 
    { 
        private: 
        int x; 
    
        public: 
        void setX(int newX) { this->x = newX; } 
        int getX() { return this->x; } 
    } 
    

    Kurz:
    C# Eigenschaften sind völlig in Ordnung, nicht blindlings nur nicht standardmäßig sie und Sets zu bekommen und nicht jedes Datenfeld in der Klasse einer machen öffentliches Eigentum, denke darüber nach, was Nutzer deiner Klasse wirklich wissen/ändern müssen.

    1

    Wie andere Beiträge in diesem Thread werde ich darauf hinweisen, dass Eigenschaften in C# nur spezielle Fälle von Accessor-Funktionen sind, die Sie erwähnen.Tatsächlich können Sie die Methoden get_Property und set_Property in der IL für Ihr Objekt optimieren, die ein Flag haben, das angibt, dass es sich um Eigenschaften handelt. Dies gilt auch für Ereignisse, die die Methoden add_ und remove_ mit Präfix implementieren.

    Ein wichtiger Unterschied beim Umgang mit Abstraktionen ist, ob das Festlegen der Eigenschaft auf das Objekt wirkt, außer nur den internen Status zu aktualisieren oder eine PropertyChanged-Ausnahme auszulösen.

    Wenn Sie sich viele interne BCL-Objekte ansehen, werden die Eigenschaften so implementiert, dass Sie alle Eigenschaften in beliebiger Reihenfolge einstellen können, um das Objekt zu konfigurieren. Wenn eine komplexe Verarbeitung durchgeführt wird, ist normalerweise eine Methode, die beschreibt, was passieren wird, eine bessere Wahl.

    9

    Wenn Sie Clean Code fertig sind würde ich empfehlen Sie Bob Martins andere Buch lesen:

    Agile Principles Patterns and Practices In C#

    die große ammount des Buches In diesem Buch Studie ein Fall diskutiert und in ihm, Bob wendet die in Clean Code erörterten Prinzipien an. Ich lese zuerst Clean Code, aber im Rückblick denke ich "Agile Patterns" sollte zuerst gelesen werden, da Clean Code eher ein Tageshandbuch oder ein Handbuch mit guten SW-Prinzipien ist.

    Zum Beispiel in "Agile Muster ..." den folgenden Code verwendet:

    public class OrderData 
    { 
    public string customerId; 
    public int orderId; 
    public OrderData() {} 
    
    ... 
    
    } 
    

    Die folgende Validierung der Nutzung von öffentlichen Daten befasst sich mit Ihrer Frage:

    Don‘ t durch die Verwendung von öffentlichen Daten Mitgliedern beleidigt werden. Dies ist kein Objekt in der wahre Sinn. Es ist einfach ein Container für Daten. Es hat kein interessantes Verhalten, das eingekapselt sein muss. Machen Sie die Daten Variablen privat, und Getter und Setter wäre eine Verschwendung der Zeit. Ich könnte eine Struktur anstelle einer Klasse verwendet haben, aber ich möchte, dass die OrderData durch den Verweis statt nach Wert übergeben werden.


    Abgesehen:

    Persönlich muss ich sagen, dass Robert Martin einen massiven Beitrag zur SW-Entwickler-Community (zusammen mit Martin Fowler, Michael Feathers ..) mit dieser Bücher gemacht hat. Ich denke, sie müssen lesen.

    +0

    Es gibt auch [The Clean Coder] (http://www.amazon.com/The-Clean-Coder-Professional-Programmers/dp/0137081073) - anderes Thema, aber es lohnt sich, IMHO zu lesen. – TrueWill

    2

    Hier ist der Deal.

    Obwohl öffentliche Variablen gelegentlich nützlich sein können, ist es oft am besten, sie privat zu halten.

    Es ist einfach, Ihren Code organisiert zu halten, wenn das Objekt das einzige Steuerelement mit der Variablen ist.

    Stellen Sie sich vor, Sie möchten eine Höhe zwischen 0 und 200 beibehalten. Wenn Sie eine Methode zum Einstellen Ihrer Höhe haben, können Sie dies problemlos überwachen.

    Zum Beispiel (Ich werde für Geschwindigkeit willen mit Java sein):

    public void setHeight(int newHeight) 
    { 
        if (newHeight < 0) 
         height = 0; 
        else if (newHeight > 200) 
         height = 200; 
        else 
         height = newHeight 
    } 
    

    Wie Sie sehen können, ist dieser Ansatz sehr strukturiert und kontrolliert.

    Stellen Sie sich nun vor, dass wir eine Codezeile haben, die diese Höhe extern bearbeitet, weil Sie sie veröffentlichen möchten. Wenn Sie es nicht außerhalb des Codes steuern, erhalten Sie möglicherweise eine Höhe, die sich nicht gut mit Ihrem Programm verhält. Selbst wenn Sie steuern möchten, würden Sie Code wiederholen.

    Sehr einfaches Beispiel, aber ich denke, es bringt den Punkt über.

    5

    Während öffentliche Eigenschaften keine unmittelbare Code Geruch sind, sollten Sie diesen Artikel:

    Coding with Reason by Yechiel Kimchi (aus dem Buch 97 Dinge, die jeder Programmierer wissen sollten)

    “... fragen Sie nicht ein Objekt Für Informationen, mit denen gearbeitet werden soll, bitten Sie das Objekt, die Arbeit mit den Informationen zu erledigen, die es bereits hat. "

    Dies spielt nicht immer die Hauptrolle (z. B. Datenübertragungsobjekte). Worauf ich achten muss, ist Inappropriate Intimacy.

    +2

    +1 für das Zitat auf meinem Schreibtisch hängen! Danke für die Referenz. – JSprang

    +0

    Dies ist streng OOP-Ansatz. In einigen Kontexten schwer zu erreichen. Betrachten Sie das MVVM-Muster. – onof

    3

    In reinem OO muss "ein reales Objekt" die Daten vollständig verbergen, die es verwendet, um seine Verantwortung zu erfüllen. Es muss also vermieden werden, dass interne Daten offen gelegt werden, egal ob dies durch ein öffentliches Feld, eine öffentliche Eigenschaft oder öffentliche Getter/Setter-Funktionen geschieht.

    Interne Daten sind nicht versteckt, nur durch den Routing-Zugriff auf es durch eine Eigenschaft ABSTRAKTIERT!

    Um Ihre Frage zu beantworten: - Vermeiden Sie öffentliche Eigenschaften, wenn Sie ein Objekt schreiben - Nutzung öffentlicher propertiers wenn Sie Datenstrukturen zu schreiben sind (ein öffentliches Feld die Arbeit machen würde, auch)