Espace de noms C # et convention de dénomination de classe pour les bibliothèques

26

Je construis des bibliothèques avec diverses petites fonctions utilitaires en C # et j'essaie de décider d'un espace de noms et d'une convention de dénomination de classe. Mon organisation actuelle est comme ceci:

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

Est-ce un bon moyen d'organiser l'espace de noms et les classes, ou existe-t-il un meilleur moyen? En particulier, il semble que le fait d'avoir le même nom dans l'espace de noms et le nom de classe (par exemple, l' Company.TextUtilsespace de noms et la TextUtilsclasse) n'est qu'une duplication et suggère que le schéma pourrait être meilleur.

utilisateur
la source
5
Les lignes directrices de Microsoft recommandent des noms singuliers pour les énumérations (donc SISuffixau lieu de SISuffixes), et je pense que le singulier se lit mieux. Suffix.A se lit comme "suffixe A". De plus, j'évite généralement de répéter les noms d'un niveau supérieur dans la hiérarchie. Autrement dit, au lieu de Company.SIUnits.SISuffixes, je me pencherais vers Company.SI.SuffixetCompany.SI.Unit
Harrison Paine
2
@richzilla thecodelesscode.com/case/220
Tin Man

Réponses:

9

Il est très difficile de déterminer l'efficacité de votre stratégie de nommage indépendamment du reste de votre code.

L'espace de noms devrait donner une idée de sa place dans la structure générale de votre base de code, et le nom de classe décrirait généralement le type de fonctionnalité ou de concept qu'il représente dans cette zone.

Mis à part les mises en garde, dans votre exemple spécifique, si vous êtes susceptible d'avoir beaucoup plus de classes de type «Util», j'envisagerais de les placer sous Company.Utils.Mathsetc. un endroit naturel pour cela.

richzilla
la source
1
Ça a l'air d'être une bonne idée. Arrêtez trop de vous inquiéter, il vous suffit de tout mettre dans "Company.Util".
utilisateur
30

Il y a un bon document qui contient beaucoup de règles que vous devez suivre pour être en conformité avec Microsoft: Framework Design Guidelines .

Une chose que vous devez changer: ne nommez pas les classes comme leur espace de noms. Cela conduira à des mélanges de compilateurs. Mais ne le fais pas. Trouvez un meilleur nom pour la classe de l'espace de noms.

nvoigt
la source
3
Le lien direct vers les directives relatives aux espaces de noms: msdn.microsoft.com/en-us/library/ms229026(v=vs.110).aspx
Pagotti
1
Qui par coïncidence ou non est aussi le même nom d'un grand livre sur le sujet, également écrit par des personnes Microsoft qui ont participé à la création du framework DotNet, avec plusieurs remarques sur ce qu'ils ont bien fait et où ils se sont trompés. Vaut la peine d'être lu: amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/…
Machado
@nvoigt, pourriez-vous modifier votre réponse pour ajouter une citation à partir du lien fourni par notre ami Pagotti: " N'UTILISEZ PAS le même nom pour un espace de noms et un type dans cet espace de noms. Par exemple, n'utilisez pas Debug comme nom d'espace de noms et puis fournissez également une classe nommée Debug dans le même espace de noms. Plusieurs compilateurs nécessitent que ces types soient pleinement qualifiés. "
Machado
2
Mise en garde: Parfois, un nom de produit est préférable à l'utilisation d'un nom de société. Été dans quelques scénarios où une entreprise a été rachetée et nous avons dû produire de nouveaux espaces de noms à tous les niveaux et rééditer. Je pense que c'est très mineur mais je voulais le souligner.
Jon Raynor
1
Les directives de conception de framework de Microsoft sont très discutables, contiennent de fausses déclarations sur le fonctionnement de .NET et ne sont très souvent pas suivies par Microsoft lui-même. Leurs directives de dénomination sont bonnes, mais j'éviterais de lier les directives générales à une déclaration selon laquelle "vous devriez les suivre".
Carl Leth
6

Cela fait un moment que je n'ai pas travaillé avec C # ou l'écosystème .NET, donc je ne peux pas dire quelles sont les meilleures pratiques recommandées. Je recommanderais une modification de vos noms comme ceci:

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

Ce que j'ai fait ici, c'est supprimer "Utils" des noms d'espace de noms. Je pense que "Util" ne devrait pas être dans un espace de noms, car l' Company.Textespace de noms pourrait un jour contenir des classes qui ne sont pas des classes utilitaires de texte. L' Company.Mathespace de noms contient déjàArbitraryPrecisionNumber ce qui ne semble pas être un "utilitaire".

La suppression de "Util" de l'espace de noms élimine également toute confusion qui pourrait survenir en ayant deux choses avec le même nom (comme mentionné dans la réponse de Robert: /software//a/340440/13156 )

Une autre façon dont vous auriez pu organiser le code:

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

Dans ce cas, toutes les classes d'utilitaires résident dans le même espace de noms. Il n'y a plus d' Company.Textespace de noms puisque la seule chose qu'il y avait une classe d'utilité.

Personnellement, je trouve la première option un peu plus claire.

FrustratedWithFormsDesigner
la source
4

L'utilisation du même nom pour l'espace de noms et la classe à l'intérieur est problématique.

  • Si l'espace de noms contient plusieurs classes, pourquoi y aurait-il d'autres classes? cela ne semble pas correct, car le but du nom de l'espace de noms est de décrire toutes les classes qu'il contient , pas seulement une. Par exemple, si vous avez JsonSerialization, BinarySerializationet des XmlSerializationclasses dans un espace de noms, serait - il judicieux de nommer votre espace XmlSerialization?

    Ce qui se produit généralement, c'est qu'en raison d'une extraction d'une classe à partir d'un espace de noms existant, ou d'une fusion entre plusieurs classes ou d'une autre réorganisation, vous vous retrouvez avec un espace de noms contenant une classe principale ; progressivement, des classes mineures y sont mises car elles sont légèrement liées à la classe d'origine. Par exemple, un espace de noms LogParserpeut contenir une seule classe LogParser, puis quelqu'un le place LogConverter, car il est assez lié à l'analyseur, alors LogSearcher, etc. Le problème ici est que le nom de l'espace de noms n'a pas été changé: dès qu'il a LogConverterété ajouté, le le nom aurait dû être changé LogsProcessingou, tout simplement, Logs.

  • Si l'espace de noms ne contient qu'une seule classe, cela peut être le signe d'un problème au sein de l'organisation du code.

    Bien que j'ai vu à quelques reprises les situations où une seule classe avec des principes SOLID appropriés était très différente de toute autre chose dans la base de code et était donc placée dans un espace de noms dédié, de tels cas sont rares. Le plus souvent, cela indique un problème. De même, rien ne vous empêche d'avoir une classe contenant une seule méthode, mais le plus souvent, ces classes indiquent un problème.

    Même si votre espace de noms ne contient qu'une seule classe, il existe généralement un moyen d'être plus précis lors du nommage de la classe et plus général lors du nommage de l'espace de noms. Imaginez une application qui, entre autres, devrait à un moment donné convertir des fichiers écrits au format ABC au format DEF. La conversion ne nécessite aucune désérialisation / sérialisation vers / depuis les objets métier, et se fait en appliquant un tas d'expressions régulières suffisamment courtes pour être placées dans la classe de conversion elle-même appeléeAbcToDefConverter. Toute la logique de conversion prend environ 80 LLOC dans une dizaine de méthodes interdépendantes - semble être une situation où il n'est absolument pas nécessaire de diviser la classe existante, ni de créer des classes supplémentaires. Étant donné que la partie restante de l'application n'a rien à voir avec les conversions, la classe ne peut pas être regroupée avec d'autres classes dans des espaces de noms existants. On crée donc un espace de noms appelé AbcToDefConverter. Bien qu'il n'y ait rien de fondamentalement mauvais à cela, on pourrait également utiliser un nom plus générique, tel que Converters. Dans des langages tels que Python, où des noms plus courts sont préférés et où la répétition est lancée, cela peut même devenir converters.Abc_To_Def.

Par conséquent, utilisez des noms différents pour les espaces de noms et pour les classes qu'ils contiennent. Le nom d'une classe doit indiquer ce que fait la classe, tandis que le nom de l'espace de noms doit mettre en évidence ce qui est commun à toutes les classes qu'il contient.


Soit dit en passant, les classes d'utilité sont fausses par nature: au lieu de contenir quelque chose de spécifique, comme l'arithmétique de précision arbitraire, elles contiennent plutôt tout ce qui n'a pas trouvé son chemin dans d'autres classes . C'est tout simplement une mauvaise appellation, tout comme un Miscellaneousrépertoire sur un ordinateur de bureau - quelque chose qui indique le manque d'organisation.

La dénomination existe pour une raison: pour vous faciliter la vie lorsque vous avez besoin de trouver des choses plus tard. Vous savez que si vous avez besoin de dessiner un graphique, vous pouvez essayer de rechercher «graphique» ou «tracé». Lorsque vous devez modifier la façon dont une application génère des factures, vous recherchez «facture [e / ing]» ou «facture». De même, essayez d'imaginer un cas où vous vous direz: "hm, cette fonctionnalité devrait probablement se trouver dans misc". Je ne peux pas.

Regardez .NET Framework. La plupart de ces classes ne sont-elles pas des classes utilitaires? Je veux dire, ils ont peu de choses à voir avec le domaine des affaires. Si je travaille sur une application financière, sur un site Web de commerce électronique ou sur la plate-forme de formation de prochaine génération, sérialiser XML ou lire des fichiers ou effectuer des requêtes SQL ou effectuer des transactions est tout ce qui est utile. Cependant, ils ne sont pas appelés UtilitySerializationou UtilityTransactionet ils ne se trouvent pas dans l' Utilityespace de noms. Ils ont des noms propres, ce qui permet (et facile, merci aux développeurs .NET!) De les trouver quand j'en ai besoin.

Il en va de même pour vos cours que vous réutilisez couramment dans vos applications. Ce ne sont pas des classes d'utilité. Ce sont des classes qui font certaines choses, et les choses qu'elles font devraient en fait être les noms des classes.

Imaginez que vous avez créé du code qui traite des unités et de la conversion des unités. Vous pouvez le nommer Utilityet être détesté par vos collègues; ou vous pouvez le nommer Unitset UnitsConversion.

Arseni Mourzenko
la source
7
"Les classes d'utilité sont fausses par nature". Intéressant. Quelle solution proposez-vous pour quelque chose comme une classe utilitaire de fonction mathématique? Une instance d'un objet Math devrait-elle vraiment être nécessaire pour utiliser des fonctions au-delà des opérateurs arithmétiques de base?
FrustratedWithFormsDesigner
1
Je suis d'accord avec vous, mais que proposez-vous comme alternative?
utilisateur
2
Je l'
appellerai
4
J'ai retardé la création d'une bibliothèque "utils" pendant le plus longtemps mais finalement il vous suffit de céder. L'alternative est d'avoir des DLL composées d'environ 3 lignes de code, ce qui est juste encombrant (et me rappelle le désordre des dépendances node.js est ), ou copiez et collez vos méthodes utilitaires dans chaque classe qui en aurait besoin (pour éviter d'avoir cette classe "collection de méthodes aléatoires"). À la fin, l'OMI est un mal nécessaire.
Matti Virkkunen
3
@FrustratedWithFormsDesigner: simplement ... Math? Je ne vois pas comment l'ajout d'un Utilitysuffixe à tout nous faciliterait la vie. Lorsque vous utilisez la System.Math.Min()méthode de .NET , préférez-vous vraiment écrire à la SystemUtility.MathUtility.Min()place? Dans tous les cas, j'ai fortement modifié ma réponse, donc ça devrait être plus clair maintenant.
Arseni Mourzenko