(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.