Die bestehenden Codierungsstandards für ein großes C # -Projekt enthalten die Regel, dass alle Typnamen vollständig qualifiziert sein müssen, und verbieten die Verwendung der Direktive 'using'. Also eher als das Vertraute:
using System.Collections.Generic;
.... other stuff ....
List<string> myList = new List<string>();
(Es ist wahrscheinlich keine Überraschung, dass var
auch verboten ist.)
Am Ende habe ich:
System.Collections.Generic.List<string> myList = new System.Collections.Generic.List<string>();
Das ist eine Steigerung der Eingabe um 134%, wobei keine dieser Steigerungen nützliche Informationen liefert. Meiner Ansicht nach ist 100% der Zunahme Rauschen (Unordnung), das das Verstehen tatsächlich behindert .
In über 30 Jahren Programmierung habe ich ein oder zwei Mal einen solchen Standard vorgeschlagen, aber nie implementiert. Die Begründung dahinter entgeht mir. Die Person, die den Standard auferlegt, ist nicht dumm, und ich glaube nicht, dass er bösartig ist. Was als einzige Alternative fehlgeleitet bleibt, es sei denn, mir fehlt etwas.
Haben Sie jemals von einem solchen Standard gehört? Wenn ja, aus welchem Grund? Können Sie sich andere Argumente als "es ist dumm" oder "jeder andere beschäftigt using
" vorstellen, die diese Person davon überzeugen könnten, dieses Verbot aufzuheben?
Argumentation
Die Gründe für dieses Verbot waren:
- Es ist umständlich, mit der Maus über den Namen zu fahren, um den vollqualifizierten Typ zu erhalten. Es ist besser, immer den vollständig qualifizierten Typ sichtbar zu haben.
- Codeausschnitte per E-Mail haben nicht den vollständigen Namen und sind daher möglicherweise schwer zu verstehen.
- Wenn Sie den Code außerhalb von Visual Studio anzeigen oder bearbeiten (z. B. Notepad ++), ist es nicht möglich, den vollständig qualifizierten Typnamen abzurufen.
Meine Behauptung ist, dass alle drei Fälle selten sind und dass es falsch ist, alle den Preis für überfüllten und weniger verständlichen Code zahlen zu lassen, nur um ein paar seltene Fälle zu berücksichtigen.
Mögliche Probleme mit Namespace-Konflikten, von denen ich erwartet hatte, dass sie die Hauptsorge sind, wurden nicht einmal erwähnt. Das ist besonders überraschend, weil wir einen Namespace haben MyCompany.MyProject.Core
, was eine besonders schlechte Idee ist. Ich habe vor langer Zeit gelernt, dass es ein schneller Weg zum Wahnsinn ist , irgendetwas System
oder Core
in C # zu benennen .
Wie bereits erwähnt, können Namespace-Konflikte leicht durch Refactoring, Namespace-Aliase oder teilweise Qualifizierung gelöst werden.
quelle
Antworten:
Die allgemeinere Frage:
Ja, ich habe davon gehört und die Verwendung von vollständig qualifizierten Objektnamen verhindert Namenskollisionen. Wenn sie vorkommen, sind sie zwar selten, können aber außerordentlich schwierig zu ermitteln sein.
Ein Beispiel: Dieser Typ eines Szenarios wird wahrscheinlich besser mit einem Beispiel erklärt.
Nehmen wir an, wir haben zwei,
Lists<T>
die zu zwei separaten Projekten gehören.Wenn wir den vollständig qualifizierten Objektnamen verwenden, ist klar, welcher
List<T>
verwendet wird. Diese Klarheit geht natürlich zu Lasten der Ausführlichkeit.Und Sie könnten argumentieren: "Warten Sie! Niemand würde jemals zwei Listen wie diese verwenden!" An dieser Stelle werde ich auf das Wartungsszenario hinweisen.
Sie haben ein Modul
Foo
für Ihr Unternehmen geschrieben, das das genehmigte, optimierte Unternehmen verwendetList<T>
.Später beschließt ein neuer Entwickler, die von Ihnen geleistete Arbeit zu erweitern. Da sie die Standards des Unternehmens nicht kennen, aktualisieren sie den
using
Block:Und Sie können sehen, wie die Dinge in Eile schlecht laufen.
Es sollte trivial sein, darauf hinzuweisen, dass Sie zwei proprietäre Klassen mit demselben Namen, jedoch in unterschiedlichen Namespaces innerhalb desselben Projekts haben können. Es geht also nicht nur darum, mit von .NET Framework bereitgestellten Klassen zu kollidieren.
Die Realität:
Tritt dies wahrscheinlich in den meisten Projekten auf? Nein nicht wirklich. Wenn Sie jedoch an einem großen Projekt mit vielen Eingaben arbeiten, tun Sie Ihr Bestes, um die Gefahr von Explosionen auf Sie zu minimieren.
Große Projekte mit mehreren beitragenden Teams sind eine besondere Art von Tier in der Anwendungswelt. Regeln, die für andere Projekte unangemessen erscheinen, werden aufgrund der Eingabeströme für das Projekt und der Wahrscheinlichkeit, dass die Beitragenden die Projektrichtlinien nicht gelesen haben, relevanter.
Dies kann auch auftreten, wenn zwei große Projekte zusammengeführt werden. Wenn beide Projekte ähnlich benannte Klassen hatten, werden Kollisionen angezeigt, wenn Sie von einem Projekt zum anderen referenzieren. Und die Projekte sind möglicherweise zu umfangreich, um sie umzugestalten, oder das Management genehmigt nicht die Kosten für die Finanzierung der für die Umgestaltung aufgewendeten Zeit.
Alternativen:
Sie haben zwar nicht gefragt, aber es lohnt sich darauf hinzuweisen, dass dies keine großartige Lösung für das Problem ist. Es ist keine gute Idee, Klassen zu erstellen, die ohne ihre Namespace-Deklarationen kollidieren.
List<T>
Insbesondere sollte es als reserviertes Wort behandelt und nicht als Name für Ihre Klassen verwendet werden.Ebenso sollten einzelne Namespaces innerhalb des Projekts nach eindeutigen Klassennamen streben. Wenn Sie versuchen, herauszufinden, mit welchem Namespace
Foo()
Sie arbeiten, ist dies ein mentaler Aufwand, der am besten vermieden wird. Anders gesagt: Sie müssenMyCorp.Bar.Foo()
und werdenMyCorp.Baz.Foo()
Ihre Entwickler aus der Ruhe bringen und dies am besten vermeiden.Wenn nicht anders angegeben, können Sie teilweise Namespaces verwenden, um die Mehrdeutigkeit aufzulösen. Wenn Sie beispielsweise keine der
Foo()
Klassen umbenennen können, können Sie deren Teil-Namespaces verwenden:Spezifische Gründe für Ihr aktuelles Projekt:
Sie haben Ihre Frage mit den spezifischen Gründen aktualisiert, die Sie für Ihr aktuelles Projekt angegeben haben. Lassen Sie uns einen Blick auf sie werfen und wirklich den Hasenpfad entlang schweifen.
"Schwerfällig?" Ähm, nein. Vielleicht ärgerlich. Das Bewegen einiger Unzen Plastik, um einen Bildschirmzeiger zu verschieben, ist nicht umständlich . Aber ich schweife ab.
Diese Argumentation scheint eher eine Vertuschung zu sein als alles andere. Auf den ersten Blick würde ich vermuten, dass die Klassen in der Anwendung schwach benannt sind und Sie sich auf den Namespace verlassen müssen, um die entsprechende Menge an semantischen Informationen zu erhalten, die den Klassennamen umgeben.
Dies ist keine gültige Rechtfertigung für vollständig qualifizierte Klassennamen. Vielleicht ist es eine gültige Rechtfertigung für die Verwendung von teilweise qualifizierten Klassennamen.
Diese (Fortsetzung?) Argumentation untermauert meinen Verdacht, dass Klassen derzeit schlecht benannt sind. Auch hier ist mit Namen schlecht Klasse keine gute Begründung für die Forderung , alles über ein voll qualifizierten Klassennamen zu verwenden. Wenn der Klassenname schwer zu verstehen ist, ist viel mehr falsch, als mit vollständig qualifizierten Klassennamen behoben werden kann.
Aus all den Gründen hätte ich beinahe mein Getränk ausgespuckt. Aber ich schweife ab.
Ich frage mich, warum das Team häufig Code außerhalb von Visual Studio bearbeitet oder anzeigt. Und jetzt sehen wir uns eine Rechtfertigung an, die ziemlich orthogonal zu den Namespaces ist, die bereitgestellt werden sollen. Dies ist ein werkzeuggestütztes Argument, während Namespaces dazu dienen, dem Code eine Organisationsstruktur zu geben.
Es hört sich so an, als ob Ihr eigenes Projekt unter schlechten Namenskonventionen leidet, zusammen mit Entwicklern, die nicht die Vorteile nutzen, die die Tools für sie bieten können. Und anstatt diese tatsächlichen Probleme zu lösen, haben sie versucht, ein Pflaster über eines der Symptome zu legen und benötigen vollständig qualifizierte Klassennamen. Ich denke, es ist sicher, dies als einen fehlgeleiteten Ansatz zu kategorisieren.
Angesichts der Tatsache, dass es schlecht benannte Klassen gibt und Sie nicht umgestalten können, ist die richtige Antwort, die Visual Studio-IDE zu ihrem vollen Vorteil zu nutzen. Erwägen Sie möglicherweise, ein Plugin wie das VS PowerTools-Paket hinzuzufügen. Wenn ich mir dann anschaue,
AtrociouslyNamedClass()
kann ich auf den Klassennamen klicken, F12 drücken und direkt zur Definition der Klasse weitergeleitet werden, um besser zu verstehen, was sie versucht zu tun. Ebenso kann ich Shift-F12 drücken, um alle Stellen im Code zu finden, die gerade benutzt werden müssenAtrociouslyNamedClass()
.In Bezug auf die Probleme mit den Außenwerkzeugen ist es am besten, diese einfach zu beenden. Schicken Sie keine Schnipsel per E-Mail hin und her, wenn nicht sofort klar ist, worauf sich der Verweis bezieht. Verwenden Sie keine anderen Tools außerhalb von Visual Studio, da diese Tools nicht über die für Ihr Team erforderlichen Informationen zum Code verfügen. Notepad ++ ist ein großartiges Tool, aber es ist nicht für diese Aufgabe geeignet.
Daher stimme ich Ihrer Einschätzung hinsichtlich der drei spezifischen Begründungen zu, die Ihnen vorgelegt wurden. Ich denke, Ihnen wurde jedoch gesagt: "Wir haben grundlegende Probleme in diesem Projekt, die wir nicht lösen können / wollen, und auf diese Weise haben wir sie" behoben "." Und das spricht offensichtlich für tiefere Probleme innerhalb des Teams, die für Sie als rote Fahnen dienen können.
quelle
usings
aber es hört sich nicht so an, als würde Ihr Projekt als einer dieser Fälle eingestuft.Ich habe in einer Firma gearbeitet, in der es viele Klassen mit demselben Namen gab, aber in verschiedenen Klassenbibliotheken.
Zum Beispiel,
Schlechtes Design, könnte man sagen, aber Sie wissen, wie sich diese Dinge organisch entwickeln und was die Alternative ist - benennen Sie alle Klassen um, um den Namespace einzuschließen? Großes Refactoring von allem?
Auf jeden Fall gab es mehrere Stellen, an denen Projekte, die auf all diese verschiedenen Bibliotheken verweisen, mehrere Versionen der Klasse verwenden mussten.
Mit dem
using
direkt an der Spitze, das war ein großer Schmerz im Arsch, ReSharper würde seltsame Dinge tun, um es zumusing
Laufen zu bringen , die Direktiven im laufenden Betrieb umschreiben , man würde Kunden-kann-nicht-als-Cast bekommen Kundenstilfehler und nicht wissen, welcher Typ der richtige war.Also, mit mindestens dem partiellen Namespace,
oder
Verbesserte die Lesbarkeit des Codes erheblich und machte deutlich, welches Objekt Sie wollten.
Es war kein Codierungsstandard, es war nicht der vollständige Namespace, und es wurde nicht standardmäßig auf alle Klassen angewendet.
quelle
Es ist nicht gut, zu ausführlich oder zu kurz zu sein: Man sollte eine goldene Mitte darin finden, detailliert genug zu sein, um subtile Fehler zu verhindern und gleichzeitig zu vermeiden, zu viel Code zu schreiben.
In C # sind dies beispielsweise die Namen von Argumenten. Ich bin mehrmals auf ein Problem gestoßen, bei dem ich stundenlang nach einer Lösung gesucht habe, während eine ausführlichere Schreibweise den Fehler an erster Stelle verhindern konnte. Das Problem besteht in einem Fehler in der Reihenfolge der Argumente. Sieht es zum Beispiel für Sie richtig aus?
Auf den ersten Blick sieht es ganz gut aus, aber es gibt einen Fehler. Die Signaturen der Konstruktoren der Ausnahmen sind:
Bemerkt die Reihenfolge der Argumente?
Durch die Verwendung eines ausführlicheren Stils, bei dem der Name eines Arguments jedes Mal angegeben wird, wenn die Methode zwei oder mehr Argumente desselben Typs akzeptiert , wird verhindert, dass der Fehler erneut auftritt.
ist offensichtlich länger zu schreiben, führt aber zu weniger Zeitverschwendung beim Debuggen.
Extreme Anforderungen können dazu führen, dass überall benannte Argumente verwendet werden , auch in Methoden, bei
doSomething(int, string)
denen es nicht möglich ist, die Reihenfolge der Parameter zu mischen. Dies wird wahrscheinlich das Projekt langfristig schädigen, was zu viel mehr Code führt, ohne den oben beschriebenen Fehler zu verhindern.In Ihrem Fall ist die Motivation hinter der „Nein
using
ist“ Regel , dass es sollte es die falsche Art zu verwenden, wie zum Beispiel erschwerenMyCompany.Something.List<T>
vs.System.Collections.Generic.List<T>
.Persönlich würde ich eine solche Regel vermeiden, da die Kosten für schwer lesbaren Code meiner Meinung nach weit über dem Nutzen eines geringfügig verringerten Risikos für den Missbrauch des falschen Typs liegen, aber zumindest gibt es einen triftigen Grund für diese Regel.
quelle
paramName
mit demInvokerParameterName
Attribut und gibt eine Warnung aus, wenn kein solcher Parameter vorhanden ist.SomeBusiness.Something.DoStuff(string name, string description)
? Kein Werkzeug ist schlau genug, um zu verstehen, was ein Name und was eine Beschreibung ist.Namespaces geben Code eine hierarchische Struktur, die kürzere Namen ermöglicht.
Wenn Sie das Schlüsselwort "using" zulassen, gibt es eine Ereigniskette ...
(weil er jeden Namespace enthält, den er sich nur wünschen kann).
Um das Risiko zu vermeiden, beginnen alle, sehr lange Namen zu verwenden:
Die Situation eskaliert ...
Ich habe dies gesehen, kann also mit Firmen sympathisieren, die das "Verwenden" verbieten.
quelle
using
ist die nukleare Option. Namespace-Aliase und Teilqualifikationen sind vorzuziehen.Das Problem dabei
using
ist, dass es ohne explizite Deklaration auf magische Weise zum Namespace hinzugefügt wird. Dies ist ein weitaus größeres Problem für den Wartungsprogrammierer, der auf so etwas stößtList<>
und nicht mit der Domäne vertraut ist und nicht weiß, welcheusing
Klausel dies eingeführt hat.Ein ähnliches Problem tritt in Java auf, wenn man
import Java.util.*;
nichtimport Java.util.List;
zum Beispiel schreibt ; Die letztgenannte Deklaration dokumentiert, welcher Name eingeführt wurde, so dassList<>
der Ursprung bei einem späteren Auftreten in der Quelle aus derimport
Deklaration bekannt ist.quelle