Ich habe vor ein paar Monaten Onkel Bobs Clean Code gelesen und er hatte tiefgreifende Auswirkungen auf die Art und Weise, wie ich Code schreibe. Selbst wenn es so aussah, als würde er Dinge wiederholen, die jeder Programmierer wissen sollte, führt das Zusammenfügen und Umsetzen dieser Dinge zu einem viel saubereren Code. Insbesondere empfand ich es als unglaublich nützlich, große Funktionen in viele kleine Funktionen und große Klassen in viele kleine Klassen aufzuteilen.
Nun zur Frage. Die Beispiele des Buches sind alle in Java, während ich in den letzten Jahren in C ++ gearbeitet habe. Wie würden sich die Ideen in Clean Code auf die Verwendung von Namespaces auswirken, die in Java nicht vorhanden sind? (Ja, ich kenne die Java-Pakete, aber es ist nicht wirklich dasselbe.)
Ist es sinnvoll, die Idee, viele kleine Einheiten mit jeweils klar definierter Verantwortung zu erstellen, auf Namespaces anzuwenden? Soll eine kleine Gruppe zusammengehöriger Klassen immer in einen Namespace eingeschlossen werden? Ist dies der Weg, um die Komplexität von vielen kleinen Klassen zu verwalten, oder wären die Kosten für die Verwaltung vieler Namespaces unerschwinglich?
Bearbeiten: Meine Frage wird in diesem Wikipedia-Eintrag über Paketprinzipien beantwortet .
Antworten:
(Ich habe Clean Code nicht gelesen und kenne nicht viel Java.)
Ja, genau wie beim Refactoring in mehrere Klassen und Funktionen.
Ohne tatsächlich zu antworten: Ja, Sie sollten mindestens einen Namespace der obersten Ebene verwenden. Dies kann auf Projekt, Organisation oder was auch immer basieren, aber die Verwendung weniger globaler Namen verringert Namenskonflikte. Ein einziger Namespace, in dem alle anderen Elemente gruppiert werden, führt nur einen globalen Namen ein. (Ausgenommen externe "C" -Funktionen, dies liegt jedoch an der C-Interoperabilität und wirkt sich nur auf andere externe "C" -Funktionen aus.)
Sollte eine kleine Gruppe verwandter Klassen in einen ihnen gewidmeten Namespace eingeschlossen werden? Wahrscheinlich. Besonders wenn Sie feststellen, dass Sie ein gemeinsames Präfix für diese Klassen verwenden - FrobberThing, FrobberThang, FrobberDoohickey - sollten Sie einen Namespace in Betracht ziehen - frobber :: Thing und so weiter. Dies würde sich immer noch unter Ihrem Stamm-Namespace oder einem anderen Namespace befinden, wenn sie Teil eines größeren Projekts sind.
Anhand des obigen Beispiels für Präfixnamen ist es nicht schwieriger, frobber :: Thing als FrobberThing zu verwalten. Mit einigen Tools wie Dokumentation und Code-Vervollständigung kann es sogar einfacher sein. Es gibt einen Unterschied zu ADL, aber dies kann zu Ihren Gunsten funktionieren: Weniger Namen in zugeordneten Namespaces vereinfachen das Herausfinden von ADL, und Sie können mithilfe von Deklarationen bestimmte Namen in den einen oder anderen Namespace einfügen.
Mit Namespace-Aliasnamen können Sie einen kürzeren Namen für einen längeren Namespace in einem bestimmten Kontext verwenden, was wiederum eine einfachere Verwendung ermöglicht:
Betrachten Sie Boost, das einen einzigen Root-Namespace, boost und dann viele Subnamespaces - boost :: asio, boost :: io, boost :: filesystem, boost :: tuples usw. - für verschiedene Bibliotheken hat. Einige Namen werden in den Root-Namespace "befördert" :
Der größte Unterschied zu Sprachen mit "echten" Modulen besteht darin, wie häufig eine flachere Struktur verwendet wird. Dies geschieht meistens, weil dies so funktioniert, es sei denn, Sie nehmen zusätzliche, spezifische Anstrengungen in Kauf, um verschachtelte Namen zu definieren.
quelle
Sie sollten einen Master-Namespace für Ihren gesamten Code haben. Dies unterscheidet es von externem Code in Bezug auf Namespaces.
In Ihrem Master-Namespace können Sie abhängig von der Größe und Komplexität Unter-Namespaces öffnen. Hier bedeuten Namen eindeutig etwas in einem Kontext, und dieselben Namen können in einem anderen Kontext verwendet werden.
Insbesondere wenn Sie einen allgemein klingenden Namen wie FileInfo haben, der etwas Bestimmtes in einem Kontext bedeutet, setzen Sie ihn in einen Namespace.
Sie können dazu auch eine Klasse verwenden, obwohl eine Klasse nicht erweiterbar ist, sodass Sie der Klasse keine neuen Deklarationen hinzufügen können, ohne ihren Header zu ändern.
quelle
Namespaces sind kein Modulkonzept, daher würde ich sie nur dort verwenden, wo Namenskonflikte auftreten können.
quelle
Java hat Namespaces, die werden einfach nicht so genannt. In
javax.swing.*
javax
ist ein Namespace undswing
ist ein Subnamespace. Ich habe das Buch nicht gelesen, um zu wissen, was es über Java-Pakete aussagt, aber die gleichen Prinzipien gelten so ziemlich direkt für Namespaces in jeder Sprache.Eine gute Heuristik ist, dass Sie einen Namespace verwenden, wenn Sie feststellen, dass Sie immer wieder dasselbe Präfix für Klassen eingeben möchten. Ich habe zum Beispiel kürzlich einige Klassen mit den Namen OmciAttribute, OmciAlarm, OmciMe usw. geschrieben und festgestellt, dass ich Omci in einen eigenen Namespace unterteilen muss.
quelle
Ich mag tiefe Namespaces (was normalerweise drei Ebenen bedeutet).
Abhängig von der Situation kann ich eine weitere Stufe haben
quelle