(Non ho letto Clean Code e non conosco molto Java.)
Does it make sense to apply the idea of creating many tiny entities, each with a clearly define responsibility, to namespaces?
Sì, proprio come con il refactoring in più classi e più funzioni.
Should a small group of related classes always be wrapped in a namespace?
Senza rispondere effettivamente: sì, dovresti almeno usare uno spazio dei nomi di primo livello. Questo può essere basato su progetto, organizzazione o qualsiasi altra cosa, ma l'uso di pochi nomi globali ridurrà i conflitti di nome. Un singolo spazio dei nomi per raggruppare tutto il resto sotto di esso introduce solo un nome globale. (Tranne le funzioni "C" esterne, ma ciò è dovuto all'interoperabilità C e riguarda solo altre funzioni "C" esterne.)
Dovrebbe essere racchiuso un piccolo gruppo di classi correlate in uno spazio dei nomi dedicato a loro? Probabilmente. Soprattutto se ti ritrovi a usare un prefisso comune su quelle classi - FrobberThing, FrobberThang, FrobberDoohickey - dovresti considerare uno spazio dei nomi - frobber :: Thing e così via. Questo sarebbe ancora sotto lo spazio dei nomi di root o un altro spazio dei nomi se fanno parte di un progetto più grande.
Is this the way to manage the complexity of having lots of tiny classes, or would the cost of managing lots of namespaces be prohibitive?
Prendendo l'esempio precedente di nomi con prefisso, non è più difficile gestire frobber :: Thing di FrobberThing. Potrebbe anche essere più semplice con alcuni strumenti, come la documentazione e il completamento del codice. C'è una differenza con ADL, ma questo può funzionare a tuo favore: un numero minore di nomi negli spazi dei nomi associati semplifica l'identificazione di ADL e puoi utilizzare le dichiarazioni per inserire nomi specifici in uno spazio dei nomi o in un altro.
Gli alias dello spazio dei nomi ti consentono di utilizzare un nome più breve per uno spazio dei nomi più lungo in un contesto specifico, che di nuovo consente un uso più semplice:
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.
}
Considera Boost, che ha un singolo spazio dei nomi di root, boost e quindi molti sotto-namespace - boost :: asio, boost :: io, boost :: filesystem, boost :: tuples, ecc. - per varie librerie. Alcuni nomi sono "promossi" allo spazio dei nomi di root:
All definitions are in namespace ::boost::tuples, but the most common names are lifted to namespace ::boost with using declarations. These names are: tuple, make_tuple, tie and get. Further, ref and cref are defined directly under the ::boost namespace.
La più grande differenza dalle lingue con i moduli "reali" è quanto sia comune utilizzare una struttura più piatta, cosa che accade soprattutto perché è così che funziona, a meno che tu non faccia uno sforzo specifico per definire i nomi annidati.