Méthodes conseillées pour l'utilisation des espaces de noms en C ++ [fermé]

38

J'ai lu le code propre d' Oncle Bob il y a quelques mois et cela a eu un impact profond sur la façon dont j'écris le code. Même s'il semblait qu'il répétait des choses que tout programmeur devrait savoir, les mettre ensemble et les mettre en pratique donne un code beaucoup plus propre. En particulier, j'ai trouvé que diviser de grandes fonctions en plusieurs petites fonctions et diviser de grandes classes en plusieurs petites classes était extrêmement utile.

Maintenant pour la question. Les exemples du livre sont tous en Java, alors que je travaille en C ++ depuis plusieurs années. Comment les idées de Clean Code pourraient-elles s'étendre à l'utilisation d'espaces de noms, qui n'existent pas en Java? (Oui, je connais les packages Java, mais ce n'est pas vraiment pareil.)

Est-il judicieux d'appliquer l'idée de créer de nombreuses petites entités, chacune avec une responsabilité clairement définie, aux espaces de noms? Un petit groupe de classes liées doit-il toujours être enveloppé dans un espace de noms? Est-ce le moyen de gérer la complexité d'avoir beaucoup de classes minuscules ou le coût de la gestion de nombreux espaces de noms serait-il prohibitif?

Edit: Cette entrée Wikipedia contient des réponses sur les principes de package .

Dima
la source
7
Un autre exemple de bonne question d’un développeur réel est clos . Si ce n'est pas le site stackexchange à poser sur les meilleures pratiques des développeurs, qu'est-ce que c'est?
Sam Goldberg
@SamGoldberg: ça va mieux. J'ai trouvé une bonne réponse à cette question ici: en.wikipedia.org/wiki/Package_Principles . J'ai posté cette réponse et un modérateur l'a supprimée, car j'ai simplement posté le lien et je n'ai pas eu le temps de copier / coller le contenu.
Dima
1
Je pense que ma seule critique de la question serait, au lieu de poser plusieurs questions à la fin, essayez de la résumer en une seule question, par exemple "quel devrait être le critère pour déterminer si les éléments doivent se trouver dans le même espace de noms ou dans des espaces de noms différents?" ".
Sam Goldberg

Réponses:

22

(Je n'ai pas lu Clean Code et je ne connais pas beaucoup Java.)

Est-il judicieux d'appliquer l'idée de créer de nombreuses petites entités, chacune avec une responsabilité clairement définie, aux espaces de noms?

Oui, comme pour le refactoring dans plusieurs classes et plusieurs fonctions.

Un petit groupe de classes liées doit-il toujours être enveloppé dans un espace de noms?

Sans répondre réellement: oui, vous devriez au moins utiliser un espace de noms de premier niveau. Cela peut être basé sur le projet, l'organisation, ou ce que vous voulez, mais l'utilisation de quelques noms globaux réduira les conflits de noms. Un seul espace de noms pour regrouper tout le reste ne contient qu'un seul nom global. (Sauf les fonctions externes "C", mais cela est dû à l'interopérabilité du C et n'affecte que les autres fonctions externes "C".)

Un petit groupe de classes liées doit-il être enveloppé dans un espace de noms qui leur est dédié? Probablement. Surtout si vous utilisez un préfixe commun pour ces classes - FrobberThing, FrobberThang, FrobberDoohickey - vous devriez envisager un espace de noms - frobber :: Thing, etc. Ce serait toujours sous votre espace de noms racine ou un autre espace de noms s'ils font partie d'un projet plus grand.

Est-ce le moyen de gérer la complexité d'avoir beaucoup de classes minuscules ou le coût de la gestion de nombreux espaces de noms serait-il prohibitif?

En prenant l'exemple ci-dessus de noms préfixés, il n'est pas plus difficile de gérer frobber :: Thing que FrobberThing. Cela peut même être plus facile avec certains outils, tels que la documentation et la complétion de code. Il existe une différence avec ADL, mais cela peut jouer en votre faveur: moins de noms dans les espaces de noms associés rendent ADL plus facile à comprendre, et vous pouvez utiliser des déclarations pour injecter des noms spécifiques dans un ou plusieurs espaces de noms.

Les alias d'espaces de noms vous permettent d'utiliser un nom plus court pour un espace de noms plus long dans un contexte spécifique, ce qui facilite encore une utilisation:

void f() {
  namespace CWVLN = Company_with_very_long_name;  // Example from the standard.
  // In this scope, use CWVLN::name instead of Company_with_very_long_name::name.
  namespace fs = boost::filesystem;  // Commonly used.
}

Considérez Boost, qui ne possède qu'un seul espace de noms racine, boost, puis de nombreux espaces de sous-noms - boost :: asio, boost :: io, boost :: système de fichiers, boost :: tuples, etc. - pour différentes bibliothèques. Certains noms sont "promus" dans l'espace de noms racine:

Toutes les définitions sont dans namespace :: boost :: tuples, mais les noms les plus courants sont levés dans namespace :: boost à l'aide de déclarations. Ces noms sont: tuple, make_tuple, tie et get. De plus, ref et cref sont définis directement sous l’espace de noms :: boost.

La plus grande différence par rapport aux langues avec de "vrais" modules réside dans le fait qu’il est courant d’utiliser une structure plus plate, ce qui se produit principalement parce que c’est ainsi que cela fonctionne à moins que vous ne preniez un effort supplémentaire et spécifique pour définir des noms imbriqués.

Fred Nurk
la source
+1 @Fred Nurk pour l’analyse complète au lieu d’une réponse à une ligne. Vous n'êtes pas obligé de lire le livre pour savoir de quoi parle la question. Ce fil de commentaire expose les concepts et les différences qu'un programmeur C ++ et Java pourrait avoir sur ce livre. Commentaire de Clean Code sur Amazon
Marlon
8

Vous devriez avoir un espace de noms principal pour tout votre code. Cela le distingue du code externe en ce qui concerne les espaces de noms.

Dans votre espace de noms principal, en fonction de la taille et de la complexité, vous pouvez ouvrir des sous-espaces de noms. C'est là que les noms signifient clairement quelque chose dans un contexte et que les mêmes noms peuvent être utilisés dans un contexte différent.

En particulier, si vous avez un nom générique, comme FileInfo, qui signifie quelque chose de particulier dans un contexte, placez-le dans un espace de noms.

Vous pouvez également utiliser une classe pour cela, bien qu'une classe ne soit pas extensible, vous ne pouvez donc pas ajouter de nouvelles déclarations à la classe sans modifier son en-tête.

Vache à lait
la source
3

Les espaces de noms n'est pas un concept de module, je ne les utiliserais donc qu'en cas de conflit de noms.

Brainlag
la source
4
Pas sûr de ce que vous voulez dire. Pourquoi un ensemble de classes liées encapsulées dans un espace de noms ne serait-il pas un module?
Dima
Il n'y a pas de restrictions dans l'espace de noms. Dans un module, vous pouvez dire qu'une classe, une fonction ou une variable donnée ne peut être accédée que depuis l'intérieur du module. Dans un espace de noms, ce n'est pas possible, il s'agit simplement d'un préfixe du nom.
Brainlag
3
On dirait que nous ne sommes pas d'accord sur la définition d'un module . Pour moi, tout ce qui regroupe des entités liées et qui porte un nom descriptif est un module, qu’il soit ou non saturé, il fournit une encapsulation.
Dima
3
La restriction d'accès est orthogonale aux modules. En fait, vous avez des systèmes performants comme Python qui ressemblent nettement plus à des modules que les espaces de noms C ++, mais n'imposent aucune restriction d'accès.
Fred Nurk
Je pense que c'est l'une des meilleures pratiques répertoriées dans les livres de Scott Meyer
Raphael, le
1

Java a des espaces de noms, ils ne s'appellent pas vraiment comme ça. In javax.swing.* javaxest un espace de noms et swingest un sous-espace de noms. Je n'ai pas lu le livre pour savoir ce qu'il dit sur les paquets java, mais les mêmes principes s'appliqueraient assez directement aux espaces de noms dans toutes les langues.

Une bonne heuristique consiste à utiliser un espace de noms lorsque vous souhaitez taper le même préfixe pour les classes, encore et encore. Par exemple, j'ai récemment écrit des classes appelées OmciAttribute, OmciAlarm, OmciMe, etc.

Karl Bielefeldt
la source
1

J'aime les espaces de noms profonds (ce qui signifie généralement trois niveaux).

  • J'ai le nom de l'entreprise.
  • app / util / lib / etc
  • Nom du projet / ou paquet selon le cas

Selon la situation, il se peut que j'aie encore un niveau

  • details (détails d'implémentation spécifiques à la plate-forme)
  • utils (objet utilitaire qui n’a pas encore été déplacé vers l’utilitaire général).
  • tout ce dont j'ai besoin.
Martin York
la source