Wie verpacke ich einen Dienst, damit er einfacher ist?

11

Wir sind von einem Drittanbieter abhängig, der eine gigantische Schnittstelle bereitstellt, für die wir nur drei Methoden benötigen. Außerdem ändert sich die Benutzeroberfläche häufig ...

Ich habe beschlossen, die Schnittstelle in eine Klasse in unserem Projekt einzuschließen und nur die Methoden bereitzustellen, die wir benötigen.

Ich bin mir jedoch nicht sicher, wie ich mit den Rückgabewerten umgehen soll ... Die Schnittstelle gibt ein Objekt vom Typ zurück Storage. Wir haben intern einen Typ, StorageModelder unsere interne Darstellung von a ist Storage.

Was würden Sie im Mapper zurückgeben: Storageoder StorageModel? Wir haben einen DataService, StorageServiceder eine Abhängigkeit des injizierten Wrappers erhält.

Momentan mache ich es im Grunde so:

public class StorageService 
{
    private readonly IExternalStorageWrapper externalStorageWrapper;

    public StorageService(IExternalStorageWrapper externalStorageWrapper)
    {
        this.externalStorageWrapper = externalStorageWrapper;
    }

    public StorageModel GetStorage(int storageId)
    {
        return this.externalStorageWrapper.GetStorage(storageId).ConvertToStorageModel();
    }
}

public class ExternalStorageWrapper : IExternalStorageWrapper
{
    public Storage GetStorage(int storageId)
    {
        using(var ext = new ExternalStorage())
        {
            return ext.GetStorage(storageId);
        }
    }
}

Was würdest du sagen:

  • Ist es gut wie oben, dass der Wrapper das externe StorageObjekt und der interne das interne StorageServicezurückgibt StorageModel?
  • Oder würden Sie bereits eine StorageModelin der Verpackung zurückgeben?
Xeraphim
quelle
2
Warum nennst du es einen Wrapper? Achten Sie besser auf das Fassaden-, Brücken- und Adaptermuster. Soweit ich weiß, würde ein Wrapper alle Methoden des Drittanbieter-Dienstes bereitstellen - aber das ist nicht das, was Sie wollen.
Tobias Otto
@TobiasZu einem Wrapper muss nicht das gesamte Verhalten des umschlossenen Objekts verfügbar gemacht werden. Weitere Informationen finden Sie in diesem Artikel unter "Ein eingeschränkter Wrapper".
Guillaume31

Antworten:

11

Meiner Meinung nach sollte sich der Wrapper mit allen Dingen befassen, die mit der externen Bibliothek zusammenhängen. Dies bedeutet, dass die öffentliche Schnittstelle des Wrappers keine externen Typen benennen darf.

Das Zuordnen externer Typen zu den jeweiligen Typen Ihrer Anwendung ist Teil der Aufgaben des Wrappers. Wenn dies keine triviale Operation ist, können Sie die verschiedenen verfügbaren Tools verwenden, um das Problem zu zerlegen, z. B. das Injizieren eines Übersetzerobjekts. Der Übersetzer muss jedoch weiterhin Teil Ihres Wrapper-Moduls sein, und kein anderer Teil Ihrer Anwendung darf davon abhängen.

Auf diese Weise ist der Rest Ihrer Anwendung nicht nur gegen Änderungen in der Bibliothek, sondern auch gegen das Ersetzen der Bibliothek durch eine andere völlig immun.

doubleYou
quelle
3

Ich habe beschlossen, die Schnittstelle in eine Klasse in unserem Projekt einzuschließen und nur die Methoden bereitzustellen, die wir benötigen.

Das ist ok. Dies wird auch als Adapter bezeichnet .

Sie wählen das Adaptermuster , daher besteht das Ziel hier darin , eine Schnittstelle (Bibliotheksmodell) in eine andere (Domänenmodell) umzuwandeln . Wenn also etwas von dem ersteren das Domänenmodell erreicht, erfüllt der Adapter seinen Zweck nicht .

Gemäß den vorherigen Argumenten sollte der Adapter das zurückgeben StorageModel.

Letztendlich "spricht" Ihre Domain eine bestimmte Sprache, in der Storagesich ein Fremder befindet .

Aber ich bin mir nicht sicher, wie ich mit den Rückgabewerten umgehen soll ...

Der Schlüssel hier ist zu wissen, aus welchem ​​Grund Sie die Bibliothek verpacken / anpassen .

Adapter-, Dekorations- und Fassadenmuster haben möglicherweise Ähnlichkeiten, sind jedoch ziemlich unterschiedlich. So unterschiedlich wie die Probleme, die sie lösen.

Das heißt, Sie könnten auch interessiert sein an:

Laiv
quelle
1

Sie können eine Bibliothek nicht effektiv verpacken, indem Sie sie duplizieren.

Was Sie einschließen sollten, ist Ihre Nutzung der Bibliothek und das bedeutet, dass Sie keine Objekte verfügbar machen, in diesem Fall Speicher. Versuchen Sie auch nicht, sie zu duplizieren.

Verwenden Sie die Bibliothek, aber halten Sie sie enthalten. Wenn Sie also in Ihrem Fall den StorageService zum Speichern von Dingen verwenden, sollten Sie ihn in Repositorys verpacken

MyPocoObjectRepo
    MyPocoObject GetObject(string id);

Dabei ist MyPocoObject ausschließlich Ihre Daten- und Geschäftslogik. Keine Vervielfältigung von Speicher oder einem DataReader oder irgendetwas

Ewan
quelle
0

Die Antwort ist, dass es davon abhängt, ob Sie jemals Storagedirekt von einer Klasse aus zugreifen müssen, die es nicht ist StorageModel.

Wenn Sie die Bibliothek umbrechen möchten, ist es sinnvoll, auch das von ihr zurückgegebene Objekt zu umschließen, damit Sie in Zukunft Änderungen an der Bibliothek vornehmen können. Wenn Sie jedoch jemals Storagedirekt verwenden müssen, bedeutet dies, dass je nach Situation möglicherweise eine Rückkehr erforderlich ist Storage. Es könnte ein Argument dafür angeführt werden, dass die StorageVerwendung hier so vorgeschrieben ist, dass StorageModelSie wahrscheinlich während Ihres gesamten Programms konsistent bleiben möchten.

Ich würde Ihnen dringend empfehlen, sowohl die Benutzeroberfläche als auch das zurückgegebene Objekt zu verpacken, wenn Sie dies nicht bereits tun. Dies ist jedoch nur dann sinnvoll, wenn Sie es nur im StorageModelgesamten Programm verwenden und nicht Storage.

Neil
quelle