2009-04-03 10 views
2

ich ziemlich neu bin auf all dies, so ist dies wahrscheinlich OOP 101, aber ich kann meinen Kopf nicht drum herum kommen, gelten folgende Voraussetzungen C# -Code lebt in einer Baugruppe:Objekte erstellen, ohne Verkapselung zu brechen

internal interface IDataStore 
{ 
    void Store(string name, object data); 
    object Retrieve(string name); 
} 

internal class DBStore : IDataStore 
{ 
    public DBStore(string connection) { } 
    public void Store(string name, object data) { } 
    public object Retrieve(string name) { } 
} 

public class GizmoManager 
{ 
    public GizmoManager(IDataStore dataStore) { } 
    // Other stuff 
} 

public class WidgetManager 
{ 
    public WidgetManager(IDataStore dataStore) { } 
    // Other stuff 
} 

Wenn eine zweite Assembly versucht, einen GizmoManager und einen WidgetManager zu erstellen, kann sie dies nicht tun, da sie keinen DBStore erreichen kann (da sie intern nicht öffentlich ist).

Die folgenden nicht AFAICS arbeiten:

  • DBStore und IDataStore öffentlich machen. Schlecht, weil die Client-Assembly dann GizmoManager/WidgetManager umgehen und auf die Datenbank zugreifen kann, wie sie möchte.
  • Geben Sie keinen IDataStore an die Konstruktoren GizmoManager und WidgetManager weiter. Schlecht, weil es die Testbarkeit verringert (Sie können einen MockDataStore nicht einfach weitergeben).
  • Machen Sie etwas Magie mit Fabriken. Scheint nichts zu lösen, da Sie denselben IDataStore sowohl an GizmoManager als auch an WidgetManager übergeben müssen und die Client-Assembly daher immer noch einen IDataStore einer Variablen zuweisen muss (was nicht möglich ist, da IDataStore intern ist).

Dies ist wahrscheinlich erstaunlich offensichtlich, aber ich kann es einfach nicht sehen. Wie würde man diesen Widerspruch überwinden?

TIA.

Antwort

1

Machen Sie IDataStore und DBStore öffentlich, aber machen Sie den DBStore-Konstruktor intern. Dann hat Assembly 1 vollständige Kontrolle darüber, wann DBStores instanziiert wird, aber Assembly 1 kann auf den DBStore zugreifen und ihn übergeben.

Ich kann mir vorstellen, dass Sie dann eine Factory in Assembly 1 möchten, die die Anzahl oder Konfiguration der DBStore-Instanzen begrenzt, die erstellt werden.

3

Einfach die Schnittstelle IDataStore öffentlich machen. Auf diese Weise können Clients Ihre Klassen WidgetManager und GizmoManager mit Mock-Objekten instanziieren, die sie selbst erstellen.

auf der Umsetzung Fabrik Klasse von Entwurfsmustern Schaffung von GiszmoManager und WidgetManager Objekten von Client-Code zu ermöglichen. Auf diese Weise kann Client-Code niemals ein DBStore Objekt erstellen, so dass sie Ihre Manager niemals umgehen können.

BTW: Warum stören Sie die Kapselung? Dies kann sinnvoll sein, wenn Sie sich im proprietären Frameworks-Geschäft befinden, aber ansonsten YAGNI.

0

Sie können die Schnittstelle und Klassen public machen, aber die Methoden zum direkten Zugriff auf die Datenbank internal machen. Auf diese Weise instanziieren Sie eine Instanz von DBStore, ohne Zugriff auf Methoden zuzulassen, die anderen Baugruppen nicht erlaubt sind.

internal Methoden sind nur für Klassen in derselben Baugruppe sichtbar.

Ich würde lieber überprüfen, ob es keine Möglichkeit gibt, Ihre Objekte zu montieren, ohne ein DBStore jedes Mal instanziieren zu müssen. Vielleicht ein Fabrikmuster oder eine Abhängigkeitsinjektion? Dann können Sie Ihre Schnittstelle öffentlich machen und eine Factory in der ersten Assembly instanziieren lassen.Dies wirkt sich nicht auf die Testbarkeit aus, reduziert jedoch die von Ihnen erstellten Objektinstanzen. Weniger new XYZ() Anweisungen ist besser ...

0

Machen Sie DBStore public, aber machen Sie alle Mitglieder, die Sie nicht privat oder intern offen legen wollen. Dann ... Option 1: Entfernen Sie alle Mitglieder aus IDataStore, auf die Sie außerhalb der Assembly nicht zugreifen möchten, und machen Sie IDataStore öffentlich. Option 2: Benennen Sie IDataStore in IDataStoreInternal um und machen Sie es von einer neuen öffentlichen IDataStore-Schnittstelle erben, die keine Mitglieder (oder nur Mitglieder, die extern verfügbar gemacht werden sollen) hat.

0

Ich mag beides:

  • Geben Sie es nicht in einem IDataStore den GizmoManager und Widget Bauer. Schlecht, weil es die Testbarkeit reduziert (Sie können einen MockDataStore nicht einfach weitergeben).
  • Machen Sie etwas Magie mit Fabriken. Scheint nicht alles zu lösen, weil Sie die gleiche IDataStore passieren müssen sowohl GizmoManager und Widget und damit den Kunden Montage noch Bedürfnisse ein IDataStore zu einer Variablen zugewiesen werden (was es nicht, weil IDataStore ist intern).

Testbarkeit zu lösen, aber die Umsetzung verstecken, bieten die öffentliche Schnittstelle sollte nur die Möglichkeit, ob die Geschäfte usw. leben, prüfbar, Pre-prod sein sollte, so Sie die Verantwortung für die korrekte IDataStore Konstruktion an eine andere Partei übertragen könnte das ist in der Versammlung. Z.B. ein Factory-Konzept, das nur "Testing", "Deploy", "Debug" usw. erlaubt. Verfügen über Standardkonstruktoren (oder Singletons oder was auch immer), die bei der "mode" -Einstellung intern auf die Werkseinstellung für den korrekten Speicher verweisen.

Verwandte Themen