1. Statisch vs. Instanz
Ich denke, es gibt sehr klare Richtlinien darüber, was gutes OO-Design ist und was nicht. Das Problem ist, dass die Blogosphäre es schwierig macht, die Guten von den Schlechten und Hässlichen zu trennen. Sie können finden eine Art Referenz sogar die schlechteste Praxis unterstützen Sie denken können.
Und die schlimmste Praxis, die ich mir vorstellen kann, ist Global State, einschließlich der von Ihnen erwähnten Statik und des beliebtesten Singleton aller. Einige Auszüge aus dem klassischen Artikel von Misko Hevery zu diesem Thema .
Um die Abhängigkeiten wirklich zu verstehen, müssen Entwickler jede Codezeile lesen. Es verursacht Spooky Action in einiger Entfernung: Wenn Testsuiten ausgeführt werden, kann ein globaler Status, der in einem Test geändert wurde, dazu führen, dass ein nachfolgender oder paralleler Test unerwartet fehlschlägt. Unterbrechen Sie die statische Abhängigkeit mit der manuellen oder Guice-Abhängigkeitsinjektion.
Spooky Action in einiger Entfernung ist, wenn wir eine Sache ausführen, von der wir glauben, dass sie isoliert ist (da wir keine Referenzen übergeben haben), aber unerwartete Interaktionen und Zustandsänderungen an entfernten Orten des Systems auftreten, von denen wir dem Objekt nichts erzählt haben. Dies kann nur über den globalen Status geschehen.
Möglicherweise haben Sie das vorher nicht so gesehen, aber wenn Sie den statischen Status verwenden, erstellen Sie geheime Kommunikationskanäle und machen sie in der API nicht klar. Spooky Action at a Distance zwingt Entwickler, jede Codezeile zu lesen, um die möglichen Interaktionen zu verstehen, verringert die Entwicklerproduktivität und verwirrt neue Teammitglieder.
Daraus ergibt sich, dass Sie keine statischen Verweise auf Objekte bereitstellen sollten, die einen gespeicherten Status haben. Der einzige Ort, an dem ich Statik verwende, ist für aufgezählte Konstanten, und ich habe sogar darüber Bedenken.
2. Methoden mit Eingabeparametern und Rückgabewerten im Vergleich zu Methoden ohne
Sie müssen sich darüber im Klaren sein, dass Methoden ohne Eingabe- und Ausgabeparameter so gut wie garantiert in einem intern gespeicherten Zustand arbeiten (was tun sie sonst?). Es gibt ganze Sprachen , die auf der Idee aufbauen, einen gespeicherten Zustand zu vermeiden.
Jedes Mal, wenn Sie den Status gespeichert haben, haben Sie die Möglichkeit von Nebenwirkungen, stellen Sie also sicher, dass Sie ihn immer mit Bedacht anwenden. Dies bedeutet, dass Sie Funktionen mit definierten Ein- und / oder Ausgängen bevorzugen sollten .
Tatsächlich sind Funktionen mit definierten Ein- und Ausgängen viel einfacher zu testen. Sie müssen hier keine Funktion ausführen und dort nachsehen, um zu sehen, was passiert ist, und Sie müssen keine Eigenschaft irgendwo festlegen bevor Sie die zu testende Funktion ausführen.
Sie können diese Art von Funktion auch sicher als Statik verwenden. Das würde ich aber nicht tun, denn wenn ich später irgendwo eine etwas andere Implementierung dieser Funktion verwenden wollte, anstatt mit der neuen Implementierung eine andere Instanz bereitzustellen, kann ich die Funktionalität nicht ersetzen.
3. Überlappung vs.
Ich verstehe die Frage nicht. Was wäre der Vorteil bei 2 überlappenden Methoden?
4. Privat gegen öffentlich
Belichten Sie nichts, was Sie nicht belichten müssen. Allerdings bin ich auch kein großer Fan von Privat. Ich bin kein C # -Entwickler, sondern ein ActionScript-Entwickler. Ich habe viel Zeit mit dem Flex Framework-Code von Adobe verbracht, der um 2007 geschrieben wurde. Und sie haben einige wirklich schlechte Entscheidungen getroffen, was das Privatisieren zum Albtraum macht, wenn sie versuchen, ihre Klassen zu erweitern.
Wenn Sie also nicht glauben, dass Sie ein besserer Architekt sind als die Adobe-Entwickler um 2007 (Ihrer Frage nach haben Sie wahrscheinlich noch ein paar Jahre Zeit, um diesen Anspruch geltend zu machen), möchten Sie wahrscheinlich nur standardmäßig geschützt werden .
Es gibt einige Probleme mit Ihren Codebeispielen, die bedeuten, dass sie nicht gut strukturiert sind. Daher ist es nicht möglich, A oder B auszuwählen.
Zum einen sollten Sie Ihre Objekterstellung wahrscheinlich von ihrer Verwendung trennen . Normalerweise haben Sie also kein new XMLReader()
Recht in der Nähe des Verwendungsorts.
Wie @djna sagt, sollten Sie auch die in Ihrem XML Reader verwendeten Methoden einkapseln, damit Ihre API (Instanzbeispiel) vereinfacht werden kann:
_document Document = reader.read(info);
Ich weiß nicht, wie C # funktioniert, aber da ich mit einer Reihe von Webtechnologien gearbeitet habe, würde ich den Verdacht haben, dass Sie ein XML-Dokument nicht immer sofort zurückgeben können (außer vielleicht als Versprechen oder zukünftiger Typ) Objekt), aber ich kann Ihnen keinen Rat geben, wie mit einer asynchronen Last in C # umgegangen werden soll.
Beachten Sie, dass Sie mit diesem Ansatz mehrere Implementierungen erstellen können, die einen Parameter verwenden, der angibt, wo / was gelesen und ein XML-Objekt zurückgegeben werden soll, und diese basierend auf Ihren Projektanforderungen austauschen können. Beispielsweise können Sie direkt aus einer Datenbank, einem lokalen Geschäft oder, wie in Ihrem ursprünglichen Beispiel, aus einer URL lesen. Sie können das nicht tun, wenn Sie eine statische Methode verwenden.