Comment éviter les noms généraux des classes abstraites?

10

En général, il est bon d'éviter les mots comme "handle" ou "processus" dans le cadre des noms de routine et des noms de classe, sauf si vous traitez (par exemple) des descripteurs de fichiers ou (par exemple) des processus Unix. Cependant, les classes abstraites ne savent souvent pas vraiment ce qu'elles vont faire avec autre chose que, disons, le traiter. Dans ma situation actuelle, j'ai un "EmailProcessor" qui se connecte à la boîte de réception d'un utilisateur et en traite les messages. Je ne sais pas vraiment comment donner à ce nom un nom plus précis, même si j'ai remarqué que le style suivant se pose:

  • mieux traiter les classes dérivées comme des clients et nommer la classe de base par la partie des fonctionnalités qu'elle implémente? Lui donne plus de sens mais violera is-a. Par exemple, EmailAcquirer serait un nom raisonnable car il acquiert pour la classe dérivée, mais la classe dérivée ne sera acquise pour personne.
  • Ou juste un nom vraiment vague car qui sait ce que feront les classes dérivées. Cependant, "Processor" est encore trop général car il effectue de nombreuses opérations pertinentes, comme la connexion et l'utilisation d'IMAP.

Un moyen de sortir de ce dilemme?

Le problème est plus évident pour les méthodes abstraites, dans lesquelles vous ne pouvez pas vraiment répondre à la question "qu'est-ce que cela fait?" parce que la réponse est simplement «tout ce que le client veut».

Djechlin
la source
Avez-vous une source (et un certain contexte) pour cette affirmation "en général"? En outre, une règle de dénomination supplémentaire pour la liste - ne perdez pas de temps à chercher un nom parfait qui n'existe probablement pas. En cas de doute, donnez-lui le meilleur nom possible, ajoutez une description plus longue en tant que commentaire où elle est définie si nécessaire, mais vous pouvez toujours refactoriser plus tard si quelqu'un n'aime pas votre choix ou si le nom parfait vous vient soudainement à l'esprit lorsque vous '' re faire autre chose.
Steve314
3
@ Steve314 - oui, Steve McConnell, Code Complete, 1re éd., Chapitre 4 ou 5 sur les routines. Discussion approfondie sur la dénomination dans ces chapitres, concluant essentiellement si vous n'avez pas un bon nom, vous n'avez probablement pas une bonne fonction.
djechlin
ne pas trouver un bon nom peut sembler un mauvais signe, mais OMI, vous devez savoir si la fonction est mauvaise en fonction de la fonction elle-même. Refactoriser juste parce que la langue anglaise n'a pas été conçue sur mesure pour votre projet est un peu idiot. Non, ce n'est pas un problème quotidien, mais vous avez déjà décidé que vous aviez un problème.
Steve314
1
@ Steve314 La programmation consiste entièrement à gérer la complexité, et si votre cerveau ne peut pas trouver un mot pour quelque chose, il y a de fortes chances qu'il ne puisse pas gérer la complexité de celui-ci lorsqu'il doit faire des choses comme l'utiliser dans de plus grandes phrases ou dans le cadre de systèmes plus importants. Ce n'est en fait pas une affirmation audacieuse de dire que l'incapacité à trouver un bon nom est une grande cause de pause. Mais ceci est discuté en détail dans McConnell, je recommanderais de lire ces deux chapitres au moins bien que le livre entier vaille la peine d'être lu de couverture en couverture.
djechlin
les revendications dans Code Complete ne doivent pas nécessairement être approuvées. Je suis conscient de la réputation des livres, mais je suis aussi au courant de ce . D'ailleurs, je gère parfaitement la complexité depuis des lustres - des erreurs se produisent, bien sûr, mais quand les choses tournent mal, parfois le problème est une fonction si simple qu'elle ne peut évidemment pas se tromper, mais l'est quand même .
Steve314

Réponses:

10

Le problème n'est pas le nom, mais que vous mettez trop dans une classe.

Dans votre exemple de classe, certaines parties sont très concrètes (comment les mails seront obtenus). Les autres parties sont très abstraites (ce que vous ferez avec les mails).

Mieux vaut le faire avec des classes séparées qu'avec l'héritage.

Je suggère:

  • un MessageIterator abstrait, sous-classé par un POPMailBoxDownloader

  • une autre classe qui possède un POPMailBoxDownloader et fait quelque chose avec les messages.

Kris Van Bael
la source
Cela sonne exactement. Il semble que si vous vous trouvez en nommant quelque chose "processEvent" ou une classe "MessageProcessor", il y a de fortes chances que vous auriez pu concevoir une composition plutôt qu'une dérivation. Dans ce cas, c'est un compromis, en tant que mainteneurs, la flexibilité peut être utile, mais un client serait ennuyé en se demandant exactement ce que fait chaque fonction (plus que le mainteneur).
djechlin
6

Si je ne trouve pas un bon nom pour une classe, j'écris une documentation de code en ligne pour la classe. Il décrit le but de la classe en un seul parfum. Habituellement, je peux dériver un bon nom pour la classe de cette description. Ceci est également utile pour les classes abstraites.

Si la description de la classe est "Se connecte à la boîte de réception d'un utilisateur et en traite les messages", je suggère "InboxProcessor" comme nom de classe. Si une classe dérivée a "Se connecte à la boîte de réception d'un utilisateur et déplace le courrier indésirable dans un dossier de spam" comme description, je choisirais "InboxSpamMover" comme nom.

Je ne vois pas de problème lors de l'utilisation de noms génériques comme "processeur" si cela reflète le but générique d'une classe abstraite.

Si vous rencontrez des problèmes pour décrire le but d'une classe en une ou deux senteurs, vous pouvez avoir un problème de conception. Peut-être que la classe en fait trop et viole le principe de responsabilité unique . Cela s'applique également aux classes abstraites.

Theo Lenndorff
la source
2

Pour paraphraser Frank Zappa, c'est ce qu'il est et devrait être nommé ainsi. Votre exemple ne suffit pas à approfondir le type de traitement en cours. Est-ce un EmailToTroubleTicketProcessor, un EmailGrammarCorrectorou un EmailSpamDetector?

Le problème est plus évident pour les méthodes abstraites, dans lesquelles vous ne pouvez pas vraiment répondre à la question "qu'est-ce que cela fait?" parce que la réponse est simplement «tout ce que le client veut».

Ce n'est pas tout à fait vrai; la question à laquelle vous ne pouvez pas répondre pour quelque chose d'abstrait est " comment fait-elle ce qu'elle fait?" parce que c'est spécifique à l'implémentation. Si une EmailSenderclasse a une DeliveryStatus deliver(Email e)méthode, il existe un contrat implicite selon lequel une implémentation prendra un e-mail, tentera de le livrer et retournera un état sur la façon dont cela s'est passé. Peu importe qu'il se connecte à un serveur SMTP ou l'imprime pour être attaché à un pigeon voyageur tant que l'implémentation fait ce qui a été promis. Les résumés quantifient simplement cette promesse afin qu'une implémentation puisse dire "oui, je fais ça".

Blrfl
la source
Qu'en est-il lorsque la fonction de fin est en quelque sorte terminale, donc la classe abstraite dit "et ici, faites ce que vous voulez avec elle?" par exemple, la méthode n'a pas accès à l'état, au type de retour vide, à la non-projection.
djechlin
C'est toujours la même chose. Même si votre méthode est void doWhatYouDoWith(Email e), vous pouvez toujours appeler la classe an EmailDisposer, qui est suffisamment spécifique pour dire ce qu'elle fait mais assez générale pour savoir comment procéder. Bien que je pense que @KrisVanBael l'a bien compris: si vous avez eu recours à quelque chose d'aussi ambigu, il peut y en avoir trop sous un même toit.
Blrfl
0

Pensez à pourquoi il est mauvais d'utiliser de tels mots. Sont-ils descriptifs? Quels sont les mots pour décrire les classes? EmailBaseClass? Cela pourrait-il être plus descriptif que par exemple EmailManager ou quelque chose de similaire? La clé est d'avoir un aperçu de la classe en question, alors trouvez les verbes ou les noms appropriés. Traitez votre code comme s'il s'agissait de poésie.

zxcdw
la source
"EmailBaseClass" serait comme nommer int age"ageInteger", encore pire, car je m'attendrais à en tirer des e-mails en texte brut, des e-mails MIME, etc. Pas besoin de décrire ce qui est précédé du mot abstracten premier lieu (c'est Java). Avez-vous un aperçu particulier de la partie de base de cette classe? Et plus de perspicacité ne résout toujours pas le problème de nommer quelque chose qui va traverser une relation est-une, je peux avoir quelque chose de trop vague ou trop général, je ne vois pas d'issue à moins que si j'avais plus de perspicacité pour avoir plus de perspicacité.
djechlin
@djechlin - il y a de rares cas où ageIntegerou quelque chose comme ça est réellement approprié. La notation hongroise est une version abrégée d'un contexte où cela s'est produit beaucoup. Certes, il y a des moments où vous pouvez avoir besoin de quelque chose dans le sens ageNumericet ageStringdans la même portée, avec une indication du type dans le nom étant le moyen le plus simple et le plus clair de lever l'ambiguïté.
Steve314
@djechlin Personnellement, je trouve qu'il est plus facile de travailler avec du code auquel je peux simplement jeter un coup d'œil pour mieux comprendre. Autrement dit, les noms me disent avec quoi je travaille. Pas besoin de savoir s'il systemControllers'agit d'une classe de base abstraite ou d'une feuille dans une énorme hiérarchie. Bien sûr, cela peut être corrigé avec IDE (comme je suppose que c'est le cas avec la plupart des développements Java?) Qui peut immédiatement informer l'utilisateur du contenu et de la structure de la classe, donc les noms perspicaces ne peuvent pas être justifiés de la même manière.
zxcdw