Comment disposez-vous normalement les régions d'une classe?


17

Je me demandais s'il y avait une norme pour définir les régions d'une classe.

J'utilise actuellement

Fields
Constructor
Properties
Public Methods
Private Methods

Fieldsêtre des propriétés privées et Propertiesêtre les propriétés publiques. J'utiliserai normalement des sous-régions au sein de celle-ci si nécessaire, ou ajouterai occasionnellement d'autres régions ci-dessous (telles que des membres d'interface ou de baseClass).


1
Parlez-vous de la mise en page en général ou utilisez-vous "#regions"?
snmcdonald

1
@snmcdonald J'utilise des #regionbalises pour définir une section
Rachel

Cela ne devrait-il pas être une question wiki communautaire? Je ne crois pas qu'il existe une norme, et la réponse pourrait changer selon les langues.
Raveline

7
Je commence par supprimer tous les #regions
Ed S.

3
@Ed S. +1 parce que les régions sont le diable. Tout ce qu'ils vous permettent de faire est de masquer le fait que votre fichier de code est trop volumineux et doit être refactorisé.
MattDavey

Réponses:


4

Énumérations liées aux classes ou parfois structures / classes de données pures (au-dessus de la définition de classe réelle)

--- Définition de classe ---

Membres privés

CTOR / DTOR si la langue a des DTOR

Propriétés publiques

Méthodes utilitaires (méthodes privées ou protégées à petite portée)

Fonctionnalité de classe (peut être divisée en plusieurs régions en fonction de l'étendue de la classe).


17

Sous-régions? Votre classe a-t-elle une responsabilité unique ? (implicite en ce que ... ma réponse est "Rarement des régions, sauf peut-être pour regrouper les propriétés, les constructeurs et les méthodes" ... mais même dans ce cas, je ne l'utilise pas beaucoup)


2
Je programme en WPF en ce moment et un exemple de certaines sous-régions que j'utiliserais est un ViewModel qui a ses propriétés publiques divisées en propriétés, commandes, données liées à l'interface utilisateur, etc. Cela facilite beaucoup la recherche de ce que je suis cherche rapidement
Rachel

2
Pourquoi ne pas utiliser de grandes bannières de commentaires au lieu de régions? // ----------ViewModel Properties---------- De cette façon, vous pouvez toujours voir le code (ou le réduire avec un aperçu et voir les membres). Les régions servent à cacher des choses. Le code ne doit pas être caché, sauf s'il est généré automatiquement ou quelque chose.
Kyralessa

1
@Rachel favorise la composition.
MattDavey

10

Je voulais juste confirmer que vous vouliez dire "#regions" et non la disposition des classes en général.

Je suis surpris que personne n'ait mentionné d'éviter d'utiliser les régions. Je comprends que le PO souhaite faire un sondage sur la délimitation des régions, mais je voudrais soulever un autre point de vue.

J'évite les régions. J'aime voir le code avec lequel je travaille. Si vous trouvez difficile de trouver ce que vous cherchez, utilisez le pliage de code et regroupez les constructions de classe similaires.

Pourquoi je déteste les régions? CTRL+M,Let CTRL+M,Obasculera le pliage du code. Cependant, lors de l'effondrement, il masque toute la région. J'ai seulement besoin de réduire les méthodes / propriétés / commentaires.

S'il y a trop de régions, c'est peut-être une odeur de code et votre classe fait trop de travail. Jeff Atwood fournit un bon article sur les régions qui mérite d'être lu.

Ma citation préférée sur #regions:

Non, je n'utiliserai pas #regions. Et non, je ne négocie pas avec les terroristes. Tais-toi.

- Jeff Atwood

Cela étant dit, je sais que de nombreux programmeurs insistent pour les utiliser. Cette question est subjective. J'avais juste pensé offrir une alternative.


1
Voici une macro pour réduire les définitions mais développer les régions, au cas où vous seriez coincé à travailler avec des gens amoureux des régions: stackoverflow.com/questions/523220/awesome-visual-studio-macros/… Cela fonctionne bien sauf si vous êtes travailler avec des gens vraiment malades qui mettent les régions dans les méthodes .
Kyralessa

Une macro très utile! Je ne sais pas pourquoi ils ne l'ont pas intégré dans Visual Studio, néanmoins, merci.
snmcdonald

Mon patron aime les régions, les adore. Il aime également les cours internes privés et les méthodes énormes. Notre code a une classe avec environ une douzaine de régions qui la divisent, 3 classes internes et certaines méthodes si longues qu'elles contiennent une douzaine de régions de niveau supérieur, avec des sous-régions à l'intérieur de celles-ci.
CodexArcanum

4

Cela varie d'une langue à l'autre. Étant donné que je suis un codeur Delphi, j'ai tendance à suivre la convention standard Delphi, qui ressemble à ceci:

type
  TMyClass = class(TBaseClass)
  private
    private fields
    private methods
  protected
    protected fields
    protected methods
    protected properties
  public
    constructor(s)
    destructor
    public methods
    public properties
  end;

Je trouve que c'est un bon moyen d'organiser des informations faciles à lire et à comprendre.


3
Je trouve assez étonnant que les informations privées, protégées, publiques et publiées soient classées par ordre alphabétique et encapsulation et commencent toutes par P!
Peter Turner

amusant, je ne le fais pas. J'ai toujours trouvé qu'il était plus naturel de faire la liste en publicpremier, car la plupart des utilisateurs ne se soucient que des publicchoses.
Matthieu M.

J'ai toujours trouvé que cette convention était une idée vraiment stupide. Qu'est-ce que la visibilité a à voir avec la fonctionnalité? Dans tous les cas, j'ai toujours utilisé des interfaces pour définir la fonctionnalité publique, mais j'ai implémenté l'interface comme protégée sur la classe. Les seuls éléments que je regrouperai de manière cohérente sont les méthodes et les propriétés publiées pour les composants, et sinon je grouperai toujours par Interfaces et héritage, en utilisant plusieurs mots-clés de visibilité selon les besoins. Les éléments qui sont uniques à l'implémentation de classe (c'est-à-dire: pas les remplacements) doivent vraiment être répertoriés en premier.
S.Robins

3

J'ai tendance à les disposer de la manière suivante:

Public fields (usually static constants)
Constructors
Public methods
Private methods
Private fields

N'ont pas utilisé un langage qui utilise Propertiesdonc c'est pourquoi ceux-ci ne sont pas présentés. Je mets les méthodes et les champs privés en bas car si quelqu'un d'autre utilise ce fichier dans son code, il ne devrait avoir à se préoccuper que de l'API, qui est publique. Et tous les éditeurs de texte que je connais, et même les IDE, placent le curseur en haut lors de l'ouverture des fichiers.


+1 pour mettre les champs privés en bas. Je regroupe les méthodes publiques par l'interface qu'elles implémentent et place celles qui n'implémentent aucune interface en haut, juste après les constructeurs / destructeurs.
Sjoerd

2

C'est un jugement pour moi. J'utilise des régions lorsqu'elles sont nécessaires à la lisibilité.

J'utilise également une couleur différente dans mon jeu de couleurs Visual Studio (actuellement un rouge foncé) pour les faire ressortir du reste du code.


Exemple d'utilisation d'un #region: si j'écris une méthode de test pour un test unitaire qui nécessite un extrait de code multiligne de XML, la chaîne XML rompra l'indentation habituelle (car elle commence le long de la marge gauche de la fenêtre de code. Pour masquer la laideur, je vais l'envelopper dans une # région, afin de pouvoir la réduire.


2

Le livre Clean Code de Bob Martin consacre tout le 5ème chapitre au formatage. Il y a quelques points clés que je pense résumer bien.

  • La plupart des tentatives de regroupement des variables et des méthodes par visibilité et propreté n'ont pas beaucoup de sens et vous obligent à naviguer dans le code beaucoup.
  • Garder les méthodes qui s'appellent les unes les autres verticalement réduit la quantité de navigation que vous devez faire et facilite la recherche de choses.
  • Votre train de pensée ne va pas être rompu si vous devez vous arrêter et penser "dans quelle région appartient ce morceau de code?" toutes les quelques minutes.
  • Les variables d'instance doivent généralement être peu nombreuses et susceptibles d'être utilisées partout, elles appartiennent donc au sommet de la classe où elles seront les plus faciles à localiser. Les variables et déclarations qui ne seront utilisées que par une seule méthode doivent exister à l'intérieur de cette méthode. S'ils ne sont utilisés que par quelques méthodes, ils doivent être proches verticalement mais au-dessus des quelques méthodes qui les utilisent.

Garder votre code organisé avec des éléments communément interactifs verticalement rapprochés élimine efficacement tout besoin de créer des régions spécifiques. Si votre code est si long qu'il nécessite que les régions cachent beaucoup de code, alors c'est peut-être une odeur de code indiquant que la classe essaie d'en faire trop. Peut-être que certaines fonctionnalités peuvent être déplacées vers une classe utilitaire, ou poussées vers un ancêtre.

Si vous avez besoin de "cacher" le code parce qu'il est trop long ou trop "moche", alors vous avez probablement de plus gros problèmes à vous soucier que d'utiliser ou non les régions. Personnellement, je n'ai jamais besoin de les utiliser, et lorsque je travaille sur le code de quelqu'un d'autre, je trouve que je dois toujours les ouvrir de toute façon, alors pourquoi s'embêter?


1
+1 - Je suis surpris que cela n'ait pas été mentionné plus en évidence. Le principe de cohésion s'applique également à la façon dont vous disposez votre code, et le regroupement par modificateur d'accès est (le plus souvent) contre-productif.
Daniel B

0

J'organise actuellement des cours comme celui-ci:

class types
constructors
destructor
accessors
methods
properties (where properties are present in the language)
member variables

puis préfixez le niveau d'accès à chaque déclaration (en quelque sorte, parfois regrouper par accès). J'avais l'habitude de faire un regroupement de haut niveau par accès, mais à un moment donné, je ne sais pas quand, cela n'a pas fonctionné aussi bien que ci-dessus. Par exemple, en C ++ / CLI (que je suis obligé d'utiliser pour le moment :-(), vous pouvez le faire, ce qui perturbe le regroupement par accès:

public: property int SomeProperty
{
private: void set (int value) { ... }
public: int get () { ... }
}

Que sont les "membres" en bas? Pour moi, c'est un terme fourre-tout pour toutes les pièces d'une classe.
Mason Wheeler

@Mason: devrait être des "variables membres" pour éviter toute confusion.
Skizz

Je n'arrive vraiment pas à regrouper les choses par type comme ça. Quelle est vraiment la différence entre une méthode et une propriété? Je n'ai jamais cherché une seule fois les propriétés d'une classe, je vais cependant chercher du code logique, que ce soit des propriétés, des méthodes, etc.
Ed S.

0

Réponse lunatique marginale: je ne le fais pas, du moins en ce qui concerne C #. Entre Visual Studio et R #, je peux comme par magie naviguer vers n'importe quel membre ou implémentation, il n'y a donc aucun intérêt à être obsédé par ce genre de choses; commencez simplement à taper où se trouve le curseur.


0

Comme Wyatt et quelques autres réponses, j'évite aussi généralement l'utilisation des régions. Les régions ont un but; pour masquer le code que vous ne voulez pas avoir à regarder. Si vous avez beaucoup de code dans une classe que vous ne voulez pas avoir à regarder, et donc vous avez besoin de beaucoup de régions pour vous permettre de réduire ledit code, alors vous avez probablement trop de code dans la classe. ReSharper ne respecte pas les régions lorsqu'il décide où placer le nouveau code, sauf s'il a créé la région (ce qu'il fait pour les implémentations d'interface).

La seule utilisation des régions que je trouve acceptable est de cacher le code "inévitablement laid"; code qui traite des détails d'implémentation spécifiques qui ne peuvent pas être bien architecturés en interne aux normes actuelles. Il s'agit généralement d'un code ésotérique avancé qui ne devrait généralement pas être gâché par le programmeur junior moyen une fois écrit. Ce sont des choses comme:

  • Certaines implémentations d'interface intégrées (IDisposable, IConvertible, parfois IEnumerable ou IComparable car elles nécessitent des implémentations génériques et non génériques)
  • Externes P / Invoke intégrés et structures associées.
  • Finaliseurs / destructeurs (va généralement avec IDisposable)
  • Accroche à la mémoire non gérée / pointeurs / code "dangereux".
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.