Les normes de codage existantes pour un grand projet C # incluent une règle selon laquelle tous les noms de type doivent être pleinement qualifiés, interdisant ainsi l’utilisation de la directive "using". Donc, plutôt que le familier:
using System.Collections.Generic;
.... other stuff ....
List<string> myList = new List<string>();
(Ce n'est probablement pas une surprise si cela var
est également interdit.)
Je me retrouve avec:
System.Collections.Generic.List<string> myList = new System.Collections.Generic.List<string>();
Cela représente une augmentation de 134% du nombre de saisies, sans que cette augmentation fournisse des informations utiles. À mon avis, 100% de l'augmentation est du bruit (encombrement) qui empêche la compréhension.
En plus de 30 ans de programmation, j'ai vu une telle norme proposée une ou deux fois, mais jamais mise en œuvre. La raison derrière cela m'échappe. La personne qui impose la norme n’est pas stupide et je ne pense pas qu’elle soit méchante. Ce qui laisse à tort comme la seule autre alternative à moins que je manque quelque chose.
Avez-vous déjà entendu parler d'une telle norme imposée? Si oui, quelle était la raison derrière cela? Pouvez-vous penser à des arguments autres que "c'est stupide" ou "tout le monde emploie using
" qui pourraient convaincre cette personne de lever cette interdiction?
Raisonnement
Les raisons de cette interdiction étaient:
- Il est fastidieux de passer la souris sur le nom pour obtenir le type pleinement qualifié. Il est préférable de toujours avoir le type pleinement qualifié visible tout le temps.
- Les extraits de code envoyés par courrier électronique n'ont pas le nom complet et peuvent donc être difficiles à comprendre.
- Lors de l'affichage ou de la modification du code en dehors de Visual Studio (Notepad ++, par exemple), il est impossible d'obtenir le nom de type qualifié complet.
Mon argument est que les trois cas sont rares et que faire payer à chacun le prix d'un code encombré et moins compréhensible juste pour tenir compte de quelques cas rares est erroné.
Les problèmes potentiels de conflit dans les espaces de noms, que je pensais être la principale préoccupation, n'ont même pas été mentionnés. C'est particulièrement surprenant, car nous avons un espace de noms MyCompany.MyProject.Core
, ce qui est une très mauvaise idée. J'ai appris il y a longtemps que nommer n'importe quoi System
ou Core
en C # est un chemin rapide vers la folie.
Comme d'autres l'ont souligné, les conflits d'espaces de noms sont facilement résolus par le refactoring, les alias d'espaces de noms ou la qualification partielle.
la source
Réponses:
La question plus large:
Oui, j'en ai entendu parler et l'utilisation de noms d'objet pleinement qualifiés évite les conflits de noms. Bien que rares, quand ils se produisent, ils peuvent être exceptionnellement épineux à comprendre.
Un exemple: Ce type de scénario est probablement mieux expliqué avec un exemple.
Disons que nous avons deux
Lists<T>
appartenant à deux projets distincts.Lorsque nous utilisons le nom d'objet qualifié complet, il est clairement indiqué lequel
List<T>
est utilisé. Cette clarté est évidemment au détriment de la verbosité.Et vous vous disputerez peut-être: "Attendez! Personne n’utilisera jamais deux listes de ce genre!" C'est là que je signalerai le scénario de maintenance.
Vous êtes un module écrit
Foo
pour votre société qui utilise la société approuvée, optimiséeList<T>
.Plus tard, un nouveau développeur décide d'étendre le travail que vous avez fait. Ne connaissant pas les normes de l'entreprise, ils mettent à jour le
using
blocage:Et vous pouvez voir comment les choses vont mal à la hâte.
Il devrait être trivial de souligner que vous pouvez avoir deux classes propriétaires du même nom mais dans des espaces de noms différents au sein du même projet. Il ne s’agit donc pas uniquement de la collision avec les classes fournies par .NET Framework.
La réalité:
est-ce que cela va probablement se produire dans la plupart des projets? Non, pas vraiment. Mais lorsque vous travaillez sur un grand projet avec beaucoup d’intrants, vous faites de votre mieux pour minimiser les risques d’explosion.
Les grands projets avec plusieurs équipes contributives constituent un type particulier de bête dans le monde des applications. Les règles qui semblent déraisonnables pour d'autres projets deviennent plus pertinentes en raison des flux d'entrées vers le projet et de la probabilité que ceux qui contribuent ne lisent pas les directives du projet.
Cela peut également se produire lorsque deux grands projets sont fusionnés. Si les deux projets ont des noms similaires, vous verrez des collisions lorsque vous commencez à référencer d'un projet à l'autre. Et les projets sont peut-être trop importants pour être restructurés ou la direction n’approuve pas les dépenses engagées pour financer le temps consacré à la refactorisation.
Alternatives:
Bien que vous ne l'ayez pas demandé, cela vaut la peine de souligner que ce n'est pas une bonne solution au problème. Ce n'est pas une bonne idée de créer des classes qui vont entrer en collision sans leurs déclarations d'espace de noms.
List<T>
en particulier, doit être traité comme un mot réservé et non utilisé comme nom pour vos classes.De même, les espaces de noms individuels au sein du projet doivent s'efforcer d'avoir des noms de classe uniques. Devoir essayer de se rappeler avec quel espace de noms
Foo()
vous travaillez est une surcharge mentale qu'il vaut mieux éviter. Dit autrement: avoirMyCorp.Bar.Foo()
etMyCorp.Baz.Foo()
va faire trébucher vos développeurs et les éviter au mieux.Si rien d'autre, vous pouvez utiliser des espaces de noms partiels afin de résoudre l'ambiguïté. Par exemple, si vous ne pouvez absolument pas renommer l'une ou l'autre
Foo()
classe, vous pouvez utiliser leurs espaces de noms partiels:Raisons spécifiques de votre projet actuel:
Vous avez mis à jour votre question avec les raisons spécifiques qui vous ont été données pour votre projet actuel, conformément à cette norme. Jetons un coup d'oeil à eux et détournons vraiment le sentier du lapin.
"Lourd?" Um non. Ennuyeux peut-être. Déplacer quelques onces de plastique afin de déplacer un pointeur à l'écran n'est pas encombrant . Mais je m'égare.
Cette ligne de raisonnement semble plus être une dissimulation que toute autre chose. De prime abord, je suppose que les classes de l'application ont un nom faible et que vous devez compter sur l'espace de noms pour obtenir la quantité appropriée d'informations sémantiques entourant le nom de la classe.
Ce n'est pas une justification valable pour les noms de classe pleinement qualifiés, mais peut-être aussi une justification valable pour utiliser des noms de classe partiellement qualifiés.
Ce raisonnement (suite?) Renforce mes soupçons sur le fait que les classes portent actuellement un mauvais nom. Encore une fois, avoir des noms de classe médiocres n'est pas une bonne justification pour exiger que tout utilise un nom de classe pleinement qualifié. Si le nom de classe est difficile à comprendre, il y a beaucoup plus de problèmes que ce que les noms de classe pleinement qualifiés peuvent corriger.
De toutes les raisons, celle-ci m'a presque fait cracher mon verre. Mais encore une fois, je m'égare.
Je me demande pourquoi l'équipe modifie ou affiche fréquemment le code en dehors de Visual Studio. Et nous examinons maintenant une justification qui est assez orthogonale à ce que les espaces de noms sont censés fournir. C'est un argument basé sur les outils, alors que les espaces de noms sont là pour fournir une structure organisationnelle au code.
Il semble que votre projet souffre de mauvaises conventions de nommage, ainsi que de développeurs qui ne profitent pas de ce que l’outillage peut leur fournir. Et plutôt que de résoudre ces problèmes réels, ils ont tenté de casser un pansement sur l'un des symptômes et ont demandé des noms de classe complets. Je pense qu'il est prudent de catégoriser cela comme une approche erronée.
Étant donné qu'il existe des classes mal nommées et en supposant que vous ne pouvez pas refactoriser, la bonne réponse consiste à utiliser pleinement l'environnement de développement intégré de Visual Studio. Envisagez éventuellement d’ajouter un plugin tel que le package VS PowerTools. Ensuite, lorsque je regarde,
AtrociouslyNamedClass()
je peux cliquer sur le nom de la classe, appuyer sur F12 et accéder directement à la définition de la classe afin de mieux comprendre ce qu’il essaie de faire. De même, je peux cliquer sur Shift-F12 pour trouver toutes les taches du code qui doivent actuellement être utiliséesAtrociouslyNamedClass()
.En ce qui concerne les problèmes d'outillage extérieur - la meilleure chose à faire est simplement de l'arrêter. N'envoyez pas d'e-mails de bout en bout s'ils ne sont pas immédiatement clairs sur ce qu'ils renvoient. N'utilisez pas d'autres outils en dehors de Visual Studio, car ils ne possèdent pas l'intelligence nécessaire au code dont votre équipe a besoin. Notepad ++ est un outil génial, mais il n'est pas conçu pour cette tâche.
Je suis donc d'accord avec votre évaluation concernant les trois justifications spécifiques qui vous ont été présentées. Cela dit, on vous a dit ce qui suit: "Nous avons des problèmes sous-jacents dans ce projet qui ne peuvent pas / ne vont pas être résolus et c'est comme cela que nous les avons" résolus "." Et cela évoque évidemment des problèmes plus profonds au sein de l'équipe qui peuvent vous servir de signaux d'alarme.
la source
usings
mais il ne semble pas que votre projet soit considéré comme l'un de ces cas.J'ai travaillé dans une entreprise où plusieurs classes avaient le même nom, mais dans des bibliothèques de classes différentes.
Par exemple,
Vous pourriez dire que la conception est mauvaise, mais vous savez comment ces choses se développent de manière organique et quelle est l'alternative: renommer toutes les classes pour inclure l'espace de noms? Refactoring majeur de tout?
Dans tous les cas, il y avait plusieurs endroits où les projets faisant référence à toutes ces bibliothèques différentes devaient utiliser plusieurs versions de la classe.
Avec le
using
directement au sommet, c’était un problème majeur, ReSharper faisait des choses bizarres pour essayer de le faire fonctionner, réécrivant lesusing
directives à la volée, vous obtiendrez un client qui ne peut pas être moulé comme tel. Erreurs de type client et ne pas savoir quel type était le bon.Donc, ayant au moins l'espace de noms partiel,
ou
grandement amélioré la lisibilité du code et explicite quel objet vous vouliez.
Ce n'était pas une norme de codage, ce n'était pas tout l'espace de noms, et cela ne s'appliquait pas à toutes les classes en standard.
la source
Il n’est pas bon d’être trop bavard ou trop court: il faut trouver un juste milieu en étant suffisamment détaillé pour éviter les bugs subtils, tout en évitant d’écrire trop de code.
En C #, les noms des arguments en sont un exemple. J'ai rencontré à plusieurs reprises un problème où je passais des heures à chercher une solution, alors qu'un style d'écriture plus verbeux pourrait empêcher le bogue en premier lieu. Le problème consiste en une erreur dans l'ordre des arguments. Par exemple, cela vous semble-t-il correct?
Au premier coup d'oeil, ça a l'air parfait, mais il y a un bug. Les signatures des constructeurs des exceptions sont:
Remarqué l'ordre des arguments?
En adoptant un style plus détaillé dans lequel le nom d'un argument est spécifié chaque fois que la méthode accepte deux arguments ou plus du même type , nous évitons que l'erreur ne se reproduise, et donc:
est évidemment plus long à écrire, mais entraîne moins de perte de temps en débogage.
Poussé à l'extrême, on pourrait forcer l'utilisation d'arguments nommés partout , y compris dans des méthodes telles que les
doSomething(int, string)
cas où il est impossible de mélanger l'ordre des paramètres. Cela va probablement nuire au projet à long terme, résultant en beaucoup plus de code sans l'avantage d'éviter le bogue que j'ai décrit ci-dessus.Dans votre cas, la motivation derrière la « Aucune
using
règle » est qu'il devrait rendre plus difficile d'utiliser le mauvais type, par exemple parMyCompany.Something.List<T>
rapport àSystem.Collections.Generic.List<T>
.Personnellement, j’éviterais une telle règle car, à mon humble avis, le coût d’un code difficile à lire est bien supérieur au bénéfice d’un risque légèrement réduit d’utilisation abusive du mauvais type, mais au moins, cette règle a une raison valable.
la source
paramName
avec l'InvokerParameterName
attribut et émet un avertissement si ce paramètre n'existe pas.SomeBusiness.Something.DoStuff(string name, string description)
? Aucun outil n'est assez intelligent pour comprendre ce qu'est un nom et ce qu'est une description.Les espaces de noms donnent au code une structure hiérarchique, permettant des noms plus courts.
Si vous autorisez le mot-clé "using", il y a une chaîne d'événements ...
(car ils incluent tous les espaces de noms qu'ils pourraient éventuellement souhaiter)
Donc, pour éviter les risques, tout le monde commence à utiliser des noms très longs:
La situation dégénère ...
J'ai vu cela se produire, alors je peux sympathiser avec les entreprises qui interdisent "l'utilisation".
la source
using
est l'option nucléaire. Les alias d'espace de noms et la qualification partielle sont préférables.Le problème
using
est que cela ajoute par magie à l'espace de noms sans déclaration explicite. C'est beaucoup plus un problème pour le programmeur de maintenance qui rencontre quelque chose comme,List<>
et sans connaître le domaine, ne sait pas quelleusing
clause l'a introduit.Un problème similaire se produit en Java si l’on écrit
import Java.util.*;
plutôt queimport Java.util.List;
par exemple; cette dernière déclaration documente le nom qui a été introduit de sorte que, lorsque celaList<>
se produit plus tard dans la source, son origine soit connue de laimport
déclaration.la source