includere intestazioni all'interno di uno spazio dei nomi è sempre una cattiva idea?

1

Le risposte in questo post arrivano molto strongmente contro l'inclusione di intestazioni all'interno di uno spazio dei nomi e Doxygen è confuso se ciò è fatto (il che suggerisce che il suo team non ha considerato tale utilizzo). Vorrei chiedere se includere intestazioni all'interno di uno spazio dei nomi è giustificato nel seguente caso.

Sto sviluppando un framework di sola intestazione per esplorare una determinata famiglia di algoritmi. Una volta rilasciato, le estensioni sotto forma di file di intestazione saranno fornite dai membri della comunità di ricerca. Un file di intestazione contribuito può implementare un nuovo algoritmo o una politica di un algoritmo esistente o qualcos'altro. A seconda di ciò che la nuova intestazione implementa, verrà inserito nella cartella pertinente.

Gli spazi dei nomi nel framework imitano la struttura delle cartelle. Quindi, considera una cartella A/B/ del framework e supponi che le intestazioni x.h , y.h e z.h siano in quella cartella. Senza includere le intestazioni all'interno degli spazi dei nomi, il file x.h sarà simile al seguente:

namespace N { // The namespace in which the whole framework resides
namespace A { // Folder A/
namespace B { // Folder A/B/
namespace X { // The facilities provided by x.h are related
    ... // Definition of the facilities
}
}
}
}

I file y.h e z.h inizieranno anche con l'apertura di quattro spazi dei nomi. Inoltre, se un utente contribuisce con w.h a questa cartella, dovrà ricordarsi di aprire gli spazi dei nomi N , A e B per non interrompere la progettazione.

Nel design alternativo (e meglio a mio avviso), ogni cartella ha un file headers.h come segue.

A/B/headers.h è:

namespace B {
    #include "x.h"
    #include "y.h"
    #include "z.h"
}

A/headers.h è:

namespace A {
    #include "B/headers.h"
    ... // includes headers.h of other sub-folders of A/
}

Allora x.h assomiglia a questo

namespace X { // The facilities provided by x.h are related
    ...
}

Esistono validi motivi per non utilizzare questo design alternativo?

Tieni presente che la libreria deve essere inclusa nel .cpp nel suo insieme (cioè è incluso il header.h di primo livello). Ciò non comporta tempi di compilazione lunghi, poiché la libreria è strongmente basata su modelli e solo pochi modelli (ad esempio l'algoritmo in esame, le sue politiche e le relative funzionalità) vengono istanziati. Quindi, non mi preoccupo della possibilità di includere erroneamente un'intestazione individuale senza il suo contesto di namespace.

Non ci sono dipendenze in basso (cioè foglia), dove si trovano tutte le intestazioni che implementano le strutture effettive (come x.h , y.h e z.h nell'esempio). Pertanto, un headers.h al livello inferiore (come A/B/headers.h nell'esempio) può elencare le intestazioni incluse in ordine alfabetico. Un headers.h a un livello non inferiore (come A/headers.h nell'esempio) include headers.h da ogni sottocartella nell'ordine che rispetta le dipendenze. Tale ordine è fisso (ad esempio tutte le politiche sono incluse prima di tutti gli algoritmi) e gli utenti non dovranno occuparsene.

    
posta AlwaysLearning 03.11.2016 - 07:39
fonte

2 risposte

6

perché non è una buona idea:

  • La conoscenza del tuo design è ora parzialmente memorizzata nella struttura delle directory. Questo non è un buon posto per la logica di progettazione da inserire.
    • Cosa succede se qualcuno riceve il file x.h? Non saranno in grado di distinguere dal codice stesso quale sia la sua classificazione, perché solo con la directory completa e tutti i file qualcuno può dire che x.h è posizionato correttamente all'interno di N - > A - > B
    • Potrebbero esserci degli errori nel mettere accidentalmente qualcosa nel posto sbagliato.
    • Logicamente, ti piacerebbe qualcuno che ha solo il permesso di usare il genitore per poterlo estendere, ma ora puoi estendere solo qualcosa che hai il permesso di modificarlo.
  • Non puoi aggiungere un nuovo elemento semplicemente aggiungendo una nuova intestazione. Invece, devi anche aggiornare il file "headers.h" appropriato, portando ad ulteriori complessità e potenziali conflitti quando aggiungi nuove cose.
  • Stai prendendo una decisione sul design che l'intero file di intestazione deve essere incluso per sempre. Nella tua domanda, tieni presente che questo non è un problema al momento. Ma sei proprio sicuro che non ci sarà mai, mai un futuro nel futuro in cui qualcuno vorrà includere singoli header?
  • Stai prendendo una decisione progettuale che non può mai essere interdipendenza significativa anche in questo caso non è vero ora, ma sei davvero così sicuro che non sarà mai vero?
  • Stai facendo qualcosa di strano che è di per sé un aspetto negativo, dal momento che tutti coloro che utilizzano questo codice devono prendersi del tempo per imparare il tuo design unico, che nessun altro usa.

Eviterei questo. Inoltre, è possibile che non si debbano utilizzare spazi dei nomi nidificati ?

    
risposta data 03.11.2016 - 12:01
fonte
2

Come regola generale, non includerei mai un file all'interno di un namespace per i motivi che dan1111 ha fornito nella sua risposta. Se lo scopo dell'intestazione è quello di condividere il codice, stai costringendo gli utenti del tuo codice a conoscere i dettagli sulla struttura del codice e a scrivere correttamente lo spazio dei nomi corretto prima di includere il file.

Nel caso di una singola libreria di intestazione, puoi farla franca in qualche modo più facilmente, ma significa comunque che devi essere coerente con i tuoi spazi dei nomi ogni volta che includi quel file.

L'unico caso che posso vedere come accettabile è se l'intestazione è puramente per macro di preprocessore e si vuole limitare il loro ambito. Qualcosa come:

namespace io
{
    enum class file_permissions
    {
        none = 0,
        execute = 1,
        write = 2,
        read = 4
    };

#include "enum_macros.hpp"
    GENERATE_ENUM_BITWISE_OPERATORS(file_permissions);
#include "enum_macros_cleanup.hpp"
}

Qui l'idea è di ottenere i benefici di enumerazioni strongmente tipizzate, consentendo agli utenti di combinare i flag di autorizzazione, il tutto senza inquinare lo spazio dei nomi globale con le macro più del necessario. Anche qui mi sento un po 'in errore e generalmente preferisco attribuire ai macro nomi lunghi in maiuscolo che è improbabile che possano entrare in conflitto con qualcos'altro (o evitare completamente la macro).

    
risposta data 04.11.2016 - 20:39
fonte

Leggi altre domande sui tag