2010-06-21 14 views
7

Utilizziamo una libreria fornita da qualcun altro. Di recente a causa di cambiamenti in quella libreria il nostro progetto ha 500 errori. Durante la migrazione alla nuova libreria abbiamo rilevato che solo 15 API non funzionano e 500 errori sono ripetitivi (occorrono più volte 15 errori, poiché le stesse chiamate vengono utilizzate in così tante volte).In questo caso si tratta di un uso eccessivo dell'astrazione?

Così, per la migrazione ho proposto la creazione di un'altra classe wrapper statica interna, che avvolge le chiamate API di libreria. Perché se la biblioteca dovesse cambiare di nuovo avremo meno codice da cambiare e quindi il codice diventa più facile da mantenere in futuro. Inoltre, effettuando il wrapping delle chiamate, evitiamo errori umani (o usi API involontari (sovraccarichi)).

Ma alcune persone qui, non vedono il punto di avere un'altra classe di wrapper, che si ritiene sia totalmente non necessaria. Il loro unico punto di discussione è che, dato che la maggior parte delle modifiche API sono solo una riga, possiamo sempre cambiarle usando CTRL + H (Trova e sostituisci). E dicono anche che questa astrazione in più che sto suggerendo, toglie la leggibilità (come si nasconde la chiamata API reale dietro un altro nome del metodo (anche se significativo)) per il codificatore/lettore.

Che cosa è l'approccio migliore qui? Ho sbagliato con i miei suggerimenti?

+0

Questa non è una cattiva idea. Non lasciare che i nay-sayers ti tradiscano. Se insistono nel rimuovere questa astrazione, la prossima volta * essi * possono essere quelli che risolvono i problemi del compilatore di oltre 500 librerie. – FrustratedWithFormsDesigner

+3

E, utilizzando Trova/Sostituisci sull'intera soluzione, garantisce ore di divertimento per l'intero team .. – SWeko

+1

SWeko: Penso che ci sia uno scherzo qui mi manca. Esiste una situazione in cui una ricerca/sostituzione globale potrebbe causare "ore" di sforzi per più della persona che fa la ricerca/sostituzione? – Ken

risposta

8

è una pratica relativamente comune per avvolgere API instabili e le librerie con involucri personalizzati. Un uso comune, ad esempio, consiste nel tradurre le eccezioni di tale libreria nella nomenclatura delle eccezioni. Più in generale questi involucri sono noti come adattatori, sebbene gli adattatori (IMHO) siano più adatti a fornire funzionalità necessarie a un lato nascondendo l'esatta "lingua" dell'altro lato, non perché l'altro lato sia instabile.

Lei ha citato l'uso della statica anche se - io non sono generalmente un grande fan di utilizzare questi. IMHO è meglio talvolta di avere un'interfaccia rappresentano le funzionalità necessarie, e quindi avere sottotipi di tale interfaccia, quando uno di questi sottotipi utilizza la libreria di terze parti. Il vantaggio è che un giorno può passare a un altro fornitore senza cambiare ogni chiamata nel proprio sistema.

In entrambi i casi, sei generalmente sulla pista giusta. IMHO chiunque pensi che CTRL-H sia uno strumento di refactoring valido sta cercando problemi. Stanno almeno usando getter e setter (se applicabile) nel loro codice?

Inoltre, la parte leggibilità non è chiaro per me. Un adattatore con un nome leggibile ha lo stesso valore di un'API originale con un nome leggibile.

+0

Sì, anche io ero confuso con la parte di leggibilità. Ma poi è quello che hanno detto :). Probabilmente suggeriscono che la chiamata API nascosta in un altro wrapper potrebbe non rendere il lettore consapevole della sintassi/utilizzo dell'API o qualcosa del genere. –

+0

@Chandan: Perché il lettore deve essere consapevole della sintassi/utilizzo dell'API sottostante? Il punto è che si vuole minimizzare l'accoppiamento sull'API sottostante – Uri

+0

@Chandan: io tendo ad errare sul lato di troppa astrazione in generale - diffido di qualsiasi libreria che non sia "standard" (cioè, non sull'affidabilità di un stabilire un progetto apache). Sono anche un pazzo per l'usabilità dell'API, quindi scrivo spesso i miei adattatori. – Uri

12

Questo in realtà è noto come il modello Adapter, ed è appositamente creato con il tuo problema esatto in mente ....

adattatore viene specificamente utilizzato per NON aggiungere funzionalità, proprio per adattare l'interfaccia di un'API a un'interfaccia prevista dal chiamante. Le interfacce sono solo un pratico strumento OO per implementare la funzione adattatori in un modo coerente e gestibile, il pattern stesso descrive fondamentalmente come risolvere un problema.

+2

... ed è una buona idea! –

+0

Suppongo che l'adattatore abbia lo scopo di eseguire alcune regolazioni (aggiungendo la logica, ecc.) Con le funzionalità di terze parti esistenti. Sto semplicemente inviando una chiamata a un'API di terze parti. Sarebbe ancora eleggibile per essere chiamato Adapter? (come non sto definendo le interfacce). –

+0

Modificato la risposta. – SWeko

1

difficile da dire senza conoscere il codice, ma mi sento come una facciata/adattatore è un buon modo per chiamate API seprate dal proprio codice. Non andrei tanto lontano per dire che è necessario, ma è più chiaro.

2

Se un'API sta cambiando, un wrapper è l'unico modo per proteggersi. Se hai optato per un'API che sta cambiando, hai dei grossi rischi per il tuo progetto. Mitigare tali rischi con un wrapper consente inoltre di proteggere se stessi se si desidera passare a un'altra libreria.

Per implementare il wrapper, è necessario creare l'involucro e fare la ricerca e la sostituzione.

In entrambi i casi, è ancora necessario toccare tutte le chiamate a causa della modifica iniziale dell'API, quindi non vedo che il piccolo investimento aggiuntivo è un problema.

0

Dipende da cosa sta facendo l'API e se aggiungere un altro livello aggiunge realmente isolamento/incapsulamento o se si tratta semplicemente di aggiungere un altro livello di riferimento indiretto. Se un cambiamento nell'API richiederà una modifica nell'interfaccia pubblica del tuo wrapper, sarà di intralcio.

Un livello wrapper è particolarmente adatto quando è possibile esporre la funzionalità a un livello di astrazione che ha senso per l'applicazione, nascondendo la flessibilità dell'API che non è necessaria e standardizzando il modo in cui si accede alle funzionalità necessarie. Ciò può anche implicare l'utilizzo di nomi di funzioni e parametri più specifici per il dominio del problema, che può ridurre la difficoltà concettuale di comprendere come l'API è integrata nell'applicazione.

Problemi correlati