Quelle est la bonne conception pour permettre la rétrocompatibilité d'un type de fichier entre différentes versions de logiciel?
Par exemple, comment Microsoft obtient-il Word 2007, 2010 et 2013, etc. dans tous les fichiers docx ouverts, mais différentes éditions peuvent enregistrer plus / moins de données et enregistrer les données de manières légèrement différentes, toutes dans le même type de fichier, et un le fichier enregistré dans une version peut être ouvert dans une autre, mais certains éléments du fichier peuvent ne pas être disponibles dans les anciennes versions?
Je veux dire, la façon vraiment évidente de le faire est d'avoir quelque chose comme
private string openfile(string filename)
{
File.Open(filename)
... some logic that gets a header from the file that will never change
switch (fileversion)
case 2007:
.....
case 2010
.....
case 2013
.....
}
mais cela semble incroyablement monolithique, peu extensible et susceptible de conduire à beaucoup de code copié / collé.
Je pensais donc à utiliser une interface de base pour toutes les versions qui définit les structures immuables, telles que l'en-tête, qui doivent être présentes dans le fichier, et les méthodes qui doivent être disponibles pour la sérialisation / désérialisation, puis l'héritage multiple afin que chaque La classe de la nouvelle version qui implémente l'interface hérite de l'ancienne version et ne remplace que les éléments qui ont changé, car le fichier sera le même, pour la plupart.
Je ne suis pas vraiment dérangé par la structure du fichier, car il a déjà été décidé que nous utiliserons XML, et le schéma initial est, dans l'ensemble, déjà décidé. Cependant, il y aura sans aucun doute des modifications à l'avenir, et je veux juste être en mesure de concevoir le code d'une manière qui facilite la prise en compte de ces modifications.
la source
Réponses:
Vous pourriez avoir un aperçu du format de fichier PNG et de la façon dont il gère la compatibilité des versions. Chaque bloc a un identifiant décrivant de quel type de bloc il s'agit, et il a des indicateurs qui indiquent au logiciel quoi faire s'il ne peut pas comprendre cet identifiant. Par exemple, "vous ne pouvez pas lire le fichier si vous ne comprenez pas ce bloc", ou "vous pouvez lire le fichier sans le modifier" ou "vous pouvez modifier le fichier mais vous devez supprimer ce bloc". Pour une compatibilité descendante, votre logiciel a juste besoin de gérer la situation lorsque aucune donnée attendue n'est présente.
la source
Pour ce faire, vous pouvez utiliser une classe de base et une interface avec les fonctions de base pour la gestion de vos fichiers. Utilisez ensuite des classes pour chaque version qui s'étendent à partir de la classe de base pour gérer tous les cas spécifiques à la version. Les fonctions qui peuvent changer peuvent être virtuelles dans votre classe de base d'abstrait s'il n'y a que des implémentations spécifiques à la version. Lorsque vous avez besoin d'une classe pour gérer le fichier, utilisez une fabrique qui obtient l'implémentation spécifique à la version de l'interface de gestion des fichiers.
la source
Je l'ai fait avec XML et cela fonctionne bien:
Permettez simplement à n'importe quel élément de votre document d'avoir des attributs et des sous-éléments (et lorsque l'ordre n'est pas important - dans n'importe quel ordre). À partir de la première version du programme - lors de la lecture du document, ignorez les attributs et sous-éléments que vous ne connaissez pas dans la version actuelle.
À l'avenir, lorsque vous ajouterez une nouvelle fonctionnalité à une nouvelle version du programme, ajoutez un attribut ou un sous-élément. Les versions plus anciennes l'ignoreront. La nouvelle version doit vérifier la pression de l'attribut ou du sous-élément et gérer avec.
Par exemple, vous avez certains éléments avec des textes:
Et dans une version plus récente, vous souhaitez ajouter de la couleur à l'élément afin d'ajouter un attribut
color
:La version antérieure ignorera simplement l'
color
attribut lors de l'ouverture du document. Les nouvelles versions vérifient la pression de l'color
attribut et s'il n'existe pas, attribue la couleur par défaut.Avec cette solution simple, vous aurez à la fois une compatibilité ascendante et descendante.
la source