Práticas recomendadas para usar namespaces em C ++ [fechado]


38

Eu li o Clean Code do tio Bob há alguns meses e teve um impacto profundo na maneira como escrevo código. Mesmo que parecesse repetir coisas que todo programador deveria saber, reuni-las e colocá-las em prática resulta em um código muito mais limpo. Em particular, achei a divisão de grandes funções em muitas funções minúsculas e a divisão de grandes classes em muitas classes minúsculas para ser incrivelmente útil.

Agora para a pergunta. Os exemplos do livro estão todos em Java, enquanto eu trabalho em C ++ há vários anos. Como as idéias no Código Limpo se estendem ao uso de namespaces, que não existem em Java? (Sim, eu sei sobre os pacotes Java, mas não é o mesmo.)

Faz sentido aplicar a idéia de criar muitas entidades minúsculas, cada uma com uma responsabilidade claramente definida, aos namespaces? Um pequeno grupo de classes relacionadas sempre deve ser agrupado em um espaço para nome? Essa é a maneira de gerenciar a complexidade de ter muitas classes minúsculas ou o custo de gerenciar muitos espaços para nome seria proibitivo?

Edit: Minha pergunta é respondida nesta entrada da Wikipedia sobre Princípios de Pacotes .


7
Outro exemplo de uma boa pergunta para desenvolvedores do mundo real encerrada . Se este não é o site stackexchange para perguntar sobre as práticas recomendadas para desenvolvedores, o que é?
Sam Goldberg

@ SamGoldberg: fica melhor. Encontrei uma boa resposta para esta pergunta aqui: en.wikipedia.org/wiki/Package_Principles . Publiquei esta resposta e um moderador a excluiu, porque simplesmente publiquei o link e não tive tempo para copiar / colar o conteúdo.
Dima

1
Eu acho que minha única crítica da pergunta seria, em vez de fazer várias perguntas no final, tentar resumir em uma única pergunta, por exemplo, "quais devem ser os critérios para determinar se os itens devem estar no mesmo espaço de nome ou em diferentes espaços de nome? "
Sam Goldberg

Respostas:


22

(Eu não li o Código Limpo e não conheço muito Java.)

Faz sentido aplicar a idéia de criar muitas entidades minúsculas, cada uma com uma responsabilidade claramente definida, aos namespaces?

Sim, assim como ocorre com a refatoração em várias classes e múltiplas funções.

Um pequeno grupo de classes relacionadas sempre deve ser agrupado em um espaço para nome?

Sem realmente responder: sim, você deve pelo menos usar um espaço para nome de nível superior. Isso pode ser baseado no projeto, organização ou o que você quiser, mas o uso de poucos nomes globais reduzirá os conflitos de nomes. Um único espaço para nome para agrupar todo o resto nele apenas apresenta um nome global. (Exceto as funções externas "C", mas isso se deve à interoperabilidade C e afeta apenas outras funções externas "C".)

Um pequeno grupo de classes relacionadas deve ser envolvido em um espaço para nome dedicado a elas? Provavelmente. Especialmente se você estiver usando um prefixo comum nessas classes - FrobberThing, FrobberThang, FrobberDoohickey -, considere um espaço para nome - frobber :: Thing e assim por diante. Ainda estaria no seu espaço para nome raiz ou outro espaço para nome se eles fizerem parte de um projeto maior.

Essa é a maneira de gerenciar a complexidade de ter muitas classes minúsculas ou o custo de gerenciar muitos espaços para nome seria proibitivo?

Tomando o exemplo acima de nomes prefixados, não é mais difícil gerenciar frobber :: Thing do que FrobberThing. Pode até ser mais fácil com algumas ferramentas, como documentação e conclusão de código. Há uma diferença com a ADL, mas isso pode funcionar a seu favor: menos nomes nos espaços para nome associados tornam a ADL mais fácil de descobrir e você pode usar declarações para injetar nomes específicos em um espaço para nome ou outro.

Os aliases de namespace permitem que você use um nome mais curto para um namespace mais longo em um contexto específico, o que novamente permite um uso mais fácil:

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

Considere o Boost, que possui um único espaço para nome de raiz, boost e, em seguida, muitos subespaços de nomes - boost :: asio, boost :: io, boost :: sistema de arquivos, boost :: tuplas, etc. - para várias bibliotecas. Alguns nomes são "promovidos" para o espaço para nome raiz:

Todas as definições estão no namespace :: boost :: tuples, mas os nomes mais comuns são elevados para namespace :: boost com o uso de declarações. Estes nomes são: tupla, make_tuple, tie e get. Além disso, ref e cref são definidos diretamente no espaço para nome :: boost.

A maior diferença das linguagens com módulos "reais" é o quão comum é usar uma estrutura mais plana, o que geralmente acontece porque é assim que funciona, a menos que você faça um esforço específico e específico para definir nomes aninhados.


+1 a Fred Nurk para a análise completa, em vez de respostas de uma linha. Você não precisa ler o livro para saber do que se trata a questão. Esse segmento de comentários expõe os conceitos e diferenças que um programador C ++ e Java podem ter neste livro. Comentário sobre o Código Limpo na Amazon
Marlon

8

Você deve ter um espaço para nome mestre para todo o seu código. Isso o diferencia do código externo em relação aos espaços para nome.

No seu espaço para nome principal, dependendo do tamanho e da complexidade, você pode abrir sub-espaços para nome. É aqui que os nomes claramente significam algo dentro de um contexto, e os mesmos nomes podem ser usados ​​em um contexto diferente.

Em particular, se você tiver um nome genérico como FileInfo, que significa algo específico em um contexto, coloque-o em um espaço para nome.

Você também pode usar uma classe para isso, embora uma classe não seja extensível, portanto, você não pode adicionar novas declarações à classe sem modificar seu cabeçalho.


3

Namespaces não é um conceito de módulo, então eu os usaria apenas onde conflitos de nomes pudessem ocorrer.


4
Não tenho certeza do que você quer dizer. Por que um conjunto de classes relacionadas agrupadas em um espaço para nome não seria um módulo?
Dima

Não há restrições no espaço para nome. Em um módulo, você pode dizer que uma determinada classe, função ou variável só pode ser acessada de dentro do módulo. Em um espaço para nome, isso não é possível, é apenas um prefixo para o nome.
Brainlag

3
Parece que discordamos da definição de um módulo . Para mim, qualquer coisa que agrupe entidades relacionadas e tenha um nome descritivo é um módulo, independentemente de murchar ou não, ele fornece encapsulamento.
Dima

3
A restrição de acesso é ortogonal aos módulos. De fato, você tem sistemas bem-sucedidos como o Python, que definitivamente são mais "parecidos com módulos" que os namespaces do C ++, mas não impõem nenhuma restrição de acesso.
21911 Fred Nurk

Creio que esta é uma das melhores práticas listadas nos livros de Scott Meyer
Raphael

1

Java tem namespaces, eles simplesmente não são chamados assim. In javax.swing.* javaxé um espaço para nome e swingé um sub-espaço para nome. Não li o livro para saber o que diz sobre pacotes java, mas os mesmos princípios se aplicariam praticamente diretamente aos namespaces em qualquer idioma.

Uma boa heurística é que você usa um espaço para nome quando deseja digitar o mesmo prefixo para as classes repetidamente. Por exemplo, recentemente escrevi algumas classes chamadas OmciAttribute, OmciAlarm, OmciMe, etc. e percebi que precisava quebrar o Omci em seu próprio espaço de nome.


1

Eu gosto de namespaces profundos (o que geralmente significa três níveis).

  • Eu tenho o nome da empresa.
  • app / util / lib / etc
  • Nome do projeto / ou pacote, conforme apropriado

Dependendo da situação, posso ter mais um nível

  • detalhes (detalhes de implementação específicos da plataforma)
  • utils (objeto de utilitário que ainda não foi movido para o utilitário geral).
  • o que eu precisar.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.