ソフトウェアの異なるバージョン間でのファイルタイプの下位互換性を可能にするための優れた設計とは何ですか?
たとえば、MicrosoftはWord 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を使用することが既に決定されており、初期のスキーマは概してすでに決定されているため、それほど気にする必要はありません。ただし、将来的に変更されることは間違いありません。これらの変更に簡単に対応できるようにコードを設計できるようにしたいだけです。
あなたはPNGファイルフォーマットとそれがどのようにバージョン互換性を処理するかを見ているかもしれません。すべてのブロックには、そのブロックの種類を説明するIDがあり、そのIDを理解できない場合にソフトウェアに何をすべきかを指示するいくつかのフラグがあります。たとえば、「このブロックを理解していないとファイルを読み取ることができない」、「ファイルを読み取ることはできるが変更はできない」、「ファイルを変更することはできるがこのブロックを削除する必要がある」などです。下位互換性のために、ソフトウェアは、予期されるデータが存在しない場合の状況を処理するだけで済みます。
これを行う方法は、基本クラスを使用して、ファイル処理の基本的な関数とインターフェイスすることです。次に、すべてのバージョン固有のケースを処理するために、基本クラスから拡張する各バージョンのクラスを使用します。バージョン固有の実装しかない場合は、変更可能な関数を抽象の基本クラスで仮想化できます。ファイルを処理するクラスが必要な場合は、ファイル処理インターフェイスのバージョン固有の実装を取得するファクトリを使用します。
私はこれをXMLで行いましたが、うまく機能します。
ドキュメント内の任意の要素に任意の属性と任意のサブ要素を許可します(順序が重要でない場合-順序は任意)。プログラムの最初のバージョンから始めて-ドキュメントを読むときは、現在のバージョンでは知らない属性とサブ要素を無視します。
今後、新しいバージョンのプログラムに新しい機能を追加する場合は、属性またはサブ要素を追加します。古いバージョンでは無視されます。新しいバージョンでは、属性またはサブ要素の存在を確認し、それを処理する必要があります。
たとえば、テキスト付きのアイテムがあるとします。
<item text="Hello, world!"/>
そして、新しいバージョンでは、アイテムに色を追加して、属性color
を追加します。
<item text="Hello, world!" color="008000"/>
古いバージョンでは、ドキュメントを開くときにcolor
属性を単に無視します。新しいバージョンでは、color
属性の有無をチェックし、存在しない場合はデフォルトの色を割り当てます。
このシンプルなソリューションを使用すると、後方互換性と前方互換性の両方が得られます。