Vai al contenuto
DedicatedPHP Contatto

Come progettare la compatibilità dei dati nelle API PHP senza interrompere i client

Definisci quali modifiche possono influire sui consumer, come distribuirle per fasi e quali segnali servono prima di ritirare un contratto API.

Schema dell’evoluzione di un’API PHP con versioni dei client e modifiche ai dati distribuite per fasi

Un’API non è compatibile solo perché mantiene lo stesso endpoint o la stessa versione. I consumer dipendono anche dalla struttura dei dati, dalle regole di validazione, dai valori predefiniti e dal comportamento in caso di errore. Se client diversi vengono aggiornati a ritmi diversi, una modifica che sembra minima a chi gestisce il server può interrompere un’app mobile, un’integrazione di terze parti o un processo interno.

Una policy di compatibilità dei dati nelle API PHP trasforma questo rischio in decisioni esplicite: quali modifiche sono accettabili, come distribuirle e quali test devono essere superati prima di ritirare un contratto. Non esiste una regola universale che renda compatibile qualsiasi modifica: bisogna considerare come ogni consumer legge e invia i dati.

Il contratto comprende dati, validazione e comportamento

Il contratto comprende dati, validazione e comportamento — guía visual de DedicatedPHP

Il contratto di un’API va oltre lo schema documentato. Comprende i campi e i relativi tipi, la possibilità di ometterli o impostarli a null, l’interpretazione di date e importi, i valori accettati da una richiesta, il formato degli errori e le garanzie sulla risposta. Include anche regole osservabili, come l’ordine di una collezione quando i client dipendono da esso o la stabilità di un identificatore.

In PHP, gli oggetti di trasferimento, i validatori e i serializzatori spesso implementano parti di questo contratto. Esaminare solo il controller può lasciare nascosti cambiamenti incompatibili in una regola di validazione, in una risorsa di risposta o in una mappatura tra il modello e l’API. È opportuno documentare il contratto in base a ciò che il client osserva realmente, non alla struttura interna delle classi o delle tabelle.

Classificare le modifiche in base al consumer

La classificazione è uno strumento di valutazione, non una garanzia automatica. Una modifica additiva in genere mantiene il funzionamento dei client che ignorano i campi sconosciuti, ma può interrompere i consumer che convertono la risposta in una struttura rigida o la convalidano rispetto a uno schema chiuso. Allo stesso modo, un nuovo campo facoltativo in una richiesta può essere innocuo per i client meno recenti, mentre renderlo obbligatorio non lo è.

  • Di norma additive: aggiungere un campo facoltativo a una richiesta o a una risposta, oppure aggiungere un valore a una collezione, purché i consumer tollerino questi elementi.
  • Potenzialmente incompatibili: eliminare o rinominare un campo, modificarne il tipo, rendere obbligatorio un campo facoltativo, cambiare il formato di un errore o modificare il significato di un valore esistente.
  • Dipendenti dal contesto: cambiare l’ordine, la precisione numerica, il fuso orario, la semantica di uno stato o i criteri di paginazione. Anche se lo schema non cambia, il risultato per il client può essere diverso.

Prima di approvare una modifica, identificate i consumer e verificate come elaborano il dato. Un campo sconosciuto può essere ignorato, causare un errore di validazione o essere usato da una logica che non lo prevedeva. Non date per scontato che tutti i linguaggi, le librerie o le versioni dei client reagiscano allo stesso modo.

Far evolvere richieste e risposte con cautela

Nelle risposte, aggiungere un campo è più sicuro se si tiene conto della possibilità che i client più rigidi rifiutino proprietà aggiuntive. Se un campo cambia significato o tipo, non riutilizzatelo senza segnalarlo. Introducete un nuovo campo con una semantica chiara, documentate il suo rapporto con quello precedente e manteneteli entrambi per una transizione definita.

Nelle richieste è essenziale distinguere tra assente, null e vuoto. In PHP, una validazione che tratta una chiave assente come il suo valore null può cancellare dati o applicare valori predefiniti inattesi. Definite il significato di ciascun caso e testate sia i client nuovi sia quelli meno recenti. Per un nuovo campo, valutate inizialmente di accettarne l’assenza e di assegnargli un comportamento compatibile, invece di renderlo obbligatorio fin dal primo deployment.

Il versionamento degli endpoint non è l’unica opzione. È possibile far evolvere un contratto mantenendo lo stesso endpoint se le modifiche sono compatibili, oppure pubblicare una nuova versione quando non lo sono e la coesistenza è operativamente sensata. In entrambi i casi, documentate la policy di supporto: una semplice etichetta di versione non indica per quanto tempo un contratto resterà disponibile.

Distribuire database e API per fasi

Un deployment sicuro separa le modifiche allo storage dall’esposizione del nuovo comportamento. Una sequenza comune consiste nell’ampliare lo schema, distribuire codice in grado di funzionare con la struttura precedente e quella nuova, migrare i dati se necessario e infine attivare la nuova lettura o scrittura. La rimozione di colonne o percorsi precedenti avviene in seguito, quando ci sono prove sufficienti che non siano più necessari.

Questo approccio di espansione e contrazione evita che una versione dell’applicazione si aspetti una colonna che non esiste ancora o che un nuovo deployment smetta di funzionare con i processi meno recenti. Nei sistemi con più istanze o worker in background, tenete conto che durante il deployment possono coesistere diverse versioni del codice. Le migrazioni devono essere compatibili con questa coesistenza e prevedere una strategia di ripristino in caso di errore in una fase.

L’esposizione graduale — per esempio, abilitare una funzionalità per una parte controllata dei consumer — può limitare l’impatto, ma non equivale a un rilascio pubblico né sostituisce la compatibilità. Usate controlli di attivazione quando consentono di osservare e annullare il comportamento; definite in anticipo le condizioni che devono interrompere l’espansione.

Misurare l’utilizzo senza registrare dati sensibili

Per sapere quali consumer continuano a usare un contratto, la telemetria deve identificare la versione o la funzionalità rilevante senza memorizzare corpi di richieste o risposte contenenti informazioni personali, credenziali o dati commerciali. Registrate segnali minimi, come endpoint, versione del client dichiarata, esito e data; limitate l’accesso e la conservazione in base alle esigenze operative e agli obblighi applicabili.

Il segnale deve essere utile per prendere decisioni. Distinguete le richieste degli utenti reali dai test, dai tentativi ripetuti o dal traffico automatizzato; osservate anche gli errori, la latenza e le variazioni dei volumi. Se non esiste un identificatore affidabile del client, non deducetene l’identità a partire da dati sensibili. Tenete presente che proxy, chiavi condivise e client che non inviano la versione possono lasciare zone prive di visibilità.

Ritirare un contratto in base a criteri verificabili

Non ritirate una versione solo perché è trascorso un termine annunciato. Definite segnali e soglie adeguati al rischio: assenza prolungata di traffico identificabile, migrazione confermata delle integrazioni note, stabilità della versione successiva e una procedura di supporto per le eccezioni. Se persiste traffico sconosciuto, indagate prima di interpretare la mancata identificazione come assenza di utilizzo.

Comunicate in anticipo che cosa cambia, chi è interessato, qual è l’alternativa, le date previste e come testare la migrazione. Mantenete le informazioni in una documentazione accessibile ai team consumer e predisponete un canale per segnalare incompatibilità. Se non è possibile annullare rapidamente l’impatto, valutate una transizione più lunga o la coesistenza temporanea dei contratti.

Checklist prima della pubblicazione

Checklist prima della pubblicazione — guía visual de DedicatedPHP
  • Sono stati documentati i campi, i tipi, la nullabilità, i valori predefiniti e gli errori interessati?
  • È stato verificato il comportamento dei client tolleranti e di quelli rigidi di fronte a campi nuovi o assenti?
  • I test di contratto coprono i consumer noti e i casi limite di validazione?
  • La migrazione del database consente la coesistenza con le versioni precedenti dell’applicazione?
  • Ci sono metriche sufficienti per rilevare errori e utilizzo del contratto senza acquisire dati sensibili?
  • Sono stati definiti responsabili, comunicazioni, criteri di rollback e condizioni per ritirare gli elementi precedenti?

Una policy utile non promette che nessuna modifica interromperà alcun client. Rende esplicite le ipotesi, limita le sorprese e permette di agire sulla base di evidenze. Riesaminate queste decisioni a ogni modifica del contratto, soprattutto quando l’API ha consumer esterni il cui ciclo di aggiornamento non è sotto il controllo del team.

Vuoi applicare queste idee al tuo progetto?Parliamo della tua piattaforma PHP.
Visualizza il servizio correlato