Best practice per l'utilizzo degli spazi dei nomi in C ++ [chiuso]

35

Ho letto il codice pulito di Uncle Bob alcuni mesi fa, e ha avuto un profondo impatto sul modo in cui scrivo codice. Anche se sembrava che stesse ripetendo cose che ogni programmatore dovrebbe sapere, metterle tutte insieme e metterle in pratica produce un codice molto più pulito. In particolare, ho trovato la suddivisione di grandi funzioni in molte piccole funzioni e la suddivisione di classi grandi in molte classi minuscole per essere incredibilmente utile.

Ora per la domanda. Gli esempi del libro sono tutti in Java, mentre ho lavorato in C ++ negli ultimi anni. In che modo le idee in Pulisci codice si estendono all'uso di spazi dei nomi, che non esistono in Java? (Sì, so dei pacchetti Java, ma non è proprio lo stesso.)

Ha senso applicare l'idea di creare molte piccole entità, ognuna con una responsabilità chiaramente definita, in namespace? Un piccolo gruppo di classi correlate dovrebbe sempre essere racchiuso in uno spazio dei nomi? È questo il modo di gestire la complessità di avere molte piccole classi o il costo di gestire molti spazi dei nomi è proibitivo?

Modifica: la mia domanda ha una risposta in questa voce di Wikipedia sui principi del pacchetto .

    
posta Dima 21.02.2011 - 14:02
fonte

5 risposte

20

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

    
risposta data 21.02.2011 - 15:31
fonte
7

Dovresti avere uno spazio dei nomi principale per tutto il tuo codice. Questo lo distingue dal codice esterno per quanto riguarda gli spazi dei nomi.

All'interno del tuo spazio dei nomi principale, a seconda delle dimensioni e della complessità, puoi aprire sotto namespace. È qui che i nomi indicano chiaramente qualcosa all'interno di un contesto e gli stessi nomi potrebbero essere utilizzati in un contesto diverso.

In particolare se hai un nome generico come FileInfo che significa qualcosa di particolare in un contesto, mettilo in un namespace.

Puoi anche usare una classe per questo, sebbene una classe non sia estensibile, quindi non puoi aggiungere nuove dichiarazioni alla classe senza modificare la sua intestazione.

    
risposta data 21.02.2011 - 14:39
fonte
3

Gli spazi dei nomi non sono un concetto di modulo, quindi li userei solo dove potrebbero verificarsi conflitti di nome.

    
risposta data 21.02.2011 - 14:09
fonte
1

Java ha spazi dei nomi, non sono proprio così chiamati. In javax.swing.* javax è uno spazio dei nomi e swing è un sotto-spazio dei nomi. Non ho letto il libro per sapere cosa dice sui pacchetti java, ma gli stessi principi si applicherebbero più o meno direttamente ai namespace in qualsiasi lingua.

Una buona euristica è che usi uno spazio dei nomi quando ti trovi a voler digitare lo stesso prefisso per le classi più e più volte. Ad esempio, di recente ho scritto alcune classi chiamate OmciAttribute, OmciAlarm, OmciMe, ecc. E ho realizzato che avevo bisogno di rompere Omci nel suo spazio dei nomi.

    
risposta data 21.02.2011 - 15:45
fonte
1

Mi piacciono gli spazi dei nomi profondi (che di solito significa tre livelli).

  • Ho il nome della società.
  • app / util / lib / etc
  • Nome del progetto / o pacchetto appropriato

A seconda della situazione, potrei avere un altro livello

  • dettagli (dettagli specifici dell'implementazione della piattaforma)
  • utils (oggetto utility che non è stato ancora spostato in utilità generale).
  • tutto ciò di cui ho bisogno.
risposta data 21.02.2011 - 19:52
fonte

Leggi altre domande sui tag