Ultime modifiche alle API: come posso semplificare la transizione per gli utenti della biblioteca?

9

In passato, ho utilizzato il metodo standard per aggiungere @Deprecated annotazioni ai metodi API che verranno rimossi in una versione successiva.

Ora sto preparando una versione principale per una libreria, con molte parti API rimosse e rinominate.

Per semplificare la transizione per gli utenti esistenti, potrebbe essere utile se la nuova versione della libreria può essere utilizzata parallelamente alla vecchia versione.

I vantaggi

  • è possibile implementare la commutazione dinamica tra le versioni
  • le applicazioni possono tornare alla versione precedente se vengono rilevati errori nella nuova versione (utile in fase beta)

Per fare questo, potrei semplicemente spostare la nuova versione della libreria in un nuovo pacchetto da com.mycompany.library a com.mycompany.library.v2

Questa è una pratica comune o ci sono altre raccomandazioni per l'uso side-by-side delle librerie Java?

Sfondo:

la libreria è un semplice convertitore di documenti. Quindi oltre a un mehtod di conversione (dentro, fuori), ha molte proprietà di configurazione e alcuni gestori di eventi. Se fornisco l'utilizzo side-by-side, i consumatori potrebbero creare istanze e configurazioni dinamiche:

if (useVersion2) {
  com.mycompany.library.v2.Converter c = new com.mycompany.library.v2.Converter();
  // configure and run
  c.setOption(...);
  c.convert(in, out); 
} else {
  com.mycompany.library.Converter c = new com.mycompany.library.Converter();
  // configure and run
  c.setOption(...);
  c.convert(in, out);
}

(domanda spostata dal link )

    
posta mjn 12.05.2016 - 19:19
fonte

3 risposte

3

Questo approccio è piuttosto comune. Consente una transizione graduale verso una nuova API e un'evoluzione sicura verso nuove implementazioni.

Naturalmente, l'approccio if / then, come evidenziato da Laiv nella sua risposta, ha alcuni inconvenienti. È noioso. È facile dimenticare o mescolare le cose. Idealmente, l'uso di wrapper, fabbriche o adattatori potrebbe fornire alcune alternative più carine. Ma spesso, il più semplice è il migliore.

Martin Fowler e Pete Hogdson hanno teorizzato recentemente su questo argomento in un eccellente articolo in cui descrivono cosa chiama "feature toggle patterns". Potrebbe interessarti come diverse strategie di implementazione - come l'uso di un "toggle router" - e gli scenari di utilizzo sono descritti in tutti i dettagli.

Nota: personalmente non sono stato trovato i cavicchi delle funzioni. Venendo dal mondo C ++ preferisco l'alternativa facile e robusta usando alias di namespace e usando le clausole per scegliere a tempo di compilazione la versione da usare. Ma è specifico per la lingua, e inoltre non consente la configurazione dinamica mentre la funzione alterna. Così come detto, a volte, il più semplice è il migliore; -)

    
risposta data 12.05.2016 - 21:33
fonte
1
La libreria

Retrofit è un ottimo esempio per questo. Non è passato molto tempo da quando hanno introdotto una versione stabile 2 che è davvero buona anche se ha portato qualche rottura.

Alcune delle cose importanti che hanno fatto sono state:

  1. La nuova API ha un sacco di valore e risolve molte delle carenze della versione precedente. Ciò significa che la tua nuova API deve essere molto buona. Non solo in termini di come funziona, ma anche di renderlo bello e facile, se questo è sempre stato un problema.

  2. È stata rilasciata la versione beta della nuova API che consente agli utenti di apprendere tempestivamente i cambiamenti e fornisce anche un buon feedback.

  3. Anche la transizione non è stata dolorosa. Hanno introdotto il numero di versione nel nome del pacchetto stesso, il che significa che alcune modifiche richiedevano solo la modifica delle istruzioni di importazione. Sì, alcune classi sono state rimosse e alcune introdotte, ma non sembrava troppo drastica. Ciò dipende anche da come l'utente ha organizzato il proprio codebase che è in parte fuori dal campo di applicazione dello sviluppatore dell'API.

Inoltre, le guide di migrazione sono preferite. Retrofit, essendo una libreria popolare, molti articoli su questo sono disponibili online.

    
risposta data 13.05.2016 - 08:25
fonte
0

Non penso che la suddivisione del codice con if/else sia un buon approccio.

Pensa a lungo termine. Che cosa hai intenzione di fare con ulteriori versioni ?. )

In che modo il codice utente può finire nel tempo?

Per le versioni o le recensioni secondarie, è necessario mantenere la compatibilità. @Deprecated viene fornito con un commento che richiede allo sviluppatore di non utilizzare quel codice. Suggerisce anche cosa dovrebbe invece usare componente / metodo / classe . Infine molti di loro informano che il codice deprecato non sarà supportato in ulteriori versioni. O potrebbe non essere supportato (non lo sanno ancora).

Tuttavia sulle nuove versioni (riprogettazione delle modifiche principali) non ha molto senso tenere codice deprecato perché rende più difficile la manutenzione. Il codice legacy può anche essere influenzato dalle modifiche apportate. Direttamente o meno.

Rende anche poco chiaro l'utilizzo. Anche se il codice deprecato è annotato.

Se il tuo caso è un cambiamento o un miglioramento sostanziale, preferirei incoraggiare / forzare gli utenti a passare alla nuova funzione.

Se la nuova lib sembra un utente nonestabile, puoi eseguire il downgrade della dipendenza e seguirla fino a quando non vengono risolti nuovi bug di lib.

Come sviluppatore mi aspetto cambiamenti da una versione all'altra. Se decido di usare quello nuovo, accetto di trattare tali cambiamenti.

Nel peggiore dei casi, posso tornare al precedente.

Non metterei su espressioni come 'è temporale'. Perché sappiamo tutti come finisce ...

Piuttosto per impedire all'utente di cadere in tali affermazioni che finisce nel codice difficile da leggere e difficile da mantenere

    
risposta data 12.05.2016 - 20:34
fonte

Leggi altre domande sui tag