Apa desain yang baik untuk memungkinkan kompatibilitas mundur file antara berbagai versi perangkat lunak?

14

Apa desain yang baik untuk memungkinkan kompatibilitas mundur dari jenis file antara berbagai versi perangkat lunak?

Misalnya, bagaimana microsoft mendapatkan kata 2007, 2010 dan 2013 dll ... untuk semua file docx terbuka, tetapi edisi yang berbeda dapat menyimpan lebih banyak / lebih sedikit data dan menyimpan data dengan cara yang sedikit berbeda, semua untuk jenis file yang sama, dan file yang disimpan dalam satu versi dapat dibuka di yang lain, tetapi elemen-elemen tertentu dari file mungkin tidak tersedia di versi yang lebih lama?

Maksud saya, cara yang sangat jelas untuk melakukannya adalah memiliki sesuatu seperti

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

tapi itu kelihatannya sangat monolitik, tidak terlalu bisa diperluas, dan cenderung mengarah ke banyak kode copy / paste.

Jadi saya berpikir untuk menggunakan antarmuka dasar untuk semua versi yang mendefinisikan struktur yang tidak dapat diubah, seperti header, yang perlu ada dalam file, dan metode yang perlu tersedia untuk serialisasi / deserialisasi, kemudian banyak pewarisan sehingga masing-masing kelas versi baru yang mengimplementasikan antarmuka mewarisi versi lama, dan hanya menimpa hal-hal yang telah berubah, karena file akan sama, sebagian besar.

Saya tidak terlalu peduli dengan struktur file, karena sudah diputuskan bahwa kita akan menggunakan XML, dan skema awalnya, pada umumnya, sudah diputuskan. Namun, tidak akan ada keraguan untuk mengubahnya di masa depan, dan saya hanya ingin dapat merancang kode dengan cara yang membuatnya mudah untuk mengakomodasi perubahan ini.

JJBurgess
sumber
6
Anda harus merancang format file sehingga tidak hanya mengabaikan informasi yang hilang karena sumbernya dari versi yang lebih lama, tetapi juga informasi yang tidak diharapkan karena sumbernya dari versi yang lebih baru . Jika Anda memulai dari awal, mohon mohon lakukan kompatibilitas juga. Hampir tidak ada upaya ekstra dan menggandakan kegunaan perangkat lunak Anda.
Kilian Foth
Saat terbuka, apakah Anda akan selalu tahu di depan (misalnya, dari header) versi file yang Anda hadapi? Selain itu, untuk membuat permintaan lain, harap periksa file yang rusak atau berbahaya dan jangan biarkan mereka menimbulkan masalah. Sysadmin Anda akan berterima kasih :).
cxw
1
Ya, nomor versi akan selalu ada di header file, dan format header tidak akan pernah berubah. Kami akan dengan gagasan bahwa file yang dibuat antara revisi perangkat lunak kecil harus kompatibel, yaitu file yang dibuat di v1.1 dapat dibuka di v1.2 dan sebaliknya, meskipun beberapa fungsi dari 1.2 mungkin hilang di 1.1 tetapi revisi besar akan merusak kompatibilitas ke depan, sehingga hal-hal yang ditulis dalam v2 tidak akan terbuka di v1, tetapi hal-hal yang ditulis dalam v1 akan terbuka di v2.
JJBurgess
Dan untuk hal korupsi, file berisi DSL, dan program membuka / menutupnya adalah in-house IDE / compiler kustom. Ini tidak akan mendekati lingkungan produksi, jadi admin tidak perlu khawatir.
JJBurgess

Jawaban:

10

Anda mungkin melihat format file PNG dan bagaimana menangani kompatibilitas versi. Setiap blok memiliki id yang menggambarkan jenis blok itu, dan memiliki beberapa tanda yang memberitahu perangkat lunak apa yang harus dilakukan jika tidak dapat memahami id itu. Misalnya "Anda tidak dapat membaca file jika Anda tidak memahami blok ini", atau "Anda dapat membaca file tetapi tidak memodifikasinya", atau "Anda dapat memodifikasi file tetapi Anda harus menghapus blok ini". Untuk kompatibilitas mundur, perangkat lunak Anda hanya perlu menangani situasi ketika data yang diharapkan tidak ada.

gnasher729
sumber
Ide yang hebat! Format PNG bergantung pada fitur dan bukan pada versi. Tetapi ini berarti bahwa format dasar tidak boleh berubah. (yaitu tajuk yang mendefinisikan fitur.)
Florian Margaine
Itu menarik. Saya sedang membaca spesifikasi file saat ini. Saya suka ide potongan kritis dan tambahan, dan mungkin mencoba dan mengerjakan ini.
JJBurgess
3

Cara melakukan ini bisa dengan menggunakan kelas dasar dan antarmuka dengan fungsi dasar untuk penanganan file Anda. Kemudian gunakan kelas untuk setiap versi yang memanjang dari kelas dasar untuk menangani semua kasus khusus versi. Fungsi yang dapat berubah bisa virtual di kelas dasar Anda abstrak jika hanya ada implementasi versi spesifik. Saat Anda membutuhkan kelas untuk menangani file, gunakan pabrik yang mendapatkan implementasi antarmuka antarmuka file versi khusus.

teman sebaya
sumber
Satu-satunya masalah saya dengan ini adalah bahwa Anda akan berakhir duplikat implementasi spesifik versi untuk setiap revisi berikutnya. Katakanlah Anda memiliki tiga metode kelas dasar: ReadNames (), ReadAges () dan ReadAddresses () dan di V2 kelas, Anda membuat perubahan ke ReadAges (). Jika di V3, Anda kemudian memutuskan untuk membuat perubahan ke ReadNames (), jika semua kelas khusus versi Anda mewarisi dari pangkalan, Anda akan kehilangan perubahan V2 Anda, atau Anda perlu menyalin / menempelkan perubahan dari V2 ke dalam implementasi V3 juga.
JJBurgess
1
Implementasi pembacaan dapat memanggil kelas yang berbeda yang memegang implementasi aktual tentang cara membaca usia untuk versi ini. Membuat kelas Anda akan lebih banyak konfigurasi antarmuka / pabrik daripada pemrograman yang sebenarnya.
rekan
2

Saya telah melakukan ini dengan XML dan berfungsi dengan baik:

Cukup izinkan elemen apa pun dalam dokumen Anda, untuk memiliki atribut dan subelemen apa pun (dan bila pesanan tidak penting - dalam urutan apa pun). Mulai dari versi pertama program - saat membaca dokumen, abaikan atribut dan sub-elemen yang tidak Anda ketahui dalam versi saat ini.

Di masa mendatang ketika Anda menambahkan fitur baru ke versi program baru, kemudian tambahkan atribut atau sub-elemen. Versi yang lebih lama akan mengabaikannya. Versi baru harus memeriksa tekanan atribut atau sub-elemen dan menanganinya.

Misalnya Anda memiliki beberapa item dengan teks:

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

Dan di versi yang lebih baru Anda ingin menambahkan warna ke item sehingga Anda menambahkan atribut color:

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

Versi yang lebih lama akan mengabaikan coloratribut saat membuka dokumen. Versi baru memeriksa tekanan coloratribut dan jika tidak ada menetapkan warna default.

Dengan solusi sederhana ini Anda akan memiliki kompatibilitas mundur dan maju.

pengguna3123061
sumber
Masalah kecil dengan ini sebagai opsi "sederhana" adalah bahwa Anda akan menghapus semua atribut yang tidak terduga (atau tetap tidak berubah) saat menyimpan dokumen. Seperti disebutkan dalam jawaban lain, solusi yang lebih baik setidaknya menentukan dalam beberapa versi dengan cara agnostik, apakah atribut harus dijatuhkan, disimpan atau menyebabkan dokumen menjadi hanya-baca untuk versi yang tidak memahaminya.
Mark Hurd
@ Mark Hudr: Ya, saya diam-diam berasumsi bahwa kompatibilitas ke belakang harus dimiliki dan kompatibilitas ke depan adalah bonus. Ketika seseorang membuka dokumen baru dalam aplikasi versi lama, mereka tidak perlu heran bahwa ketika mereka menyimpannya, mereka kehilangan sesuatu yang belum terlihat di aplikasi lama. Logika tambahan sepertinya terlalu direkayasa untuk saya.
user3123061