Come estendere i campi enum dell'API REST mentre sono compatibili con le versioni precedenti

3

Immagina che ci sia un endpoint GET /v1/status che restituisce uno degli stati predefiniti che sono documentati. Ad esempio uno dei [ disabled , enabled ]. L'endpoint può essere utilizzato da altri servizi di terze parti.

Il problema che vedo solo aggiungendo uno stato di blocked così com'è, è quello i clienti di terze parti non saranno in grado di elaborare questo caso o addirittura di avere qualcosa di simile:

if (status == 'disabled') {
  // do something when status disabled
} else {
  // do something when status enabled
}

Bumping una versione e mantenere 2 versioni non sembra una buona soluzione per una modifica così piccola.

Qual è l'approccio migliore per aggiungere un nuovo stato, ad esempio blocked , senza rompere i client di terze parti che potrebbero dipendere da questo endpoint? O quale è un modo migliore di progettare o documentare API pubbliche per evitare tali problemi in futuro?

    
posta Ostap Maliuvanchuk 14.11.2017 - 21:01
fonte

2 risposte

3

La modifica di ciò che un endpoint restituisce estendendo l'enumerazione restituita non è una modifica compatibile con le versioni precedenti. (D'altra parte, l'estensione di un'enumerazione fornita a un nodo finale è.)

Questo suggerisce due possibili soluzioni al problema in cui ti trovi (oltre ad aumentare il numero di versione): 1) non estendere l'enumerazione ma passare altre informazioni in un altro modo, oppure 2) utilizzare un nuovo endpoint. Entrambi questi approcci presuppongono che le nuove informazioni non siano necessarie per utilizzare l'interfaccia in modi antichi. Ma ovviamente questo è solo ciò che è compatibile con le versioni precedenti. Il primo approccio potrebbe assumere la forma di restituire una "motivazione" dall'output status tramite corpo, intestazioni o possibile codice di stato HTTP. Quest'ultimo sarebbe un nuovo endpoint, statusDetails say, che potrebbe restituire la "ragione" descritta nell'approccio precedente. In effetti, questo secondo approccio è solo il primo approccio, ma utilizza un nuovo endpoint per fornire le informazioni. Sto supponendo, ma sospetto che non ci sia una grande differenza tra "bloccato" e "disabilitato" in un programma che consuma l'API, e la differenza tra i due è solo una questione di perché è non abilitato. In altre parole, se un consumatore ha appena "bloccato" come "disabilitato", funzionerebbe comunque correttamente.

Se la mia ipotesi è corretta, allora il design originale sembra perfettamente ragionevole, ed è il nuovo approccio che è irragionevole (oltre ad essere retrocompatibile). Il nuovo approccio suona come modifica dei booleani in True , False , FileNotFound . Se la mia ipotesi non è corretta, è difficile dire cosa sia ragionevole senza conoscere l'intento dell'endpoint. Ad esempio, se si intendeva solo "informativo", un tipo di dati aperti come una stringa avrebbe dovuto essere utilizzato con garanzie molto deboli fornite nella documentazione per scoraggiare l'uso improprio. In alternativa, se è più simile allo stato di una macchina a stati, allora, almeno, dovrebbe essere stata utilizzata una denominazione diversa e l'aggiunta di un nuovo stato alla macchina a stati sarebbe molto più una modifica incompatibile con le versioni precedenti e non "piccola" a tutti . Tuttavia, questa sarebbe una scelta di design molto insolita per un'API REST.

    
risposta data 15.11.2017 - 02:29
fonte
1

Il modo in cui lo eviterei dal lato client è quello di elencare esplicitamente le combinazioni nella mia istruzione if e fallire se non c'è molto nello stile di GD di Guarded Command Language di Dykstra

Anche se questa è la mia abitudine e non necessariamente ciò che gli altri farebbero.

Detto questo, stai apportando una modifica API che non è retrocompatibile in tutte le situazioni in quanto è necessario un bump di versione o viene fornita un'appendice al contratto per la versione corrente.

    
risposta data 14.11.2017 - 23:56
fonte

Leggi altre domande sui tag