Come posso concludere un servizio in modo che sia più semplice


11

Abbiamo una dipendenza da un servizio di terze parti che espone una gigantesca interfaccia di cui abbiamo bisogno solo di 3 metodi. Inoltre, l'interfaccia cambia frequentemente ...

Ho deciso di racchiudere l'interfaccia in una classe nel nostro progetto ed esporre solo i metodi di cui abbiamo bisogno.

Ma non sono sicuro di come dovrei gestire i valori di ritorno ... L'interfaccia restituisce un oggetto di tipo Storage. Internamente abbiamo un tipo StorageModelche è la nostra rappresentazione interna di a Storage.

Cosa vorresti restituire nel mapper: Storageo StorageModel? Abbiamo un DataService StorageServiceche ottiene una dipendenza del wrapper iniettato.

Attualmente lo sto facendo sostanzialmente così:

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);
        }
    }
}

Cosa vorresti dire:

  • È buono come sopra, che il wrapper restituisca l' Storageoggetto esterno e quello interno StorageServicerestituisca quello interno StorageModel?
  • O restituiresti già un StorageModelnell'involucro?

2
Perché lo chiami wrapper? Cercare meglio il modello di facciata, ponte e adattatore. A quanto ho capito, un wrapper fornirebbe tutti i metodi del servizio di terze parti, ma non è quello che desideri.
Tobias Otto,


@TobiasOtto un wrapper non ha bisogno di esporre tutto il comportamento dell'oggetto avvolto, vedi questo articolo in "Un wrapper limitato".
guillaume31,

Risposte:


11

Nella mia opinione, il wrapper dovrebbe occuparsi di tutte le cose relative alla libreria esterna. Ciò significa che l'interfaccia pubblica di Wrapper non deve nominare alcun tipo esterno.

La mappatura dei tipi esterni ai rispettivi tipi dell'applicazione è parte delle funzioni del wrapper. Se questa non è un'operazione banale, è possibile utilizzare i vari strumenti disponibili per scomporre il problema, ad esempio iniettando un oggetto traduttore. Tuttavia, il traduttore deve comunque far parte del modulo wrapper e nessun'altra parte dell'applicazione può dipendere da esso.

In questo modo, il resto della tua applicazione è completamente immune non solo ai cambiamenti nella libreria, ma anche alle sostituzioni della libreria con un'altra.


3

Ho deciso di racchiudere l'interfaccia in una classe nel nostro progetto ed esporre solo i metodi di cui abbiamo bisogno.

Va bene. Questo è anche noto come adattatore .

Scegli il modello Adapter , quindi l'obiettivo è quello di trasformare un'interfaccia (modello di libreria) in un'altra (modello di dominio). Quindi, se qualcosa dal primo raggiunge il modello di dominio, l'adattatore non riesce al suo scopo .

Secondo gli argomenti precedenti, l'adattatore dovrebbe restituire il file StorageModel.

In definitiva, il tuo dominio "parla" una lingua specifica, dove Storageè estraneo .

Ma non sono sicuro di come dovrei gestire i valori di ritorno ...

La chiave qui è sapere per quale motivo stai avvolgendo / adattando la libreria .

I motivi Adapter, Decorator, Facade potrebbero avere somiglianze ma sono abbastanza diversi. Diversi come i problemi che risolvono.

Detto questo, potresti essere interessato anche a:


1

Non è possibile avvolgere efficacemente una libreria duplicandola.

Quello che dovresti avvolgere è l'utilizzo della libreria e questo significa non esporre oggetti, in questo caso Archiviazione. Non provare nemmeno a duplicarli.

Usa la libreria, ma tienila contenuta. Quindi, nel tuo caso, supponendo che tu stia utilizzando StorageService per archiviare le cose, dovresti avvolgerlo in repository

MyPocoObjectRepo
    MyPocoObject GetObject(string id);

dove MyPocoObject è interamente i tuoi dati e la tua logica aziendale. Non una duplicazione di archiviazione o un DataReader o altro


0

La risposta è che dipende dalla necessità o meno di accedere Storagedirettamente da una classe che non lo è StorageModel.

Se hai intenzione di avvolgere la libreria, ha senso anche avvolgere l'oggetto restituito per consentirti di apportare modifiche a prova di futuro apportate dalla libreria in futuro. Tuttavia, se hai mai bisogno di utilizzare Storagedirettamente, significa che potrebbe essere necessario tornare in Storagebase alla situazione. Un argomento potrebbe essere detto per obbligare l' Storageuso qui StorageModelcome è probabile che tu voglia rimanere coerente durante il tuo programma.

Consiglio vivamente di avvolgere sia l'interfaccia che l'oggetto restituito se non lo stai già facendo, anche se di nuovo, questo ha senso solo se lo usi solo StorageModeldurante il tuo programma e non Storage.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.