Ich erstelle Bibliotheken mit verschiedenen kleinen Hilfsprogrammfunktionen in C # und versuche, eine Namensraum- und Klassennamenskonvention festzulegen. Meine derzeitige Organisation sieht folgendermaßen aus:
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 {...}
Ist dies eine gute Möglichkeit, den Namespace und die Klassen zu organisieren, oder gibt es eine bessere Möglichkeit? Insbesondere scheint es so, als ob der gleiche Name im Namespace und im Klassennamen (z. B. Company.TextUtils
Namespace und TextUtils
Klasse) nur eine Verdoppelung ist, und dies deutet darauf hin, dass das Schema besser sein könnte.
SISuffix
stattSISuffixes
), und ich denke, dass Singular besser liest.Suffix.A
liest als "Suffix A". Außerdem vermeide ich im Allgemeinen, Namen von einer höheren Ebene in der Hierarchie aus zu wiederholen. Das heißt, stattdessenCompany.SIUnits.SISuffixes
würde ich mich zuCompany.SI.Suffix
undCompany.SI.Unit
Antworten:
Es ist sehr schwierig festzustellen, wie effektiv Ihre Namensstrategie unabhängig vom Rest Ihres Codes ist.
Der Namespace sollte eine Vorstellung davon geben, wo er in die breite Struktur Ihrer Codebasis passt, und der Klassenname würde normalerweise beschreiben, welche Art von Funktionalität oder Konzept er in diesem Bereich darstellt.
Abgesehen von den Einschränkungen in Ihrem speziellen Beispiel, wenn Sie wahrscheinlich viel mehr Util-Typklassen haben, würde ich in Betracht ziehen, diese unter
Company.Utils.Maths
usw. zu stellen. Auf diese Weise müssen Sie bereits Funktionen hinzufügen, die mehreren Versorgungsbereichen gemeinsam sind ein natürlicher Ort dafür.quelle
Es gibt ein nettes Dokument, das viele Regeln enthält, die Sie befolgen sollten, um mit Microsoft übereinzustimmen : Framework Design Guidelines .
Eine Sache, die Sie ändern sollten: Benennen Sie Klassen nicht als ihren Namespace. Das wird zu Compiler-Verwechslungen führen. Tu es einfach nicht. Suchen Sie einen besseren Namen für die Klasse des Namespaces.
quelle
Es ist schon eine Weile her, dass ich mit C # oder dem .NET-Ökosystem gearbeitet habe. Daher kann ich nicht sagen, welche Best Practices derzeit empfohlen werden. Ich würde eine Änderung Ihrer Namen wie folgt empfehlen:
Ich habe hier "Utils" aus den Namespace-Namen entfernt. Ich denke, dass "Util" nicht in einem Namespace sein sollte, weil der
Company.Text
Namespace eines Tages Klassen enthalten könnte, die keine Textdienstprogrammklassen sind . DerCompany.Math
Namespace enthält bereits,ArbitraryPrecisionNumber
was anscheinend kein "Dienstprogramm" ist.Das Entfernen von "Util" aus dem Namespace beseitigt auch Verwirrungen, die auftreten können, wenn zwei Dinge mit demselben Namen vorliegen (wie in Roberts Antwort erwähnt: https://softwareengineering.stackexchange.com/a/340440/13156 ).
Auf eine andere Weise hätten Sie den Code organisieren können:
In diesem Fall befinden sich alle Dienstprogrammklassen im gleichen Namespace. Es gibt keinen
Company.Text
Namespace mehr, da es nur eine Utility-Klasse gab.Persönlich finde ich die erste Option etwas klarer.
quelle
Das Verwenden des gleichen Namens für den Namespace und die Klasse darin ist problematisch.
Wenn der Namespace mehr als eine Klasse enthält, warum werden andere Klassen dort abgelegt? es fühlt sich nicht richtig an, weil das Ziel des Namens des Namespaces darin besteht, alle Klassen darin zu beschreiben , nicht nur eine. Wenn Sie zum Beispiel haben
JsonSerialization
,BinarySerialization
undXmlSerialization
Klassen in einem Namespace, würde es Sinn macht Ihren Namensraum zu nennenXmlSerialization
?Was geschieht in der Regel ist , dass aufgrund einer Extraktion einer Klasse aus einem vorhandenen Namespace oder eine Zusammenführung zwischen mehreren Klassen oder anderer Form der Reorganisation, können Sie sich mit einem Namespace finden eine enthält wichtige Klasse; Nach und nach werden dort kleinere Klassen abgelegt, da sie leicht mit der ursprünglichen Klasse verwandt sind. Zum Beispiel kann ein Namensraum
LogParser
kann eine einzelne Klasse enthältLogParser
, und dann jemand setztLogConverter
, weil es ganz an den Parser verwendet ist, dannLogSearcher
usw. Das Problem hierbei ist , dass der Name des Namespace nicht geändert wurde: sobaldLogConverter
hinzugefügt wurde, das Name hätte geändert werden sollenLogsProcessing
oder einfachLogs
.Wenn der Namespace nur eine Klasse enthält, weist dies möglicherweise auf ein Problem in der Codeorganisation hin.
Obwohl ich einige Male Situationen erlebt habe, in denen sich eine einzelne Klasse mit den richtigen SOLID-Prinzipien von allem anderen in der Codebasis stark unterschied und daher in einen dedizierten Namespace gestellt wurde, sind solche Fälle selten. Häufiger weist dies auf ein Problem hin. In ähnlicher Weise hindert nichts Sie daran, eine Klasse zu haben, die eine einzelne Methode enthält. Meistens weisen solche Klassen jedoch auf ein Problem hin.
Selbst wenn Ihr Namespace nur eine Klasse enthält, gibt es normalerweise eine Möglichkeit, beim Benennen der Klasse spezifischer und beim Benennen des Namespace allgemeiner vorzugehen. Stellen Sie sich eine Anwendung vor, die unter anderem zu einem bestimmten Zeitpunkt Dateien, die im ABC-Format geschrieben wurden, in das DEF-Format konvertieren soll. Die Konvertierung erfordert keine Deserialisierung / Serialisierung von / zu den Geschäftsobjekten und erfolgt durch Anwenden einer Reihe regulärer Ausdrücke, die kurz genug sind, um in die Konvertierungsklasse selbst gestellt zu werden
AbcToDefConverter
. Die gesamte Konvertierungslogik benötigt ungefähr 80 LLOC in ungefähr zehn voneinander abhängigen Methoden. Dies scheint eine Situation zu sein, in der es absolut nicht erforderlich ist, die vorhandene Klasse weder zu teilen noch zusätzliche Klassen zu erstellen. Da der verbleibende Teil der Anwendung nichts mit Konvertierungen zu tun hat, kann die Klasse nicht mit anderen Klassen in vorhandenen Namespaces gruppiert werden. So erstellt man einen Namespace namensAbcToDefConverter
. Daran ist zwar an sich nichts auszusetzen, man könnte aber auch einen allgemeineren Namen verwenden, wie zConverters
. In Sprachen wie Python, in denen kürzere Namen bevorzugt werden und Wiederholungen angewendet werden, kann dies sogar der Fall seinconverters.Abc_To_Def
.Daher tun für Namensräume unterschiedliche Namen verwenden als für die Klassen , die sie enthalten. Der Name einer Klasse sollte angeben, was die Klasse tut, während der Name des Namespaces die Gemeinsamkeiten aller darin enthaltenen Klassen hervorheben sollte.
Utility-Klassen sind übrigens von Natur aus falsch: Anstatt etwas Bestimmtes wie Arithmetik mit willkürlicher Genauigkeit zu enthalten, enthalten sie eher alles, was in anderen Klassen nicht seinen Weg gefunden hat . Dies ist einfach eine schlechte Benennung, genau wie ein
Miscellaneous
Verzeichnis auf einem Desktop - etwas, das auf die mangelnde Organisation hinweist.Die Benennung erfolgt aus einem Grund: um Ihnen das Leben zu erleichtern, wenn Sie später etwas suchen müssen. Wenn Sie ein Diagramm zeichnen müssen, versuchen Sie möglicherweise, nach "Diagramm" oder "Diagramm" zu suchen. Wenn Sie die Art und Weise ändern möchten, in der eine App Rechnungen erstellt, suchen Sie nach "Rechnung [e / ing]" oder "Rechnung". Stellen Sie sich einen Fall vor, in dem Sie sich sagen: "Hm, diese Funktion sollte wahrscheinlich in verschiedenen Anwendungen zu finden sein." Ich kann nicht
Sehen Sie sich .NET Framework an. Sind die meisten dieser Klassen keine Utility-Klassen? Ich meine, sie haben ein paar Dinge mit der Geschäftsdomäne zu tun. Wenn ich an einer Finanz-App, einer E-Commerce-Website oder einer Bildungsplattform der nächsten Generation arbeite, ist das Serialisieren von XML, das Lesen von Dateien, das Ausführen von SQL-Abfragen oder das Durchführen von Transaktionen alles Nützliche. Sie werden jedoch nicht
UtilitySerialization
oder aufgerufenUtilityTransaction
und befinden sich nicht imUtility
Namespace. Sie haben Eigennamen, die es ermöglichen (und dank .NET-Entwicklern ganz einfach!), Sie zu finden, wenn ich sie brauche.Dasselbe gilt für Ihre Klassen, die Sie normalerweise in Ihren Apps wiederverwenden. Sie sind keine Gebrauchsklassen. Es sind Klassen, die bestimmte Dinge tun, und die Dinge, die sie tun, sollten eigentlich die Namen der Klassen sein.
Stellen Sie sich vor, Sie haben Code erstellt, der sich mit Einheiten und der Umrechnung von Einheiten befasst. Sie können es benennen
Utility
und von Ihren Kollegen gehasst werden; oder du kannst es benennenUnits
undUnitsConversion
.quelle
Math
? Ich verstehe nicht, wie das Hinzufügen vonUtility
Suffixen zu allem unser Leben erleichtern würde. Würden Sie bei Verwendung der .NET-System.Math.Min()
Methode lieber schreibenSystemUtility.MathUtility.Min()
? In allen Fällen habe ich meine Antwort stark bearbeitet, daher sollte es jetzt klarer sein.