Il existe de nombreuses façons de gérer le problème de versionnage; vous pouvez le faire en ayant une fonction de chargement par version, vous pouvez essayer d'automatiser le processus en décrivant (via des attributs généralement) la transformation de la structure des actifs au fil du temps, vous pouvez faire des vérifications spécifiques à la version à l'intérieur des fonctions de chargement / sauvegarde, et cetera .
J'aime l'approche «décrire les changements», mais je trouve que tenter de le faire via des attributs devient rapidement gênant . J'utiliserais des fonctions à la place; implémentez une fonction qui transforme les données en version N
en données en version N + 1
pour toute votre version appropriée. Lors du chargement, vérifiez la version par rapport à la dernière et, si ce n'est pas le cas, exécutez les données via toutes les fonctions de version appropriées. Enregistrez toujours la dernière version.
Cela fonctionne mieux si vous effectuez la transformation lorsque les données sont encore sous forme de valeur-clé d'exécution. Cela signifie que vous souhaiterez probablement implémenter une représentation pour vos données qui est une approche «sac d'exécution de propriétés», car vous ne pouvez pas utiliser la forme de valeur-clé sous-jacente de JSON ou XML si vous avez votre propre format binaire. Si vous ne le faites pas, vous devrez peut-être également conserver les anciennes définitions de classe, ce qui devient laid. Pouvoir avoir vos actifs dans ce mauvais format de propriété est également extrêmement utile pour le développement de l'éditeur de jeux.
Pendant le développement, au fur et à mesure que vous parcourez vos données, elles remonteront naturellement à la dernière version et vous pourrez éventuellement supprimer les anciennes fonctions de version. Il s'agit plus ou moins de la même approche de haut niveau que nous avons utilisée pour la version des éléments artistiques (tels que les cartes) dans Guild Wars 2.
Maintenant, tout cela dit, je pense qu'il est utile de prendre en charge à la fois le texte et la sérialisation binaire pour les actifs. Pendant le développement, conservez toutes vos données dans un format lisible par l'homme basé sur XML ou JSON. Cela peut augmenter considérablement votre capacité d'itération car vous n'avez pas besoin de créer des outils aussi complexes pour modifier les données. Vous pouvez redevenir capable de faire de simples ajustements rapides à la main.
Deuxièmement, en supposant que vous souhaitiez toujours un format binaire pour l'expédition du jeu (ce qui peut améliorer la taille du fichier ou les temps d'E / S de fichier, c'est donc un souhait valide), concevez vos API de sérialisation et de désérialisation pour gérer la gestion des versions. La gestion des versions est toujours utile dans un contexte d'expédition, car à un moment donné, vous souhaiterez peut-être envoyer des mises à jour ou des corrections de bogues. Il existe certains documents décrivant les capacités de version de la sérialisation .NET et de la sérialisation de Boost qui peuvent vous intéresser. Si vous êtes allez soutenir à la fois le texte et les formats binaires, assurez-vous de les tester de temps en temps (ou de construire des tests automatisés pour le faire, encore mieux).
Utilisez un langage de balisage avec des paires attribut-valeur comme XML ou JSON.
L'analyseur peut simplement ignorer tous les attributs qu'il ne comprend pas ou utiliser les valeurs par défaut pour ceux qu'il ne trouve pas, ce qui rend la compatibilité ascendante et descendante assez facile. En outre, le format est lisible par l'homme afin que vous puissiez facilement le modifier avec un éditeur de texte.
Lorsque vous utilisez un langage établi comme XML ou JSON, vous remarquerez également que de nombreux langages de script le prennent en charge, donc lorsque vous avez encore besoin d'écrire un script pour modifier un grand nombre de fichiers, vous le trouverez beaucoup plus facile à faire.
L'inconvénient de la plupart de ces langues est qu'elles sont assez verbeuses. Cela signifie que les fichiers résultants sont beaucoup plus volumineux qu'ils ne devraient l'être avec un format binaire optimisé. De nos jours, la taille du fichier n'a pas trop d'importance dans la plupart des situations. Mais dans ceux où cela importe, la taille du fichier peut souvent être considérablement réduite en compressant le fichier avec un algorithme de stock comme zip.
Les langages de balisage n'autorisent souvent pas l'accès aléatoire à moins que le document entier ne soit lu sur le disque dur et analysé. Mais en pratique, cela n'a pas beaucoup d'importance, car les disques durs sont les plus rapides avec des lectures séquentielles. La recherche aléatoire de plusieurs fois dans différentes parties du même fichier peut souvent être beaucoup plus lente que la simple lecture du fichier en une seule fois, même lorsque cela signifie que vous lisez plus de données que nécessaire.
la source
vous pouvez utiliser protobuf. https://code.google.com/p/protobuf/ Il vous offre les avantages de json / xml, que vous pouvez facilement étendre tout en étant rétrocompatible, plus l'avantage d'être binaire. Le flux de travail consiste à créer une description du format de données dans le langage protobuf, puis à générer le code source pour la sérialisation et la désérialisation. La source peut être générée pour plusieurs langues. C'est aussi un gros avantage que vous ayez une spécification claire de vos données sérialisées, contrairement à json où la spécification se fait implicitement en lecture / écriture.
la source