Quelle est la meilleure approche pour nommer les classes?

92

Il est notoirement difficile de trouver de bons noms précis pour les classes. Bien fait, il rend le code plus auto-documenté et fournit un vocabulaire pour raisonner sur le code à un niveau d'abstraction plus élevé.

Les classes qui implémentent un modèle de conception particulier peuvent recevoir un nom basé sur le nom de modèle bien connu (par exemple FooFactory, FooFacade), et les classes qui modélisent directement les concepts de domaine peuvent prendre leurs noms du domaine du problème, mais qu'en est-il des autres classes? Y a-t-il quelque chose comme le thésaurus d'un programmeur vers lequel je peux me tourner lorsque je manque d'inspiration et que je veux éviter d'utiliser des noms de classe génériques (comme FooHandler, FooProcessor, FooUtils et FooManager)?

Henri
la source
6
Ceci est une excellente question! La fermeture est à mon humble avis injustifiée, mieux serait de migrer le site des programmeurs.
Timofey
1
Je suis d'accord, devrait être rouvert ou déplacé
ftl
J'ai vu beaucoup de ces excellentes questions "fermées par casperOne". Peut-être pourrait-il servir de suppresseur sur Wikipedia?
Perlator

Réponses:

59

Je vais citer quelques passages de Implementation Patterns de Kent Beck:

Nom de superclasse simple

"[...] Les noms doivent être courts et percutants. Cependant, rendre les noms précis semble parfois exiger plusieurs mots. Un moyen de sortir de ce dilemme est de choisir une métaphore forte pour le calcul. Avec une métaphore en tête, même Les mots uniques apportent avec eux un riche réseau d'associations, de connexions et d'implications. Par exemple, dans le cadre de dessin HotDraw, mon prénom pour un objet dans un dessin était DrawingObject . Ward Cunningham est venu avec la métaphore typographique: un dessin est comme une page imprimée et mise en page. Les éléments graphiques sur une page sont des figures, donc la classe est devenue Figure . Dans le contexte de la métaphore, Figure est à la fois plus courte, plus riche et plus précise que DrawingObject . "

Nom de la sous-classe qualifiée

"Les noms des sous-classes ont deux tâches. Ils ont besoin de communiquer à quelle classe ils ressemblent et en quoi ils sont différents. [...] Contrairement aux noms à la racine des hiérarchies, les noms de sous-classes ne sont pas utilisés presque aussi souvent dans les conversations, afin qu'ils puissent être expressifs au prix d'être concis. [...]

Donnez aux sous-classes qui servent de racines aux hiérarchies leurs propres noms simples. Par exemple, HotDraw a une classe Handle qui présente les opérations d'édition de figure lorsqu'une figure est sélectionnée. Il s'appelle simplement Handle malgré l'extension de la figure . Il existe toute une famille de poignées et elles ont le plus approprié des noms tels que StretchyHandle et TransparencyHandle . Étant donné que Handle est la racine de sa propre hiérarchie, il mérite un simple nom de superclasse plus qu'un nom de sous-classe qualifié.

Les hiérarchies à plusieurs niveaux constituent un autre problème dans la dénomination des sous-classes. [...] Plutôt que d'ajouter aveuglément les modificateurs à la superclasse immédiate, pensez au nom du point de vue du lecteur. À quelle classe a-t-il besoin pour connaître cette classe? Utilisez cette superclasse comme base pour le nom de la sous-classe. "

Interface

Deux styles d'interfaces de dénomination dépendent de la façon dont vous envisagez les interfaces. Les interfaces en tant que classes sans implémentations doivent être nommées comme s'il s'agissait de classes ( nom de superclasse simple , nom de sous-classe qualifiée ). Un problème avec ce style de dénomination est que les bons noms sont utilisés avant que vous n'arriviez à nommer des classes. Une interface appelée File a besoin d'une classe d'implémentation appelée quelque chose comme ActualFile , ConcreteFile ou (beurk!) FileImpl(à la fois un suffixe et une abréviation). En général, il est important de savoir s'il s'agit d'un objet concret ou abstrait, que l'objet abstrait soit implémenté en tant qu'interface ou en superclasse est moins important. Le report de la distinction entre les interfaces et les superclasses est bien> pris en charge par ce style de dénomination, vous laissant libre de changer d'avis plus tard si cela devient nécessaire.

Parfois, nommer des classes concrètes est simplement plus important pour la communication que de cacher l'utilisation des interfaces. Dans ce cas, préfixez les noms d'interface avec «I». Si l'interface s'appelle IFile , la classe peut être simplement appelée File .

Pour une discussion plus détaillée, achetez le livre! Ça en vaut la peine! :)

Marcio Aguiar
la source
1
«Parfois, nommer des classes concrètes est simplement plus important pour la communication que de cacher l'utilisation des interfaces. Dans ce cas, préfixez les noms d'interface avec« I ». Si l'interface s'appelle IFile, la classe peut être simplement appelée File.» C'est tellement drôle, car dans le livre Clean Code de Robert C.Martin, j'ai découvert que nous préférerions nommer les implémentations comme FileImpl, plutôt que nommer l'interface comme IFile, car nous ne voulons pas que le client sache que nous les servons un interface. Et dans le livre ^ il y a des citations du livre auquel vous faites référence :)
Cristian Ciobotea
38

Choisissez toujours MyClassA, MyClassB - Cela permet un joli tri alpha.

Je blague!

C'est une bonne question, et quelque chose que j'ai vécu il n'y a pas si longtemps. Je réorganisais ma base de code au travail et j'avais des problèmes pour savoir où placer quoi et comment l'appeler.

Le vrai problème?

J'avais des cours en faisant trop. Si vous essayez d'adhérer au principe de responsabilité unique , il fera tout tous ensemble beaucoup plus agréable .. Au lieu d'un monolithe PrintHandler classe, vous pouvez décomposer en PageHandler , PageFormatter (et ainsi de suite) et un maître imprimante classe qui rassemble tout cela.

Dans ma réorganisation, cela m'a pris du temps, mais j'ai fini par accumuler beaucoup de code en double, j'ai obtenu ma base de code beaucoup plus logique et j'ai appris énormément quand il s'agit de réfléchir avant de lancer une méthode supplémentaire dans une classe: D

Je ne recommanderais cependant pas de mettre des choses comme des noms de motifs dans le nom de la classe. L'interface des classes devrait rendre cela évident (comme cacher le constructeur d'un singleton). Il n'y a rien de mal avec le nom générique, si la classe sert un objectif générique.

Bonne chance!

Rob Cooper
la source
Acceptez de ne pas mettre de noms de motifs dans le nom de la classe. Et si le modèle change plus tard lorsque l'implémentation change?
thegreendroid
2
Je préfère mettre un nom de motif dans un nom. Pourquoi? Parce que si je dois regarder les détails de l'implémentation (comme le constructeur privé) pour découvrir qu'il s'agit d'un singleton, cela me ralentit en tant que lecteur et en fonction de mon niveau de compétence, je ne comprendrai peut-être pas qu'il s'agit en fait d'une partie de classe du modèle général. Singleton et constructeur privé est un exemple discutable, mais pour des modèles plus compliqués (Visiteur, Adaptateur, etc.), cela devient assez compliqué. Si le modèle change, les chances sont que ces classes n'existeront plus ...
dragan.stepanovic
28

L'excellent discours de Josh Bloch sur la bonne conception d'API contient quelques bons conseils:

  • Les classes doivent faire une chose et bien la faire.
  • Si une classe est difficile à nommer ou à expliquer, elle ne suit probablement pas les conseils du point précédent.
  • Un nom de classe doit communiquer instantanément ce qu'est la classe.
  • Les bons noms conduisent de bons designs.

Si votre problème est de savoir comment nommer les classes internes exposées, vous devriez peut-être les consolider dans une classe plus grande.

Si votre problème est de nommer une classe qui fait beaucoup de choses différentes, vous devriez envisager de la diviser en plusieurs classes.

Si c'est un bon conseil pour une API publique, cela ne peut nuire à aucune autre classe.

Josh Segall
la source
1
lien vidéo sur youtube youtube.com/watch?v=aAb7hSCtvGw
Andrew Harry
12

Si vous êtes coincé avec un nom, il est parfois judicieux de lui donner un nom à moitié sensé avec l'engagement de le réviser plus tard.

Ne soyez pas paralysé par les noms. Oui, les noms sont très importants, mais ils ne sont pas assez importants pour perdre énormément de temps. Si vous ne pouvez pas trouver un bon nom en 10 minutes, passez à autre chose.

Simon Johnson
la source
9

Si un bon nom ne me vient pas à l'esprit, je me demanderais probablement s'il y a un problème plus profond - la classe sert-elle un bon objectif? Si tel est le cas, le nommer devrait être assez simple.

Luke Halliwell
la source
3

Si votre "FooProcessor" traite vraiment les foos, alors n'hésitez pas à lui donner ce nom simplement parce que vous avez déjà un BarProcessor, BazProcessor, etc. En cas de doute, l'évidence est préférable. Les autres développeurs qui doivent lire votre code n'utilisent peut-être pas le même thésaurus que vous.

Cela dit, plus de spécificité ne ferait pas de mal pour cet exemple particulier. «Processus» est un mot assez large. Est-ce vraiment un "FooUpdateProcessor" (qui pourrait devenir "FooUpdater"), par exemple? Vous n'avez pas besoin d'être trop «créatif» sur la dénomination, mais si vous avez écrit le code, vous avez probablement une assez bonne idée de ce qu'il fait et ne fait pas.

Enfin, rappelez-vous que le nom de classe nu n'est pas tout ce que vous et les lecteurs de votre code devez continuer - il y a généralement des espaces de noms en jeu également. Ceux-ci peuvent souvent donner aux lecteurs suffisamment de contexte pour voir clairement à quoi sert réellement votre classe, même si son nom nu est assez générique.

McKenzieG1
la source