Come gestire il mapping dal modello a oggetti a diverse versioni di contratti o DTO

0

Sto cercando modelli o best practice per mantenere versioni diverse di un contratto API . Esistono molte informazioni su Internet relative alle API della versione (URL e intestazioni, ecc.), Ma questa domanda è correlata al mapping da un modello di oggetto a diverse versioni dei tipi di contratto (DTO), e per questo non sono stato in grado di trovare alcuna informazione.

Immagina di avere un progetto web con un endpoint e un'app client (potrebbe essere desktop o mobile) che comunica con il progetto web utilizzando quell'endpoint. L'endpoint viene utilizzato solo dall'app client, ovvero è un endpoint interno, non pubblico. La comunicazione tra il progetto web e l'app client funziona dall'app client inviando alcuni dati all'endpoint e il progetto Web lo riceve, lo elabora e restituisce un oggetto risposta. C'è un contratto per come dovrebbe apparire la struttura dei dati inviati all'endpoint e inviati dall'endpoint. È abbastanza complesso in termini di tipi del numero di tipi di oggetti e del loro nidificazione. Non puoi controllare quando i tuoi utenti aggiornano la loro app client, ed è un requisito aziendale retrocompatibile.

Hai un modello di oggetti che si evolve e non c'è problema dato che hai separato il contratto API (DTO) e il modello a oggetti. Hai un codice di mappatura che mappa dal modello a oggetti al contratto e viceversa.

Puoi apportare modifiche senza interruzioni al contratto, ma se hai bisogno di apportare modifiche urgenti, avrai bisogno di una nuova versione del contratto e dovrai assicurarti di poter eseguire la mappatura dal modello a oggetti il nuovo contratto. Ma dato che devi essere retrocompatibile, devi anche assicurarti di poter mappare in qualche modo dal modello a oggetti alla versione precedente del contratto.

La mia domanda è quindi: come gestiresti architettonicamente questo? Conosci modelli o best practice che possono essere utilizzati per questo?

La sfida è quando si modifica il modello di oggetto e si crea un nuovo contratto, inoltre è necessario assicurarsi che ci sia un modo in cui il vecchio contratto continua a funzionare. Un modo vedo che è possibile farlo mantenendo un mapping dal modello a oggetti a ciascuna versione del contratto.

Un altro modo potrebbe essere solo mantenere un mapping dal modello di oggetto al contratto più recente, ma poi mantenere un percorso di migrazione dalle diverse versioni del contratto (quindi quando è necessario mappare da v3 a v1, dovresti mappare da modello a oggetto a contratto più recente (v3), quindi mappare a v2, quindi mappare a v1).

Un altro problema da considerare è la quantità di duplicazione . Quando il contratto ha un sacco di tipi e devi solo eliminare un singolo campo da uno dei tipi, questa è una modifica di rottura e richiede una nuova versione. Copierai l'intero contratto (Tutti i tipi) in una nuova cartella nel tuo progetto, quindi cancellerai il campo? Ciò significherebbe che hai un contratto quasi identico e molti tipi verrebbero duplicati. La duplicazione in questo caso può essere giustificata, ma esiste un modo migliore?

Qualsiasi suggerimento, approfondimento e suggerimento sono apprezzati.

    
posta René 10.09.2017 - 17:58
fonte

1 risposta

1

I problemi che descrivi esistono in forma identica nei sistemi di serializzazione degli oggetti, e questi problemi sono stati tutti risolti nel corso degli anni. Quello che descrivi come un contratto può anche essere visto come un formato di serializzazione dell'oggetto, ad un livello più alto.

Per la serializzazione, in generale, hai implementato solo una singola versione del "contratto". Questa implementazione supporta l'ultima versione senza percorsi condizionali; il percorso di codice predefinito e più semplice supporta l'ultima versione. Per mantenere la retrocompatibilità con la versione precedente, i condizionali devono essere introdotti in base al tipo di modifica dell'oggetto:

  • Rimozione di una proprietà (utilizzo la proprietà word come in .net, ma è un campo pubblico in un oggetto): normalmente non è necessario fare nulla per la compatibilità con le versioni precedenti.
  • Aggiunta di una proprietà: se si fornisce un valore predefinito utile per la proprietà, l'utente API non ha bisogno di inizializzare la nuova proprietà. Uso la parola "proprietà" anche per fare riferimento a dati ortogonali: una proprietà non influisce su un'altra. Questo fa parte della buona progettazione dell'API e un requisito per la compatibilità con le versioni precedenti.
  • Modifica il tipo o il nome di una proprietà: in questo caso devi aggiungere il codice condizionale per esaminare la versione del consumer dell'API e convertire il nome o il tipo nel nuovo nome o tipo.
  • Modifica il nome di un tipo di dati: la modifica è simile; in alcuni casi, devi mantenere il vecchio tipo di dati in modo che possa essere caricato con i dati prima della conversione.

Ora considera la compatibilità API invece della compatibilità di serializzazione. In molti modi, questo è un problema più difficile, perché è necessario fornire l'intera API nella versione esatta necessaria. Sebbene sia possibile aggiungere a tale API, non è possibile modificare la funzionalità della vecchia API in alcun modo. È necessario conservare tutti i vecchi tipi di dati e tutte le vecchie proprietà. La strategia generale è questa:

  • Aggiungi nuove funzionalità e nuovi tipi di dati senza interferire con la vecchia API. Aggiungere nuove proprietà non è un problema.
  • Gli utenti che scrivono un nuovo codice useranno la versione più recente.
  • Gli utenti che lavorano con codice precedentemente scritto non hanno alcun problema in quanto supportano l'intera vecchia API.
  • Tieni traccia dell'età della versione: a un certo punto diventa troppo difficile mantenere la versione precedente. A questo punto, si crea una versione che ha rimosso tutto il vecchio codice di compatibilità. Le persone che utilizzano versioni precedenti della tua API possono comunque collegarsi a librerie più vecchie.

La strategia principale con l'evoluzione dell'API non cambia mai. Ciò significa che la tua API deve essere molto ben progettata, con l'idea di rendere i tipi di dati più generali, non i più specifici. È necessario pianificare in anticipo per anni. Aiuta avere anni di esperienza nel dominio specifico. Anche con un'attenta pianificazione, l'API deve cambiare, ma almeno puoi minimizzare le modifiche.

    
risposta data 11.09.2017 - 00:33
fonte

Leggi altre domande sui tag