Ich diskutiere ein wenig über die Verwendung verschachtelter Klassen. Die Situation besteht darin, dass ein Klassenname sinnvoll ist, um an zwei oder mehr Stellen wiederholt zu werden, und obwohl zwischen jeder der Instanzen eine gemäßigte Ähnlichkeit besteht, sind sie im Allgemeinen unterschiedlich. Die verschachtelten Klassen werden (wenn überhaupt) nicht oft über den Bereich ihrer Elternklasse hinaus benötigt.
Also, anstatt nur drei verschiedene Klassennamen zu nennen, scheint das für mich mehr Sinn zu ergeben.
%Vor%Das offensichtliche Problem dabei ist nicht die Funktionalität, sondern die Konsistenz / Wiederholung. Ich habe mich gefragt, ob andere Entwickler jemals mit der gleichen Sache gekämpft haben, und was einige der Meinungen waren.
Der .NET-Designleitfaden rät davon ab :
Das tut es auch in der Basisklassenbibliothek: Im Namensraum System.Web.UI
haben Sie DataGridItem
, DataListItem
, ListViewItem
, MenuItem
, RepeaterItem
usw. Alle diese könnten% genannt werden co_de% und verschachtelt in Item
, DataGrid
usw. Dies würde jedoch die beiden oben beschriebenen Prinzipien verletzen.
Es sieht gut aus, wenn deine Klassen klein sind. Sobald sie aufgebläht sind, beginnen Sie wirklich darüber nachzudenken, sie in separate Dateien zu verschieben.
Mehr zu Ihrem Punkt, wenn Sie sowohl A.B als auch M.B im selben Code verwenden möchten, müssen Sie immer A.B und M.B eingeben, was ein Schmerz sein kann.
Wenn die Klasse B
Ähnlichkeiten zwischen jeder inneren Klasseninstanz aufweist, wäre es sinnvoll, die Ähnlichkeiten von B
zu einer Basisklasse zu abstrahieren, die neben A
, M
und Q
existiert. ? (Ich denke schon.) Dann wären deine inneren Klassen, obwohl sie den gleichen Namen haben könnten, etwas sauberer.
Dieser Strukturtyp kann für Dinge wie Metadaten in einer MVC-Anwendung gesehen werden. In diesem Fall haben Sie etwas wie:
%Vor% In diesem Fall dienen die inneren Klassen jeweils demselben Zweck, aber ihre Implementierungen variieren mit jeder Elternklasse. Mit den Metadata
-Definitionen ist es auch sehr sinnvoll, eine Klasse beizubehalten, die hilft, ihr Elternteil als innere Klasse zu beschreiben. Wenn es eine Chance gibt, dass du die inneren Klassen woanders wiederverwenden willst, dann würde ich sie außerhalb ihrer Eltern bewegen.
Ich denke, es ist etwas untypisch, dies in der Praxis anders zu sehen. Ich bin mir sicher, dass es gute Beispiele gibt, aber ich wette, es gibt mehr schlechte Beispiele für diese Art von Mustern.
Ich würde sagen, es ist manchmal in Ordnung, aber normalerweise kein gutes Design, private verschachtelte Klassen zu verwenden. Ich habe einmal eine vorhandene sehr große Klasse in meinem Projekt umgestaltet, um ihr private verschachtelte Klassen zu geben. Der Grund, warum ich das getan habe, war, dass einige Methoden Dutzende von Parametern brauchten, und dies gab ihnen eine logischere Gruppierung. In diesem Sinne sehe ich verschachtelte Klassen als eine gute schnelle Lösung. Es machte Sinn, weil niemand außerhalb dieser Klasse irgendeinen Nutzen für diese Felder hatte.
Im Allgemeinen würde ich in einem ersten Entwurf geschachtelte Klassen scheuen - und denke zweimal darüber nach, sie in einem Redesign zu berücksichtigen. Wenn Sie in der Wartung Zeit haben, ist es besser, die gesamte Klasse neu zu entwerfen und sie in separate Klassen in separaten Dateien aufzuteilen, die intern sind.
Ich denke, diese Strategie ist auch besser für testability als die Verwendung verschachtelter Klassen. Aufgrund der größeren Abhängigkeiten von der äußeren Klasse und anderen Klassen in der Anwendung waren meine refaktorierten geschachtelten Klassen nicht viel einfacher als die ursprüngliche große Klasse, die viele Parameter umgab. Wenn Sie verschachtelte Klassen teilen, so dass sie eigenständig sind, können Sie mehr diskrete Komponententests schreiben, die tatsächlich Einheiten testen , anstatt die Komponententests für die äußere Klasse und die innere Klasse effektiv zu kombinieren. Dies gibt Ihnen mehr Zuversicht, wenn Sie sagen: "Ja, die innere Klasse arbeitet auf der Unit-Test-Ebene" und "Ja, die äußere Klasse arbeitet auf der Unit-Test-Ebene" (die auch testet, wie es mit der inneren Klasse zusammenpasst, z in Berechnungsformeln).
Ich verstehe, dass Ihre Probe erfunden ist. Wenn Ihre Klassennamen jedoch ähnlich genug oder identisch sind, sollten Sie sie eigentlich nicht zu verschachtelten Klassen machen. Als allgemeine Regel sollten Sie geschachtelte Klassen überhaupt verwenden .
Wenn ich mich richtig erinnere, empfehlen die .NET Framework-Richtlinien gegen , geschachtelte Klassen zu verwenden. Benutzungsrichtlinien für geschachtelte Typen ist ein wenig alt (zurück zur Version 1.1), aber die Prinzipien gelten immer noch.
Verwenden Sie keine verschachtelten Typen, wenn Folgendes zutrifft:
- Der Typ muss vom Client-Code instanziiert werden. Wenn ein Typ a hat öffentlichen Konstruktor sollte es wahrscheinlich nicht verschachtelt sein. Das Grundprinzip hinter dieser Richtlinie ist, dass, wenn ein verschachtelter Typ instanziiert werden kann gibt an, dass der Typ selbst einen Platz in der Bibliothek hat. Sie können erschaffe es, benutze es und zerstöre es, ohne den äußeren Typ zu benutzen. Daher sollte es nicht verschachtelt sein. Ein innerer Typ sollte nicht weit verbreitet sein wiederverwendet außerhalb des äußeren Typs ohne eine Beziehung zum Äußeren Geben Sie ein.
- Verweise auf den Typ werden häufig im Client-Code deklariert.
Nun können Sie Namespaces verwenden, um auch solche Dinge zu tun (erstellen Sie einfach einen neuen Ordner in VS). Was ist besser für die Organisation und wird Ihnen das gleiche Ergebnis geben.
Aber wenn die Unterklasse nur für die Elternklasse relevant ist, sehe ich keinen Schaden darin.
Andererseits, wenn Sie sie dasselbe nennen, würde ich annehmen, dass sie einen ähnlichen Tropfen machen und Sie vielleicht in die Abstraktion schauen wollen, vielleicht könnten Ihre Elternklassen auch anders gemacht werden. Wirklich hängt davon ab, was Sie tun müssen, obwohl
Ich mache das gerne, für mich macht es den Gebrauch klarer und vor allem das Finden von Namen weniger problematisch. Aber normalerweise versuche ich dies auf private Klassen oder öffentliche enums zu beschränken. Zum Beispiel
%Vor%oder
%Vor%Erstellen Sie keine verschachtelte Klasse, wenn es eine Chance (oder einen Geschäftsgrund) gibt, dass Sie sie an einem anderen Ort verwenden müssen (verwenden Sie stattdessen Namespace und zögern Sie nicht, eine Klasse mit einem langen Namen zu erstellen ).
Zum Beispiel verwende ich eine verschachtelte Klasse für DTO zwischen meinem Controller und meiner Ansicht oder in einer Klasse, um einen Cache-Eintrag darzustellen.
Wenn Sie sie gleich nennen wollen, aber unterschiedliche Typen haben, können Sie verschiedene Namensräume verwenden.
%Vor%Dies führt zu zwei verschiedenen Typen, obwohl die Klassen gleich benannt sind.
Es hängt wirklich von der Funktionalität der geschachtelten Klasse ab. Das ist sehr ähnlich zu der Art und Weise, wie die C ++ - STL den Iterator in jeder Klasse unterschiedlich definierte. Es ist nichts falsch mit der Praxis per se, solange das Konzept von jedem wirklich auf der umfassenden Klasse basiert.
Es kann etwas mit Stil und Geschmack zu tun haben, aber persönlich sehe ich kein Problem, solange sie wirklich unterschiedlich sind und von der Definition der Kapselklasse abhängen. Es wird jedoch eher verwirrend, wenn sie außerhalb der Klasse öffentlich sichtbar sind. Daher würde ich die Klassen nicht persönlich öffentlich machen.
An geschachtelten Klassen ist nichts falsch, solange Sie sich an folgende Faustregeln halten:
Nie öffentlich oder intern. Es gibt spezielle Fälle, z. B. wenn Sie IEnumerator mit einer geschachtelten Klasse implementieren. Aber selbst dann sollte die Klasse selbst privat gehalten werden, da Instanzen davon als IEnumerator zurückgegeben werden, und es wird nur so getan, um zu vermeiden, dass der Namespace mit Klassen, die nicht instanziiert werden sollen, verschachtelt wird. p>
Halte sie klein. Eine private verschachtelte Klasse, die wirklich nur zum Organisieren und Weiterleiten von Daten verwendet wird, ist in Ordnung und kann manchmal ein sehr nützliches Werkzeug sein. (Nicht ganz unähnlich, wie anonyme Klassen nützlich sind.) Aber wenn Sie versuchen, große Teile der Funktionalität zu paketieren, wird es zu einem Code-Geruch, der darauf hindeutet, dass Sie stattdessen eine Umgestaltung der äußeren Klasse in Erwägung ziehen sollten.
Tags und Links c# design-patterns