Convenção de nomenclatura de namespace e classe C # para bibliotecas


26

Estou construindo bibliotecas com várias pequenas funções utilitárias em C # e tentando decidir sobre um espaço para nome e convenção de nomenclatura de classe. Minha organização atual é assim:

Company
Company.TextUtils
    public class TextUtils {...}
Company.MathsUtils
    public class MathsUtils {...}
    public class ArbitraryPrecisionNumber {...}
    public class MathsNotation {...}
Company.SIUnits
    public enum SISuffixes {...}
    public class SIUnits {...}

Essa é uma boa maneira de organizar o namespace e as classes, ou existe uma maneira melhor? Em particular, parece que ter o mesmo nome no namespace e no nome da classe (por exemplo, Company.TextUtilsnamespace e TextUtilsclasse) é apenas duplicação e sugere que o esquema poderia ser melhor.



5
As diretrizes da Microsoft recomendam nomes singulares para enums (então, ao SISuffixinvés de SISuffixes), e acho que o singular é melhor. Suffix.A lê como "sufixo A". Além disso, geralmente evito repetir nomes de um nível acima na hierarquia. Ou seja, em vez de Company.SIUnits.SISuffixes, eu me inclinaria para Company.SI.SuffixeCompany.SI.Unit
Harrison Paine

Respostas:


9

É muito difícil determinar a eficácia da sua estratégia de nomenclatura isolada do restante do seu código.

O espaço para nome deve dar uma idéia de onde ele se encaixa na ampla estrutura da sua base de código, e o nome da classe geralmente descreveria que tipo de funcionalidade ou conceito ele representa nessa área.

Advertências à parte, em seu exemplo específico, se é provável que você tenha muito mais classes do tipo 'Util', consideraria colocá-las em Company.Utils.Mathsetc. etc. Dessa forma, se você precisar adicionar funcionalidades comuns a várias áreas de utilidades, você já terá um local natural para isso.


1
Parece uma boa ideia. Pare de se preocupar muito, apenas coloque tudo em "Company.Util".
usuário

30

Há um bom documento que contém muitas regras que você deve seguir para estar alinhado com a Microsoft: Diretrizes de Design da Estrutura .

Uma coisa que você deve alterar: não nomeie classes como seu espaço para nome. Isso levará a misturas de compiladores. Apenas não. Encontre um nome melhor para a classe do espaço para nome.


3
O link direto para as diretrizes de namespaces: msdn.microsoft.com/en-us/library/ms229026(v=vs.110).aspx
Pagotti

1
Por coincidência ou não, também é o mesmo nome de um ótimo livro sobre o assunto, também escrito por pessoas da Microsoft que participaram da criação da estrutura DotNet, com várias observações sobre o que fizeram de certo e onde erraram. Vale a pena ler: amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/…
Machado

@nvoigt, você poderia editar sua resposta para adicionar uma citação no link que nosso amigo Pagotti forneceu: " NÃO use o mesmo nome para um espaço para nome e um tipo nesse espaço para nome. Por exemplo, não use Debug como nome para espaço para nome e também forneça uma classe chamada Debug no mesmo espaço para nome. Vários compiladores exigem que esses tipos sejam totalmente qualificados. "
Machado

2
Advertência: Às vezes, o nome de um produto é melhor do que usar o nome de uma empresa. Estivemos em alguns cenários em que uma empresa foi comprada e tivemos que produzir novos espaços para nome em geral e relançar. Eu acho que isso é muito pequeno, mas queria salientar.
Jon Raynor

1
As diretrizes de design da estrutura da Microsoft são altamente questionáveis, contêm declarações falsas sobre como o .NET funciona e, muitas vezes, não são seguidas pela própria Microsoft. Suas diretrizes de nomenclatura são boas, mas eu evitaria vincular as diretrizes gerais a uma declaração de que "você deve segui-las".
precisa saber é o seguinte

6

Já faz um tempo desde que eu trabalhei com C # ou o ecossistema .NET, então não posso dizer quais são as melhores práticas recomendadas atualmente. Eu recomendaria uma alteração nos seus nomes assim:

Company
Company.Text
    public class TextUtils {...}
Company.Math
    public class MathUtils {...}
    public class ArbitraryPrecisionNumber {...}
    public class MathsNotation {...}
Company.SI
    public enum SISuffixes {...}
    public class SIUnits {...}

O que eu fiz aqui é remover "Utils" dos nomes de namespace. Eu acho que "Util" não deve estar em um espaço para nome, porque o Company.Textespaço para nome poderia um dia conter classes que não são classes de utilitário de texto. O Company.Mathespaço para nome contém o ArbitraryPrecisionNumberque não parece ser um "utilitário".

A remoção de "Util" do espaço para nome também elimina qualquer confusão que possa surgir com duas coisas com o mesmo nome (conforme mencionado na resposta de Robert: /software//a/340440/13156 )

Outra maneira de organizar o código:

Company
Company.Util
    public class TextUtils {...}
    public class MathUtils {...}
Company.Math
    public class ArbitraryPrecisionNumber {...}
    public class MathsNotation {...}
Company.SI
    public enum SISuffixes {...}
    public class SIUnits {...}

Nesse caso, todas as classes de utilitário residem no mesmo espaço para nome. Não há mais Company.Textespaço para nome, pois a única coisa que havia uma classe de utilitário.

Pessoalmente, acho a primeira opção um pouco mais clara.


4

Usar o mesmo nome para o espaço para nome e a classe dentro dele é problemático.

  • Se o espaço para nome contiver mais de uma classe, por que outras classes seriam colocadas lá? não parece certo, porque o objetivo do nome do espaço para nome é descrever todas as classes dentro dele, não apenas uma. Por exemplo, se você tem JsonSerialization, BinarySerializatione XmlSerializationclasses em um namespace, faria sentido para nomear seu namespace XmlSerialization?

    O que geralmente acontece é que, devido à extração de uma classe de um espaço para nome existente ou a uma mesclagem entre várias classes ou outra reorganização, você se encontra com um espaço para nome que contém uma classe principal ; progressivamente, classes menores são colocadas lá porque estão um pouco relacionadas à classe original. Por exemplo, um espaço para nome LogParserpode conter uma única classe LogParsere alguém o coloca LogConverter, porque é bastante relacionado ao analisador LogSearcher, etc. O problema aqui é que o nome do espaço para nome não foi alterado: assim que LogConverterfoi adicionado, o O nome deveria ter sido alterado para LogsProcessingou, simplesmente Logs,.

  • Se o espaço para nome contiver apenas uma classe, pode ser um sinal de um problema na organização do código.

    Embora eu tenha visto algumas vezes as situações em que uma única classe com princípios SOLID adequados era muito diferente de qualquer outra coisa na base de código e, portanto, foi colocada em um espaço de nome dedicado, esses casos são raros. Mais frequentemente, isso é indicativo de um problema. Da mesma forma, nada impede que você tenha uma classe contendo um único método, mas, na maioria das vezes, essas classes indicariam um problema.

    Mesmo que seu espaço para nome contenha apenas uma classe, geralmente há uma maneira de ser mais específico ao nomear a classe e mais geral ao nomear o espaço para nome. Imagine um aplicativo que, entre outras coisas, deve, em um determinado momento, converter arquivos escritos no formato ABC para o formato DEF. A conversão não requer desserialização / serialização de / para os objetos de negócios e é feita aplicando várias expressões regulares curtas o suficiente para serem colocadas na própria classe de conversão chamadaAbcToDefConverter. Toda a lógica de conversão leva cerca de 80 LLOC em cerca de dez métodos interdependentes - parece uma situação em que não há absolutamente nenhuma necessidade de dividir a classe existente, nem criar classes adicionais. Como a parte restante do aplicativo não tem nada a ver com conversões, a classe não pode ser agrupada com outras classes nos namespaces existentes. Então, cria-se um espaço para nome chamado AbcToDefConverter. Embora não haja nada inerentemente errado nisso, também é possível usar um nome mais genérico, como Converters. Em linguagens como Python, onde nomes mais curtos são preferidos e repetição é aplicada, pode até se tornar converters.Abc_To_Def.

Portanto, use nomes diferentes para namespaces e para as classes que eles contêm. O nome de uma classe deve indicar o que a classe está fazendo, enquanto o nome do espaço para nome deve destacar o que é comum em todas as classes inseridas nela.


A propósito, as classes de utilidade são erradas por natureza: em vez de conter algo específico, como aritmética de precisão arbitrária, elas contêm tudo o que não foi encontrado em outras classes . Isso é simplesmente uma má nomeação, assim como um Miscellaneousdiretório em uma área de trabalho - algo que é indicativo da falta de organização.

A nomeação existe por um motivo: para facilitar sua vida quando você precisar encontrar coisas mais tarde. Você sabe que, se precisar desenhar um gráfico, tente procurar "gráfico" ou "plot". Quando você precisar alterar a maneira como um aplicativo gera faturas, você pesquisará "fatura [e / ing]" ou "fatura". Da mesma forma, tente imaginar um caso em que você dirá para si mesmo: "hm, esse recurso provavelmente deve ser encontrado em diversos". Eu não posso

Veja o .NET Framework. A maioria dessas classes não é de utilidade? Quero dizer, eles têm poucas coisas a ver com o domínio comercial. Se eu trabalho em um aplicativo financeiro, site de comércio eletrônico ou na plataforma educacional de próxima geração, serializar XML ou ler arquivos ou fazer consultas SQL ou realizar transações é tudo de utilidade. No entanto, eles não são chamados UtilitySerializationou UtilityTransactione não estão no Utilityespaço para nome. Eles têm nomes próprios, o que torna possível (e fácil, obrigado desenvolvedores do .NET!) Encontrá-los quando eu precisar deles.

O mesmo vale para as aulas que você geralmente reutiliza em seus aplicativos. Eles não são classes de utilidade. São classes que fazem certas coisas, e as coisas que fazem devem realmente ser os nomes das classes.

Imagine que você criou um código que lida com unidades e conversão de unidades. Você pode nomear Utilitye ser odiado por seus colegas; ou você pode nomear Unitse UnitsConversion.


7
"Classes utilitárias estão erradas por natureza". Interessante. Que solução você propõe para algo como uma classe de utilitário de função Math? Uma instância de um objeto Math deve ser realmente necessária para usar funções além dos operadores aritméticos básicos?
FrustratedWithFormsDesigner

1
Eu concordo com você, mas o que você sugere como alternativa?
usuário


4
Adiei a criação de uma biblioteca "utils" por mais tempo, mas eventualmente você apenas precisa ceder. A alternativa é ter DLLs consistindo em cerca de 3 linhas de código, o que é complicado (e me lembra a bagunça das dependências node.js é ) ou copiar e colar seus métodos utilitários para todas as classes que precisam deles (para evitar a classe "coleção de métodos aleatórios"). OMI, no final, é um mal necessário.
precisa saber é o seguinte

3
@FrustratedWithFormsDesigner: simply ... Math? Não vejo como adicionar Utilitysufixo a tudo tornaria nossa vida mais fácil. Ao usar o System.Math.Min()método .NET , você prefere realmente escrever SystemUtility.MathUtility.Min()? Em todos os casos, editei fortemente minha resposta, por isso deve ficar mais clara agora.
Arseni Mourzenko
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.