Il wrapping di una libreria di terze parti è una buona pratica [duplicato]

10

Mi sono imbattuto nelle seguenti affermazioni leggendo Pulisci libro codici di Robert C. Martin.

Chapter : 7 : Error Handling
Page No : 109
..In fact, wrapping third-party APIs is a best practice. When you wrap a third-party API, you minimize your dependencies upon it: You can choose to move to a different library in the future without much penalty. Wrapping also makes it easier to mock out third-party calls when you are testing your own code.

One final advantage of wrapping is that you aren’t tied to a particular vendor’s API design choices. You can define an API that you feel comfortable with.

Sono abbastanza confuso riguardo alla parte grassetto .

Sono totalmente all'oscuro di come possiamo passare a una libreria diversa così facilmente se avvolgiamo la libreria di terze parti e come il testing diventa facile con esso?

    
posta CoderCroc 24.09.2015 - 14:19
fonte

6 risposte

16

Immagina di avere una libreria complicata da cui dipendere. Supponi che la libreria esponga quattro diverse chiamate alla sua funzionalità e che la tua base di codice utilizzi ognuna di esse tre volte.

Se utilizzi l'API del fornitore grezzo nel tuo codice, se la libreria del fornitore cambia o devi sostituirla, dovrai modificare dodici chiamate API nel tuo codice base. Se avessi un livello di astrazione tra il codice e il codice, dovresti modificare quattro posizioni nel livello di astrazione e nessuno nella tua base di codice. È possibile notare che ciò consente di risparmiare: maggiore è il numero di chiamate che l'API offre. E la maggior parte delle API del mondo reale offre più di quattro punti di accesso.

    
risposta data 24.09.2015 - 14:23
fonte
13

Oltre all'eccellente risposta di Killian Foth, prendi in considerazione alcuni problemi con il codice di test che utilizza le API:

  • Il test è difficile perché l'API fa qualcosa di "reale" . Immagina di voler testare il tuo codice che utilizza un'API che effettua un pagamento con carta di credito. Se ogni volta che esegui il tuo codice, si ottiene una transazione reale, che sarà un grosso limite per il tuo test.
  • Il test è difficile perché non puoi controllare le informazioni restituite dall'API.
    • Il tuo codice dovrebbe fare qualcosa di speciale a Natale, ma l'API restituisce solo la data corrente. Aspetta fino a Natale per testare quella funzione?
    • Vuoi testare la gestione di un milione di indirizzi email, ma questi provengono da una piattaforma esterna che ha solo pochi utenti di test. Aggiungi manualmente un milione di utenti di test a quella piattaforma?
    • Il tuo codice utilizza l'API GPS del telefono per ottenere la posizione corrente e quindi impostare la lingua di conseguenza. Devi effettivamente andare in diversi paesi per vedere se funziona?

Potrebbero essere creati molti altri esempi, ma tu hai l'idea. Tutti questi problemi sono risolti da wrapping the API . Quindi puoi sostituire l'API effettiva con una versione di prova che restituisce tutto ciò che vuoi a scopo di test.

    
risposta data 24.09.2015 - 14:51
fonte
11

Hai ragione ad essere sospettoso. Non ho letto questo libro, ma personalmente non sono d'accordo con questo consiglio.

Questo approccio aggiunge sia il codice aggiuntivo che l'ulteriore astrazione.

Il codice può aggiungere bug e spese generali.

Le astrazioni hanno il loro limite e il povero maintainer ora deve capire sia la biblioteca che l'astrazione in cima per fare il suo lavoro.

L'astrazione è difficile: o imita la libreria API sottostante quasi 1: 1, e a questo punto questa "astrazione" non è più una. Oppure crei la tua API che sicuramente non corrisponderà al design della libreria che stai utilizzando o alla futura libreria che vorresti usare in futuro. Nella base di codice su cui sto lavorando in questo momento, c'è una tale astrazione sul parser XML che stiamo usando. Abbiamo un noto problema di prestazioni, in cui l'astrazione deve mantenere un elenco di tutti i nodi e scorrere ripetutamente su di esso per soddisfare l'API dell'astrazione. Sono passati più di 10 anni che dipendiamo da questa specifica lib di terze parti, e non abbiamo mai avuto la necessità di cambiarla. Rimuovere questa orribile astrazione è nella mia lista delle cose da fare ...

Inoltre, le librerie di terze parti sostituite sono un'eccezione e non la regola. Questo consiglio ti chiede di fare un po 'di lavoro in anticipo, con tutti gli svantaggi che ho delineato sopra, per un caso che è improbabile che accada.

Riguardo alla parte "mocking call to 3rd party lib", non riesco a pensare a un caso in cui mi serva per deridere una libreria. Potrei essere un po 'miope, qui.

    
risposta data 24.09.2015 - 14:45
fonte
5

Sento che spesso questa pratica può essere usata male.

Ad esempio, supponiamo che tu stia utilizzando il client MongoDB per accedere al tuo database Mongo. Racchiudere il client stesso mentre espone ancora tutte le sue funzionalità è piuttosto difficile. Dovrai implementare un oggetto query e trasformarlo in uno propiziatorio ecc. È un sacco di lavoro e se cambi il client più tardi potresti scoprire che il nuovo segue un modello completamente diverso e le tue interfacce e le classi wrapper sono non è più appropriato.

Tuttavia, si desidera essere in grado di iniettare oggetti simulati ecc. per il test e in genere evitare di rendere altre cose dipendenti dalla libreria di terze parti.

Questo può ancora essere ottenuto se ti sposti a un livello più alto, ad esempio seguendo il pattern del repository. Con il wrapping a questo livello superiore eviti di dover gestire tutti i dettagli della libreria di terze parti e puoi esporre un'interfaccia limitata e costante che è rilevante per il tuo codice, piuttosto che il codice esterno che stai avvolgendo.

    
risposta data 24.09.2015 - 14:52
fonte
3

Ci sono opinioni divergenti espresse, ma dubito che le persone siano fondamentalmente in disaccordo.

Il punto è che le API wrapping possono essere le migliori pratiche.

  1. Se l'interfaccia dell'API è banale, allora non ha senso chiuderla. Lo stesso se l'interfaccia è stabile, non interferisce con il testing e non è molto più complicata di quella che ti serve.
  2. Se l'interfaccia è complicata e si utilizza solo un sottoinsieme, utilizzare un wrapper. Ad esempio, un framework di registrazione avanzato in cui si desidera sempre registrare le cose nello stesso formato e tutto ciò che si usa nell'app è LogError , LogWarn , LogInfo e LogDebug . L'utilizzo di un wrapper consente di utilizzare una simulazione per testare i messaggi di registro e consente inoltre di modificare facilmente l'implementazione
  3. Se l'interfaccia è complicata perché deve essere, e tu la usi tutta, non sarai in grado di migliorare l'interfaccia e il wrapper sarà tanto complicato quanto l'interfaccia originale. Ciò significa che un wrapper non offrirà alcun vantaggio quando si passa a una libreria diversa.
risposta data 24.09.2015 - 16:39
fonte
2

Disclaimer: avvolgo il middleware della mia azienda ...

Ci sono più reclami qui, quindi li affronterò separatamente.

Wrapping also makes it easier to mock out third-party calls when you are testing your own code.

Ci sono molti vantaggi qui, in particolare quando il mocking conteggio aiuta il numero di chiamate. Alcuni sosterranno che il numero di chiamate non è funzionale e quindi non dovrebbe essere testato; tuttavia ho visto persone introdurre modifiche che hanno moltiplicato il numero di chiamate di un fattore di 10x o 100x e le implicazioni sulla performance non sono banali. Questo è particolarmente vero quando ...

... alcune librerie di terze parti sono dotate di molte dipendenze (connessione di rete, complicato file di configurazione) e solo per derisione puoi facilmente inserire errori, tra le altre situazioni specifiche che desideri testare.

Naturalmente, a questo punto, il wrapping è più giù per sbarazzarsi di una dipendenza indesiderata (connessione, file di configurazione) di qualsiasi altra cosa.

..In fact, wrapping third-party APIs is a best practice. When you wrap a third-party API, you minimize your dependencies upon it: You can choose to move to a different library in the future without much penalty.

Questo dovrebbe andare di pari passo con il principio DRY e con l'astrazione.

Quando si chiama una libreria di terze parti per analizzare un documento XML, spostarsi per estrarre alcune parti di dati, il chiamante:

  • non è interessato a quale libreria di terze parti utilizzi
  • probabilmente non è interessato alla struttura del documento XML

come risultato, lo avvolgeremo in un codice tutto tuo, che ha il duplice vantaggio di elevare il livello di astrazione (non è un documento XML, è una richiesta per comprare 4 gelati alla vaniglia, con caramello in cima) .

Se decodifichi ripetutamente i documenti XML, abbastanza rapidamente naturalmente fonderà parti del codice di decodifica che si presentano ripetutamente. Questo è solo ASCIUTTO.

Di conseguenza, trovo che il wrapping di componenti di terze parti sia naturale: ogni volta che uso la stessa chiamata due volte o tre volte, tendo ad estrarre il codice in una funzione comune, che in qualche modo diventa un wrapper.

(unasked question about boundaries and business model)

Un'API di terze parti è straniera, non parla la tua lingua.

C'è un confine tra il tuo codice e il codice di terze parti: usi oggetti diversi. Ad esempio, è possibile modellare il server come stringa (IPv4) e intero (porta), ma l'API sottostante prevede solo una stringa (IPv4: porta) o viceversa. Di conseguenza, è necessario applicare una trasformazione quando si parla con questa API estera.

Idealmente, vuoi massimizzare la quantità di codice che si occupa dei tuoi dati:

  • lo capisci
  • tu lo controlli (gli invarianti sono controllati e significativi per la tua app.)
  • ...

ciò richiede di spingere i limiti del codice straniero il più lontano possibile.

Inoltre, poiché ogni traduzione comporta il proprio rischio di impedenza di mancata corrispondenza, si desidera ridurre il numero di posizioni nel codice in cui si verifica tale traduzione.

In entrambi i casi, ciò implica un sottile strato tra il codice dell'applicazione e le API di terze parti.

    
risposta data 24.09.2015 - 17:20
fonte

Leggi altre domande sui tag