Best Practice: Reihenfolge von öffentlich / geschützt / privat innerhalb der Klassendefinition?

92

Ich starte ein neues Projekt von Grund auf und möchte, dass es sauber ist und gute Codierungsstandards hat. In welcher Reihenfolge legen die erfahrenen Entwickler hier die Dinge gerne innerhalb einer Klasse an?

A: 1) öffentliche Methoden 2) private Methoden 3) öffentliche Vars 4) private Vars

B: 1) öffentliche Variablen 2) private Variablen 3) öffentliche Methoden 4) private Methoden

C: 1) öffentliche Variablen 2) öffentliche Methoden 3) private Methoden 4) private Variablen

Im Allgemeinen möchte ich öffentliche statische Variablen an die Spitze setzen, aber würde dann eine öffentliche statische Methode vor Ihrem Konstruktor aufgeführt, oder sollte der Konstruktor immer zuerst aufgeführt werden? Diese Art von Ding...

Ich weiß, dass es finnicky ist, aber ich habe mich nur gefragt: Was sind die besten Praktiken dafür?

PS: Nein, ich benutze kein Cc #. Ich weiß. Ich bin ein Idiot.

temporärer Name
quelle
9
Es ist nichts Falsches daran, C # nicht zu verwenden. Ich habe in all meinen Jahren als professioneller Entwickler noch nie einen Stich C # geschrieben. Verwenden Sie eine Sprache, die für die Aufgabe geeignet ist, und sagen Sie jedem, der etwas anderes sagt, wo er hingehen kann!
Ether
1
Mögliches Duplikat von stackoverflow.com/questions/150479/…
Michael Freidgeim

Antworten:

139

In Clean Code rät Robert C. Martin den Codierern, Mitgliedsvariablen immer an die Spitze der Klasse zu setzen (zuerst Konstanten, dann private Mitglieder), und Methoden sollten so angeordnet werden, dass sie sich wie eine Geschichte lesen, die nichts verursacht Der Leser muss zu viel im Code herumspringen. Dies ist eine sinnvollere Methode zum Organisieren von Code als durch Zugriffsmodifikatoren.

Asaph
quelle
10
Ich hatte auch viel Glück beim Hinzufügen: Getter / Setter zuletzt. Es hilft mir, dass sich der Unterricht weniger sperrig anfühlt.
Dean J
5
Konstruktoren oben direkt nach den Elementvariablen. In OOP beginnt die Ausführung mit der Objektinstanziierung.
Asaph
6
Wenn der Leser zu viel im Code herumspringt, muss dies wahrscheinlich mit dem Erzwingen des Lesens aller Details privater Methoden in Einklang gebracht werden. Die Zeitungsmetapher wird wahrscheinlich dahingehend missverstanden, dass Ihre öffentlichen Methoden weitgehend das darstellen sollten, was Ihre Klasse tut, und Ihre privaten Methoden die Details liefern (fast wie eine Fußnote, auf die Sie sich bei Bedarf beziehen können).
Kenny Hung
1
Ich bin verwirrt. Sie sagten: (zuerst Konstanten, dann private Mitglieder) . OK. Wohin gehen die öffentlichen Mitglieder dann?
Honig
1
@Honey Sie würden direkt nach den Konstanten und den privaten Mitgliedern gehen. Das wäre also in der folgenden Reihenfolge: Konstanten, private Mitglieder, öffentliche Mitglieder.
Pierre Gillet
48

Die beste Vorgehensweise ist, konsequent zu sein .

Persönlich bevorzuge ich es, publicMethoden an die erste Stelle zu setzen, gefolgt von protectedMethoden, gefolgt von privateMethoden. Mitglied Daten sollten generell immer privat oder geschützt sein, es sei denn , Sie haben einen guten Grund für die es nicht so sein.

Mein Grund , publicMethoden an die Spitze zu setzen, ist, dass sie die Schnittstelle für Ihre Klasse definieren, sodass jeder, der Ihre Header-Datei liest, diese Informationen sofort sehen kann.

Im Allgemeinen privateund protectedMitglieder sind weniger wichtig für die meisten Menschen in der Header - Datei suchen, es sei denn , sie die Interna der Klasse modifizieren erwägen. Wenn Sie sie "aus dem Weg" halten, wird sichergestellt, dass diese Informationen nur auf der Basis von Kenntnissen aufbewahrt werden , einem der wichtigsten Aspekte der Kapselung.

LeopardSkinPillBoxHat
quelle
LeopardSkikPBH, ich stimme vollkommen zu ... das macht Sinn! Ich glaube, ich war verwirrt darüber, ob var oder funcs Vorrang haben. Vielen Dank!
Tempname
10
Ich stimme nicht zu, dass die beste Vorgehensweise darin besteht, konsistent zu sein. Es gibt viele Möglichkeiten, konsistent unlesbaren, nicht verwaltbaren Code zu schreiben.
Jason
3
@Jason, das heißt, es ist nicht empfehlenswert, auf der Straßenseite zu bleiben, da es dort immer noch zu Unfällen kommen kann.
Rex M
1
@ Jason - Vielleicht hätte ich klarer sein sollen. In diesem speziellen, ziemlich subjektiven Fall (Reihenfolge der Methoden) denke ich, dass die beste Vorgehensweise darin besteht, konsistent zu sein. Jeder wird Meinungen darüber haben, wie man Dinge am besten bestellt, aber wenn man von Natur aus konsequent ist, sollte es ziemlich wartbar sein. Ich bin damit einverstanden, dass "konsistent sein" nicht immer die beste Vorgehensweise für alle Codebereiche ist, insbesondere wenn Sie die schlechte Codequalität berücksichtigen, mit der Sie häufig zu kämpfen haben.
LeopardSkinPillBoxHat
3
@ Rex M: Nein, was ich gesagt habe, entspricht überhaupt nicht Ihrer Interpretation. Mein Punkt ist, dass es in diesem Fall kein starkes Argument ist, nur konsequent zu sein. In einigen Fällen ist die Konsistenz in Ordnung (z. B. Platzierung von Zahnspangen). Die Auswahlmöglichkeiten hier wirken sich jedoch tatsächlich auf die Lesbarkeit des Codes aus. Daher ist ein Argument erforderlich, das stärker als die Konsistenz ist.
Jason
8

Ich glaube, ich habe eine andere Philosophie als die meisten anderen. Ich bevorzuge es, verwandte Elemente zu gruppieren. Ich kann es nicht ertragen, herumspringen zu müssen, um mit einer Klasse zu arbeiten. Der Code sollte fließen und die Verwendung einer eher künstlichen Reihenfolge basierend auf der Barrierefreiheit (öffentlich, privat, geschützt usw.) oder der Instanz im Vergleich zur statischen oder der Mitgliedschaft im Vergleich zur Eigenschaft im Vergleich zur Funktion trägt nicht dazu bei, einen guten Fluss aufrechtzuerhalten. Wenn ich also eine öffentliche Methode verwende Method, die von privaten Hilfsmethoden usw. implementiert wird HelperMethodA, werde HelperMethodBich diese Methoden nicht weit voneinander entfernt in der Datei haben, sondern nahe beieinander halten. Wenn ich eine Instanzmethode habe, die von einer statischen Methode implementiert wird, werde ich diese ebenfalls zusammenfassen.

So sieht mein Unterricht oft so aus:

class MyClass {
    public string Method(int a) {
        return HelperMethodA(a) + HelperMethodB(this.SomeStringMember);
    }

    string HelperMethodA(int a) { // returns some string }

    string HelperMethodB(string s) { // returns some string }

    public bool Equals(MyClass other) { return MyClass.Equals(this, other); }

    public static bool Equals(MyClass left, MyClass right) { // return some bool }

    public double SomeCalculation(double x, double y) {
        if(x < 0) throw new ArgumentOutOfRangeException("x");
        return DoSomeCalculation(x, y); 
    }

    const double aConstant;
    const double anotherConstant;
    double DoSomeCalculation(double x, double y) {
        return Math.Pow(aConstant, x) * Math.Sin(y) 
            + this.SomeDoubleMember * anotherConstant;
    }       
}
Jason
quelle
8

Persönlich mag ich öffentlich oben, geschützt und dann privat haben. Der Grund dafür ist, dass jemand, der den Header aufbricht, zuerst sieht, auf was er zugreifen kann, und dann beim Scrollen nach unten weitere Details.

Man sollte sich nicht die Implementierungsdetails einer Klasse ansehen müssen, um sie zu verwenden, dann ist das Klassendesign nicht gut gemacht.

AndersK
quelle
3

Ich habe mich oft darum gekümmert. In den letzten Jahren mit modernen IDEs ist so ziemlich alles nur 1 oder 2 Tastenanschläge entfernt. Ich habe meine Standards erheblich entspannen lassen. Jetzt beginne ich mit Statik, Mitgliedsvariablen und dann mit Konstruktoren. Danach mache ich mir keine großen Sorgen mehr.

In C # lasse ich Resharper die Dinge automatisch organisieren.

ScottS
quelle
Genau. Meine normale Art, durch die Mitglieder in einer Datei zu navigieren, besteht darin, ein Tool zu verwenden, das in die von mir verwendete IDE oder den von mir verwendeten Editor integriert ist. Die eigentliche Gruppierung der Mitglieder wird zweitrangig. Ich bin jedoch damit einverstanden, dass Mitglieder gruppiert werden sollten, um eine rein zufällige Reihenfolge zu vermeiden, und ich verwende resharper, um die Gruppierung und Bestellung automatisch durchzuführen.
Phillip Ngan
2

Dies wäre meine Bestellung

  1. Statische Variablen
  2. Statische Methoden
  3. Öffentliche Variablen
  4. Geschützte Variablen
  5. Private Variablen
  6. Konstruktoren
  7. Öffentliche Methoden
  8. Geschützte Methoden
  9. Private Methoden

Ich verwende die folgenden Regeln:

  • statisch vor allem
  • Variablen vor Konstruktoren vor Methoden (ich betrachte Konstruktoren als in der Kategorie der Methoden)
  • öffentlich vor geschützt vor privat

Die Idee ist, dass Sie das Objekt (die Daten) vor den Verhaltensweisen (Methoden) definieren. Statik muss getrennt werden, da sie weder Teil des Objekts noch dessen Verhalten ist.

Barkmadley
quelle
danke barkmadley ... das ist interessant! dass Sie 4 und 5 vor Konstruktor setzen würden. Ich werde auf jeden Fall darüber nachdenken
Tempname
Wie diese Reihenfolge, obwohl es interessant ist, statische Methoden in der Nähe der Spitze zu haben. Ich habe mit einem Entwickler zusammengearbeitet, der private Variablen ganz unten platziert hat. Ich konnte die Idee sehen, aber sie fühlte sich nicht richtig an
Carlton
2

Ich stimme im Allgemeinen der öffentlichen, geschützten, privaten Reihenfolge sowie den statischen Daten, Mitgliedsdaten und der Reihenfolge der Mitgliederfunktionen zu.

Obwohl ich manchmal wie Mitglieder gruppiere (Getter & Setter), bevorzuge ich es im Allgemeinen, Mitglieder innerhalb einer Gruppe ALPHABETISCH aufzulisten, damit sie leichter gefunden werden können.

Ich mag es auch, die Daten / Funktionen vertikal auszurichten. I Tabulator / Leerzeichen nach rechts genug, damit alle Namen in derselben Spalte ausgerichtet sind.

AlanKley
quelle
1
Hey - ein "Tab-Spacer" nach meinem eigenen Herzen! :-) Ich bin nicht zwanghaft. Ehrlich bin ich nicht!
Tempname
1

Für jeden sein eigenes und wie Elzo sagt, haben moderne IDEs es einfacher gemacht, Mitglieder und ihre Modifikatoren auf einfache Weise mit farbigen Symbolen in Dropdown-Menüs und dergleichen zu finden.

Meiner Meinung nach ist es für den Programmierer wichtiger zu wissen, wofür die Klasse entwickelt wurde und wie sie sich voraussichtlich verhalten wird.

Wenn es sich also um einen Singleton handelt, habe ich die Semantik (statische getInstance () -Klasse) an die erste Stelle gesetzt.

Wenn es sich um eine konkrete Fabrik handelt, stelle ich zuerst die Funktion getNew () und die Funktionen register / initialize ein.

... und so weiter. Wenn ich zuerst sage, meine ich kurz nach den c'tors und d'tor - da sie die Standardmethode zum Instanziieren einer Klasse sind.

Die folgenden Funktionen sind dann in:

  1. logische Aufrufreihenfolge (z. B. initialize (), preProcess (), process (), postProcess ()) oder
  2. verwandte Funktionen zusammen (wie Accessoren, Dienstprogramme, Manipulatoren usw.),

Dies hängt davon ab, ob die Klasse in erster Linie als Datenspeicher mit einigen Funktionen oder als Funktionsanbieter mit wenigen Datenelementen gedacht war.

Fuchs
quelle
0

Bei einigen Editoren, wie Eclipse und seinen Nachkommen, können Sie die Variablen und Methoden in der Gliederungsansicht alphabetisch oder wie auf der Seite neu anordnen.

Elzo Valugi
quelle
0

Die Reihenfolge von öffentlich gefolgt von geschützt und privat ist für mich besser lesbar. Es ist besser, die Klassenlogik in Kommentaren oben in der Header-Datei einfach zu beschreiben und Funktionsaufrufreihenfolgen zu verwenden, um zu verstehen, welche Klassendosis und Algorithmen darin verwendet werden.

Ich benutze Qt c ++ für eine Weile und sehe einige neue Arten von Schlüsselwörtern wie signalund slotich bevorzuge es, weiter wie oben zu bestellen und meine Idee hier mit Ihnen zu teilen.

#ifndef TEMPLATE_H
#define TEMPLATE_H


class ClassName
{
    Q_OBJECT
    Q_PROPERTY(qreal startValue READ startValue WRITE setStartValue)
    Q_ENUMS(MyEnum)

public:

    enum MyEnum {
        Hello = 0x0,
        World = 0x1
    };

    // constructors

    explicit ClassName(QObject *parent = Q_NULLPTR);
    ~ClassName();

    // getter and setters of member variables

    // public functions (normal & virtual) -> orderby logic

public slots:

signals:

protected:

    // protected functions it's rule followed like public functions


private slots:

private:

    // methods

    // members

};

#endif // TEMPLATE_H
saeed
quelle