Jaki jest dobry projekt umożliwiający wsteczną zgodność typu pliku między różnymi wersjami oprogramowania?
Na przykład, w jaki sposób Microsoft uzyskuje słowo 2007, 2010 i 2013 itd. ... do wszystkich otwartych plików docx, ale różne wersje mogą zapisywać więcej / mniej danych i zapisywać dane w nieco inny sposób, wszystkie w tym samym typie pliku i plik zapisany w jednej wersji można otworzyć w innej, ale niektóre elementy pliku mogą nie być dostępne w starszych wersjach?
To znaczy, naprawdę oczywistym sposobem na zrobienie tego jest posiadanie czegoś takiego
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
.....
}
ale wydaje się to niewiarygodnie monolityczne, niezbyt rozszerzalne i może prowadzić do dużej ilości kopiowanego / wklejanego kodu.
Zastanawiałem się więc nad użyciem podstawowego interfejsu dla wszystkich wersji, które definiują niezmienne struktury, takie jak nagłówek, które muszą być obecne w pliku, oraz metody, które muszą być dostępne do serializacji / deserializacji, a następnie wielokrotnego dziedziczenia, aby każda klasa nowej wersji, która implementuje interfejs, dziedziczy starą wersję i zastępuje tylko rzeczy, które uległy zmianie, ponieważ plik będzie w większości taki sam.
Tak naprawdę nie przejmuję się strukturą pliku, ponieważ już zdecydowano, że będziemy używać XML, a początkowy schemat jest, ogólnie rzecz biorąc, już ustalony. Jednak bez wątpienia w przyszłości będą do niego wprowadzane zmiany, a ja po prostu chcę móc zaprojektować kod w sposób ułatwiający dostosowanie się do tych zmian.
źródło
Odpowiedzi:
Możesz rzucić okiem na format pliku PNG i sposób, w jaki obsługuje on zgodność wersji. Każdy blok ma identyfikator opisujący, jaki to jest blok, i ma pewne flagi, które informują oprogramowanie, co zrobić, jeśli nie może zrozumieć tego identyfikatora. Na przykład „nie możesz odczytać pliku, jeśli nie rozumiesz tego bloku”, lub „możesz odczytać plik, ale go nie modyfikować”, lub „możesz zmodyfikować plik, ale musisz usunąć ten blok”. Aby zapewnić zgodność z poprzednimi wersjami, oprogramowanie musi jedynie poradzić sobie z sytuacją, gdy nie ma oczekiwanych danych.
źródło
Można to zrobić za pomocą klasy bazowej i interfejsu z podstawowymi funkcjami obsługi plików. Następnie użyj klas dla każdej wersji, które wychodzą z klasy podstawowej, aby obsłużyć wszystkie przypadki specyficzne dla wersji. Funkcje, które można zmienić, mogą być wirtualne w twojej podstawowej klasie abstrakcji, jeśli istnieją tylko implementacje specyficzne dla wersji. Gdy potrzebujesz klasy do obsługi pliku, skorzystaj z fabryki, która pobiera specyficzną dla wersji implementację interfejsu obsługi plików.
źródło
Zrobiłem to z XML-em i działa dobrze:
Po prostu zezwól, aby dowolny element w dokumencie miał dowolne atrybuty i dowolne podelementy (a gdy kolejność nie jest ważna - w dowolnej kolejności). Począwszy od pierwszej wersji programu - podczas czytania dokumentu ignoruj atrybuty i podelementy, których nie znasz w bieżącej wersji.
W przyszłości, gdy dodasz nową funkcję do nowej wersji programu, dodaj atrybut lub podelement. Starsze wersje zignorują to. Nowa wersja powinna sprawdzać obecność atrybutu lub podelementu i obsługiwać go.
Na przykład masz kilka elementów z tekstami:
W nowszej wersji chcesz dodać kolor do przedmiotu, aby dodać atrybut
color
:Starsza wersja po prostu zignoruje
color
atrybut podczas otwierania dokumentu. Nowe wersje sprawdzają obecnośćcolor
atrybutu, a jeśli nie istnieje, przypisuje domyślny kolor.Dzięki temu prostemu rozwiązaniu będziesz mieć zgodność zarówno wstecz, jak i do przodu.
źródło