Domanda

Ho un'applicazione che salva documenti (pensa a documenti word) in un formato basato su Xml - Attualmente le classi C # generate da file xsd sono usate per leggere / scrivere il formato del documento e tutto è andato bene fino a poco tempo fa quando ho dovuto fare una modifica il formato del documento. La mia preoccupazione è con la retrocompatibilità poiché le versioni future della mia applicazione necessitano per poter leggere i documenti salvati da tutte le versioni precedenti e idealmente voglio anche che le versioni precedenti della mia app siano in grado di gestire con grazia la lettura dei documenti salvati dalle versioni future della mia app.

Ad esempio, supponendo che modifichi lo schema del mio documento per aggiungere un elemento extra (facoltativo) da qualche parte, quindi le versioni precedenti della mia applicazione semplicemente ignoreranno l'elemento aggiuntivo e non ci saranno problemi:

<doc>
    <!-- Existing document -->
    <myElement>Hello World!</myElement>
</doc>

Tuttavia, se viene apportata una modifica sostanziale (ad esempio un attributo viene modificato in un elemento o una raccolta di elementi), le versioni precedenti della mia app dovrebbero ignorare questo elemento se è facoltativo o informare l'utente che altrimenti sto tentando di leggere un documento salvato con una versione più recente della mia app. Anche questo mi sta causando mal di testa poiché tutte le versioni future della mia app necessitano di un codice completamente separato per leggere i due diversi documenti.

Un esempio di tale modifica sarebbe il seguente xml:

<doc>
    <!-- Existing document -->
    <someElement contents="12" />
</doc>

Modifica in:

<doc>
    <!-- Existing document -->
    <someElement>
        <contents>12</contents>
        <contents>13</contents>
    </someElement>
</doc>

Al fine di prevenire il mal di testa di supporto in futuro, ho voluto elaborare una strategia decente per gestire le modifiche che potrei apportare in futuro, in modo che le versioni della mia app che rilascerò ora saranno in grado di far fronte a queste cambiamenti in futuro:

  • Dovrebbe " il numero di versione " del documento da archiviare nel documento stesso e, in caso affermativo, quale strategia di controllo delle versioni dovrebbe essere utilizzata? Se la versione del documento deve corrispondere alla versione dell'assieme .exe o deve essere utilizzata una strategia più complessa (ad esempio, la revisione principale modificata indica cambiamenti non funzionanti, laddove incrementi minori della revisione indicano modifiche non permanenti, ad esempio elementi extra opzionali)
  • Quale metodo devo usare per leggere il documento stesso e come posso evitare di replicare enormi quantità di codice per diverse versioni di documenti?
    • Sebbene XPath sia ovviamente il più flessibile, è molto più lavoro da implementare rispetto alla semplice generazione di classi con xsd.
    • D'altra parte, se si utilizza l'analisi DOM, sarebbe necessaria una nuova copia del documento xsd nel controllo del codice sorgente per ogni modifica di rottura, causando problemi se le correzioni dovessero mai essere applicate a schemi più vecchi (le vecchie versioni dell'app sono ancora supportato).

Inoltre, ho lavorato in modo molto approssimativo sul presupposto che tutte le modifiche apportate possano essere suddivise in queste due categorie di "modifiche di beaking" e "cambiamenti non rompiscatole", ma non sono del tutto convinto che questo sia un presupposto sicuro da fare.

Nota che utilizzo il termine "documento" molto liberamente - i contenuti non assomigliano affatto a un documento!

Grazie per qualsiasi consiglio che mi puoi offrire.

È stato utile?

Soluzione

Hai sicuramente bisogno di un numero di versione nel file XML, e suggerirei di non legarlo alla versione dell'applicazione perché è davvero un'entità separata. Puoi passare attraverso due o tre versioni della tua app senza mai cambiare il formato XML o potresti finire per cambiare il formato più volte durante lo sviluppo di una singola versione.

Se vuoi che le versioni precedenti dell'applicazione siano in grado di leggere le versioni più recenti del file XML, non puoi mai, mai rimuovere elementi o cambiarne il nome. Puoi sempre aggiungere elementi e il codice precedente li ignorerà felicemente (una delle belle funzioni di XML) ma se li rimuovi, il vecchio codice non sarà in grado di funzionare.

Come ha detto Ishmael, XSLT è un buon modo per convertire il formato XML da una versione all'altra in modo da non finire con un mucchio di routine di analisi nel tuo codice sorgente.

Altri suggerimenti

XSLT è una scelta ovvia qui. Dato che puoi identificare la versione del tuo documento, per ogni versione del tuo schema, crea un XSLT che trasforma la versione precedente nella tua nuova versione.

È possibile applicare le trasformazioni in sequenza fino a raggiungere la versione corrente. Quindi stai modificando sempre e solo l'ultima versione del documento. Naturalmente, non sarai in grado di salvare nel vecchio formato e puoi rompere il documento per le versioni precedenti, ma questo è tipico di molte applicazioni. Se devi assolutamente salvare la versione precedente, crea una trasformazione che vada dall'altra parte.

Come dice @Andy, usa il numero di build principale della tua app.

Potresti aggiungere un attributo all'elemento root specificando la versione?

In questo modo le versioni precedenti non verranno interrotte e le versioni più recenti del software visualizzeranno l'attributo e passeranno a un metodo di caricamento diverso in modo appropriato.

La numerazione della versione dipende dalla frequenza di rilascio. Personalmente sceglierei il numero di build principale del tuo software, a meno che tu non preveda che il formato cambi più spesso di quello.

Modifica : ho appena notato qualcosa sulla duplicazione del codice:

Per questo vorrei usare il modello Factory, qualcosa del genere:

LoadDocument
DoNonVersionDependingLoading
VersionSpecificLoaderFactory(VersionNumber)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top