異なるバージョンのソフトウェア間でファイルの後方互換性を許可するための優れた設計とは何ですか?


14

異なるバージョンのソフトウェア間でファイルタイプの後方互換性を許可するための優れた設計とは何ですか?

たとえば、Microsoftはどのようにして2007、2010、2013などの単語をすべての開いているdocxファイルに取得しますが、異なるエディションではより多くの/少ないデータを保存し、わずかに異なる方法でデータをすべて同じファイルタイプに保存できますあるバージョンで保存されたファイルは別のバージョンで開くことができますが、ファイルの特定の要素は古いバージョンでは使用できない可能性がありますか?

つまり、それを行うための本当に明白な方法は、

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
            .....
}

しかし、それは信じられないほどモノリシックで、あまり拡張性がなく、多くのコピー/貼り付けコードにつながる可能性があります。

だから私は、ファイルに存在する必要があるヘッダーなどの不変の構造、およびシリアル化/逆シリアル化に必要なメソッドを定義するすべてのバージョンのベースインターフェイスを使用することを考えていましたインターフェースを実装する新しいバージョンのクラスは古いバージョンを継承し、ファイルがほとんど同じであるため、変更されたもののみをオーバーライドします。

ファイルの構造についてはあまり気にしません。XMLを使用することは既に決まっているので、最初のスキーマは概して決定済みです。ただし、将来的には間違いなく変更されることになるので、これらの変更に容易に対応できるようにコードを設計できるようにしたいだけです。


6
ソースが以前のバージョンからのものであるために欠落している情報だけでなく、ソースが新しいバージョンからのものであるために予期しない情報も無視するように、ファイル形式を設計する必要があります。ゼロから始める場合は、前方互換性も行ってください。余分な労力はほとんど必要なく、ソフトウェアの有用性が2倍になります。
キリアンフォス

オープン時に、どのファイルバージョンを処理しているのかを常に(ヘッダーからなど)前もって知っていますか?また、別のリクエストを行うには、破損したファイルや悪意のあるファイルをチェックして、問題が発生しないようにしてください。あなたのシステム管理者はあなたに感謝します:)。
cxw

1
はい、バージョン番号は常にファイルヘッダーにあり、ヘッダー形式は変更されません。マイナーソフトウェアリビジョン間で作成されたファイルは互換性があるはずです。つまり、v1.1で作成されたファイルはv1.2で開くことができます。前方互換性が失われるため、v2で記述されたものはv1で開かれませんが、v1で記述されたものはv2で開きます。
-JJBurgess

また、破損については、ファイルにDSLが含まれており、それらを開く/閉じるプログラムはカスタムの社内IDE /コンパイラです。これらは本番環境の近くには行きませんので、管理者は心配する必要はありません。
JJBurgess

回答:


10

PNGファイル形式と、バージョンの互換性の処理方法をご覧ください。すべてのブロックには、それがどのような種類のブロックであるかを示すIDがあり、そのIDを理解できない場合にソフトウェアに何をすべきかを伝えるフラグがあります。たとえば、「このブロックを理解していないとファイルを読み取ることができません」、「ファイルを読み取ることはできますが、変更することはできません」、「ファイルを変更することはできますが、このブロックを削除する必要があります」などです。下位互換性のために、ソフトウェアは、予想されるデータが存在しない状況を処理する必要があります。


いい案!PNG形式は、バージョンではなく機能に依存しています。ただし、基本的な形式を変更してはいけないということです。(つまり、機能を定義するヘッダー。)
フロリアンマーゲイン

それは面白い。現在、ファイルの仕様を読んでいます。私は重要で補助的なチャンクのアイデアが好きで、これを試してみるかもしれません。
JJBurgess15年

3

これを行う方法は、ファイル処理のための基本機能を備えた基本クラスとインターフェイスを使用することです。次に、基本クラスから拡張される各バージョンのクラスを使用して、すべてのバージョン固有のケースを処理します。バージョン固有の実装しかない場合、変更可能な関数は抽象の基本クラスで仮想化できます。ファイルを処理するクラスが必要な場合は、ファイル処理インターフェイスのバージョン固有の実装を取得するファクトリを使用します。


これに関する私の唯一の問題は、その後のリビジョンごとにバージョン固有の実装を複製してしまうことです。ReadNames()、ReadAges()、ReadAddresses()の3つの基本クラスメソッドがあるとします。クラスのV2では、ReadAges()に変更を加えます。V3では、ReadNames()に変更を加えることを決定します。バージョン固有のクラスがすべてベースから継承している場合、V2の変更を失うか、V2から変更をコピーして貼り付ける必要があります。 V3実装にも同様に。
-JJBurgess

1
readagesの実装は、このバージョンの年齢の読み方に関する実際の実装を保持する別のクラスを呼び出すことができます。クラスを作成することは、実際のプログラミングよりもインターフェイス/ファクトリの構成になります。
ピア

2

私はXMLでこれを行いましたが、うまく機能します:

文書内のすべての要素に、属性とサブ要素を許可するだけです(順序が重要でない場合-任意の順序で)。プログラムの最初のバージョンから始まります-ドキュメントを読むとき、現在のバージョンでは知らない属性とサブ要素を無視します。

将来、プログラムの新しいバージョンに新しい機能を追加する場合は、属性またはサブ要素を追加してください。古いバージョンでは無視されます。新しいバージョンでは、属性またはサブ要素の押下をチェックし、それを処理する必要があります。

たとえば、テキスト付きのアイテムがいくつかあります。

<item text="Hello, world!"/>

そして新しいバージョンでは、属性を追加するためにアイテムに色を追加したいと思いますcolor

<item text="Hello, world!" color="008000"/>

古いバージョンは、colorドキュメントを開くときに属性を単に無視します。新しいバージョンは、color属性の押付けをチェックし、存在しない場合はデフォルトの色を割り当てます。

このシンプルなソリューションを使用すると、下位互換性と上位互換性の両方が得られます。


「単純な」オプションとしてのこれのわずかな問題は、ドキュメントを保存するときにすべての予期しない属性を削除する(またはそれらを変更しないで保持する)ことです。他の回答で述べたように、より良い解決策は、少なくともいくつかのバージョンにとらわれない方法で、属性を削除、保持、またはドキュメントを理解できないバージョンの読み取り専用にするかどうかを決定します。
マークハード

@Mark Hudr:はい、後方互換性が必要であり、前方互換性がボーナスであると静かに仮定しています。誰かが古いバージョンのアプリケーションで新しいドキュメントを開くとき、保存するときに古いアプリケーションでまだ表示されていないものを失ったことに驚かないでください。追加のロジックは過剰に設計されているようです。
user3123061
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.