Bonne pratique: ordonner public / protégé / privé dans la définition de classe?

92

Je commence un nouveau projet à partir de zéro et je veux qu'il soit propre / ait de bonnes normes de codage. Dans quel ordre les développeurs expérimentés ici aiment-ils organiser les choses au sein d'une classe?

A: 1) méthodes publiques 2) méthodes privées 3) variables publiques 4) variables privées

B: 1) vars publiques 2) vars privées 3) méthodes publiques 4) méthodes privées

C: 1) vars publiques 2) méthodes publiques 3) méthodes privées 4) vars privées

J'aime généralement mettre les variables statiques publiques en haut, mais alors une méthode statique publique serait-elle répertoriée avant votre constructeur, ou le constructeur devrait-il toujours être répertorié en premier? Ce genre de chose...

Je sais que c'est finnicky mais je me suis juste demandé: quelles sont les meilleures pratiques pour cela?

PS: non je n'utilise pas Cc #. Je connais. Je suis un luddite.

tempname
la source
9
Il n'y a rien de mal à ne pas utiliser C #. Je n'ai jamais écrit un point de C # de toutes mes années en tant que développeur professionnel. Utilisez le langage qui convient à la tâche et dites à quiconque dit quelque chose de différent où il peut aller le coller!
Ether
1
Copie

Réponses:

143

Dans Clean Code , Robert C.Martin conseille aux codeurs de toujours placer les variables membres en haut de la classe (les constantes d'abord, puis les membres privés) et les méthodes doivent être ordonnées de telle manière qu'elles se lisent comme une histoire qui ne cause pas le lecteur doit trop sauter dans le code. C'est une manière plus judicieuse d'organiser le code plutôt que par un modificateur d'accès.

Asaph
la source
10
J'ai également eu de la chance en ajoutant: les getters / setters last. Cela aide les cours à se sentir moins encombrants, pour moi.
Dean J
5
Constructeurs en haut, juste après les variables membres. En POO, l'exécution commence par l'instanciation d'objet.
Asaph
6
Faire en sorte que le lecteur saute trop dans le code doit probablement être équilibré avec le fait de forcer le lecteur à lire tous les détails des méthodes privées. La métaphore du journal est probablement mal comprise dans la mesure où vos méthodes publiques devraient représenter largement ce que fait votre classe, et vos méthodes privées fournissent les détails (presque comme une note de bas de page à laquelle vous pouvez vous référer si vous en avez besoin).
Kenny Hung
1
Je suis confus. Vous avez dit: (constantes d'abord, puis membres privés) . D'ACCORD. Où vont alors les membres du public?
Honey
1
@Honey Ils iraient juste après les constantes et les membres privés. Ce serait donc dans l'ordre suivant: constantes, membres privés, membres publics.
Pierre Gillet
48

La meilleure pratique consiste à être cohérent .

Personnellement, je préfère mettre les publicméthodes en premier, suivies des protectedméthodes, puis des privateméthodes. Les données des membres doivent en général toujours être privées ou protégées, à moins que vous n'ayez une bonne raison de ne pas en être ainsi.

La raison pour laquelle je place les publicméthodes en haut est qu'elle définit l' interface de votre classe, donc toute personne parcourant votre fichier d'en-tête devrait pouvoir voir ces informations immédiatement.

En général, les membres privateet protectedsont moins importants pour la plupart des gens qui consultent le fichier d'en-tête, à moins qu'ils n'envisagent de modifier les éléments internes de la classe. Les garder «à l'écart» garantit que ces informations ne sont conservées que sur la base du besoin d'en connaître , l'un des aspects les plus importants de l'encapsulation.

LéopardPeauPillboxChapeau
la source
LeopardSkikPBH, je suis tout à fait d'accord ... cela a du sens! Je suppose que j'ai été confus quant à savoir si dans cela, var ou funcs ont la priorité. Merci!
tempname
11
Je ne suis pas d'accord pour dire que la meilleure pratique consiste à être cohérente. Il existe de nombreuses façons d'écrire systématiquement du code illisible et non maintenable.
jason
3
@Jason, c'est comme dire que ce n'est pas la meilleure pratique de rester de votre côté de la route parce que vous pouvez toujours avoir des accidents là-bas.
Rex M
1
@Jason - J'aurais peut-être dû être plus clair. Dans ce cas particulier, assez subjectif (ordre des méthodes), je pense que la meilleure pratique est d'être cohérente. Tout le monde aura des opinions sur la meilleure façon d'ordonner les choses, mais si vous êtes cohérent par nature, cela devrait être assez maintenable. Je conviens que «être cohérent» n'est pas toujours la meilleure pratique pour tous les domaines du code, en particulier si l'on considère la mauvaise qualité du code avec laquelle vous devez souvent faire face.
LeopardSkinPillBoxHat
4
@Rex M: Non, ce que j'ai dit ne ressemble pas du tout à votre interprétation. Mon argument est que le simple fait d'être cohérent n'est pas un argument solide en l'espèce. Dans certains cas, la cohérence est bonne (par exemple, le placement des accolades). Mais les choix ici affectent en fait la lisibilité du code. Ainsi, un argument plus fort que la cohérence est nécessaire.
jason
8

Je pense que j'ai une philosophie différente de la plupart des autres. Je préfère regrouper les éléments liés. Je ne supporte pas de devoir sauter pour travailler avec une classe. Le code doit couler et utiliser un ordre plutôt artificiel basé sur l'accessibilité (public, privé, protégé, etc.) ou instance contre statique ou membre contre propriété contre fonction ne permet pas de garder un bon flux. Donc, si je nave une méthode publique Methodqui est implémentée par des méthodes d'aide privées HelperMethodA, HelperMethodBetc., alors plutôt que d'avoir ces méthodes éloignées les unes des autres dans le fichier, je les garderai proches les unes des autres. De même, si j'ai une méthode d'instance implémentée par une méthode statique, je vais également les regrouper.

Donc mes cours ressemblent souvent à ceci:

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
la source
8

Personnellement j'aime avoir public au sommet, protégé puis privé. La raison en est que lorsque quelqu'un ouvre l'en-tête, il / elle voit ce à quoi il / elle peut accéder en premier, puis plus de détails en défilant vers le bas.

Il ne faut pas avoir à regarder les détails d'implémentation d'une classe pour l'utiliser, alors la conception de la classe n'est pas bien faite.

AndersK
la source
3

Je m'en souciais beaucoup. Au cours des dernières années, en utilisant des IDE modernes, à peu près tout n'est qu'à 1 ou 2 touches, j'ai laissé mes normes se détendre considérablement. Maintenant, je commence par la statique, les variables membres, puis les constructeurs après cela je ne m'inquiète pas beaucoup.

En C #, je laisse Resharper organiser les choses automatiquement.

ScottS
la source
Je suis d'accord. Mon mode normal de navigation parmi les membres d'un fichier est d'utiliser un outil intégré à l'IDE ou à l'éditeur que j'utilise. Le regroupement effectif des membres devient secondaire. Cependant, je suis d'accord que les membres doivent être regroupés pour éviter un ordre aléatoire pur, et j'utilise resharper pour le regroupement et la commande automatiquement.
Phillip Ngan
2

Ce serait ma commande

  1. Variables statiques
  2. Méthodes statiques
  3. Variables publiques
  4. Variables protégées
  5. Variables privées
  6. Constructeurs
  7. Méthodes publiques
  8. Méthodes protégées
  9. Méthodes privées

J'utilise les règles suivantes:

  • statique avant tout
  • les variables avant les constructeurs avant les méthodes (je considère que les constructeurs sont dans la catégorie des méthodes)
  • public avant protégé avant privé

L'idée est de définir l'objet (les données), avant les comportements (méthodes). Les statiques doivent être séparées car elles ne font pas vraiment partie de l'objet, ni de son comportement.

barkmadley
la source
merci barkmadley ... c'est intéressant! que vous mettriez 4 et 5 avant le constructeur. Je vais certainement y penser
tempname
Comme cet ordre, bien qu'avoir des méthodes statiques près du sommet soit intéressant. J'ai travaillé avec un développeur qui a mis des variables privées en bas, je pouvais voir l'idée mais ça ne me semblait pas bien
Carlton
2

Je suis généralement d'accord avec l'ordre public, protégé, privé ainsi que l'ordre des données statiques, des données membres, des fonctions membres.

Bien que je regroupe parfois des membres (getters et setters), je préfère généralement lister les membres au sein d'un groupe ALPHABÉTIQUEMENT afin qu'ils puissent être localisés plus facilement.

J'aime aussi aligner les données / fonctions verticalement. Je tabule / espace suffisamment à droite pour que tous les noms soient alignés dans la même colonne.

AlanKley
la source
1
Hé - un 'tab-spacer' après mon propre cœur! :-) Je ne suis pas obsessionnel compulsif. Honnêtement, je ne suis pas!
tempname
1

À chacun le sien, et comme le dit Elzo, les IDE modernes ont facilité la recherche de membres et de leurs modificateurs de manière simple avec des icônes colorées dans les menus déroulants et autres.

Mon opinion est qu'il est plus important pour le programmeur de savoir à quoi la classe a été conçue et comment on peut s'attendre à ce qu'elle se comporte.

Donc, s'il s'agit d'un Singleton, je mets la sémantique (classe statique getInstance ()) en premier.

S'il s'agit d'une usine concrète, je mets en premier la fonction getNew () et les fonctions register / initialize.

... etc. Quand je dis d'abord, je veux dire peu de temps après les c'tors et d'tor - car ils sont le moyen par défaut d'instancier une classe.

Les fonctions qui suivent sont alors en:

  1. ordre d'appels logique (par exemple initialize (), preProcess (), process (), postProcess ()), ou
  2. les fonctions associées ensemble (comme les accesseurs, les utilitaires, les manipulateurs, etc.),

selon que la classe était principalement destinée à être un magasin de données avec certaines fonctions ou un fournisseur de fonctions avec quelques membres de données.

Renard
la source
0

Certains éditeurs, comme Eclipse et sa progéniture, vous permettent de réorganiser dans la vue d'ensemble les vars et les méthodes, par ordre alphabétique ou comme dans la page.

Elzo Valugi
la source
0

La séquence de public suivi de protected et private est plus lisible pour moi, il est préférable de décrire simplement la logique de classe dans les commentaires en haut du fichier d'en-tête et les ordres d'appel de fonction pour comprendre ce qu'une classe dose et les algorithmes utilisés à l'intérieur.

J'utilise Qt c ++ depuis un moment et je vois de nouveaux types de mots-clés comme signalet slotje préfère continuer à commander comme ci-dessus et partager mon idée avec vous ici.

#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
la source