การออกแบบที่ดีสำหรับการอนุญาตให้ใช้งานร่วมกันได้ของไฟล์ย้อนหลังระหว่างซอฟต์แวร์รุ่นต่างๆคืออะไร


14

การออกแบบที่ดีสำหรับการอนุญาตให้ใช้งานร่วมกันได้ของชนิดไฟล์ระหว่างซอฟต์แวร์รุ่นต่าง ๆ คืออะไร

ตัวอย่างเช่น 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
            .....
}

แต่ดูเหมือนว่าเสาหินอย่างไม่น่าเชื่อไม่สามารถขยายได้มากและมีแนวโน้มที่จะนำไปสู่การคัดลอก / วางรหัสจำนวนมาก

ดังนั้นฉันจึงคิดว่าจะใช้อินเตอร์เฟสพื้นฐานสำหรับทุกเวอร์ชันที่กำหนดโครงสร้างที่ไม่เปลี่ยนรูปแบบเช่นส่วนหัวที่จำเป็นต้องมีอยู่ในไฟล์และวิธีการที่จำเป็นต้องมีสำหรับ serialization / deserialisation คลาสของเวอร์ชันใหม่ที่ใช้อินเทอร์เฟซสืบทอดเวอร์ชันเก่าและแทนที่เฉพาะสิ่งที่มีการเปลี่ยนแปลงเนื่องจากไฟล์จะเหมือนกันส่วนใหญ่

ฉันไม่ได้ใส่ใจกับโครงสร้างของไฟล์มากนักเนื่องจากมันได้ตัดสินใจแล้วว่าเราจะใช้ XML และสคีมาเริ่มต้นนั้นใหญ่และใหญ่แล้ว อย่างไรก็ตามไม่ต้องสงสัยเลยว่าจะมีการเปลี่ยนแปลงในอนาคตและฉันแค่ต้องการที่จะสามารถออกแบบรหัสในแบบที่ทำให้ง่ายต่อการรองรับการเปลี่ยนแปลงเหล่านี้


6
คุณควรจะออกแบบรูปแบบไฟล์เพื่อให้ไม่เพียง แต่มันจะไม่สนใจข้อมูลที่ขาดหายไปเนื่องจากแหล่งที่มาจากรุ่นก่อนหน้า แต่ยังมีข้อมูลว่ามันไม่ได้คาดหวังเพราะแหล่งที่มาจากรุ่นใหม่รุ่น หากคุณเริ่มต้นจากศูนย์โปรดโปรดส่งต่อความเข้ากันได้เช่นกัน แทบจะไม่มีความพยายามพิเศษและเพิ่มความได้เปรียบให้กับซอฟต์แวร์ของคุณเป็นสองเท่า
Kilian Foth

ในการเปิดคุณจะรู้ล่วงหน้าเสมอ (เช่นจากส่วนหัว) เวอร์ชันไฟล์ใดที่คุณกำลังติดต่อด้วย นอกจากนี้หากต้องการคำขออื่นโปรดโปรดตรวจสอบไฟล์ที่เสียหายหรือเป็นอันตรายและอย่าปล่อยให้พวกเขาก่อให้เกิดปัญหา ดูแลระบบของคุณจะขอบคุณ :)
cxw

1
ใช่หมายเลขรุ่นจะอยู่ในส่วนหัวของไฟล์เสมอและรูปแบบส่วนหัวจะไม่เปลี่ยนแปลง เราจะไปกับแนวคิดที่ว่าไฟล์ที่สร้างขึ้นระหว่างการแก้ไขซอฟต์แวร์เล็กน้อยควรเข้ากันได้เช่นไฟล์ที่สร้างใน v1.1 สามารถเปิดได้ใน v1.2 และในทางกลับกันแม้ว่าการทำงานบางอย่างจาก 1.2 อาจหายไปใน 1.1 แต่การแก้ไขหลัก จะหยุดการทำงานร่วมกันได้ดังนั้นสิ่งที่เขียนใน v2 จะไม่เปิดใน v1 แต่สิ่งที่เขียนใน v1 จะเปิดใน v2
JJBurgess

และสำหรับสิ่งที่เสียหายไฟล์นั้นมี DSL และการเปิด / ปิดโปรแกรมนั้นเป็น IDE / คอมไพเลอร์ในบ้าน สิ่งเหล่านี้จะไม่ไปทุกที่ที่อยู่ใกล้กับสภาพแวดล้อมการผลิตดังนั้นผู้ดูแลระบบจึงไม่ต้องกังวล
JJBurgess

คำตอบ:


10

คุณอาจดูรูปแบบไฟล์ PNG และวิธีจัดการกับความเข้ากันได้ของเวอร์ชั่น ทุก ๆ บล็อกมีรหัสที่อธิบายถึงประเภทของบล็อกและมีธงบางอันที่บอกให้ซอฟต์แวร์ทราบว่าต้องทำอย่างไรหากไม่เข้าใจรหัสนั้น ตัวอย่างเช่น "คุณไม่สามารถอ่านไฟล์หากคุณไม่เข้าใจบล็อกนี้" หรือ "คุณสามารถอ่านไฟล์ แต่ไม่สามารถแก้ไขได้" หรือ "คุณสามารถแก้ไขไฟล์ได้" แต่คุณต้องลบบล็อกนี้ " เพื่อความเข้ากันได้ย้อนหลังซอฟต์แวร์ของคุณต้องจัดการกับสถานการณ์เมื่อไม่มีข้อมูลที่คาดหวัง


ความคิดที่ดี! รูปแบบ PNG ขึ้นอยู่กับคุณสมบัติและไม่ใช่รุ่น อย่างไรก็ตามหมายความว่ารูปแบบพื้นฐานจะต้องไม่เปลี่ยนแปลง (เช่นส่วนหัวที่กำหนดคุณสมบัติ)
Florian Margaine

นั่นดูน่าสนใจ. ฉันกำลังอ่านข้อกำหนดของไฟล์ในขณะนี้ ฉันชอบความคิดของชิ้นสำคัญและเสริมและอาจลองและทำงานนี้มา
JJBurgess

3

วิธีการทำเช่นนี้สามารถทำได้โดยใช้คลาสฐานและส่วนต่อประสานกับฟังก์ชั่นพื้นฐานสำหรับการจัดการไฟล์ของคุณ จากนั้นใช้คลาสสำหรับแต่ละรุ่นที่ขยายจากคลาสพื้นฐานเพื่อจัดการกับเคสเฉพาะรุ่นทั้งหมด ฟังก์ชั่นที่สามารถเปลี่ยนสามารถเป็นเสมือนในคลาสพื้นฐานของคุณหากมีเฉพาะการใช้งานเฉพาะรุ่น เมื่อคุณต้องการคลาสเพื่อจัดการไฟล์ให้ใช้ factory ที่รับการปรับใช้เฉพาะเวอร์ชันของอินเตอร์เฟสการจัดการไฟล์


ปัญหาเดียวของฉันคือคุณจะต้องทำซ้ำการใช้งานเฉพาะรุ่นสำหรับการแก้ไขแต่ละครั้งในภายหลัง สมมติว่าคุณมีเมธอดคลาสพื้นฐานสามวิธี: ReadNames (), ReadAges () และ ReadAddresses () และใน V2 ของคลาสคุณทำการเปลี่ยนเป็น ReadAges () หากใน V3 คุณต้องตัดสินใจเปลี่ยนเป็น ReadNames () ถ้าคลาสเฉพาะรุ่นทั้งหมดของคุณกำลังสืบทอดจากฐานคุณจะสูญเสียการเปลี่ยนแปลง V2 ของคุณหรือคุณต้องคัดลอก / วางการเปลี่ยนแปลงจาก V2 ในการใช้งาน V3 เช่นกัน
JJBurgess

1
การใช้งานของ readages สามารถเรียกคลาสที่แตกต่างกันซึ่งถือเป็น implemention จริงเกี่ยวกับวิธีการอ่านอายุสำหรับรุ่นนี้ การทำให้คลาสของคุณเป็นอินเทอร์เฟซ / โรงงานมากกว่าการเขียนโปรแกรมจริง
เพียร์

2

ฉันทำสิ่งนี้ด้วย XML และทำงานได้ดี:

เพียงอนุญาตให้องค์ประกอบใด ๆ ในเอกสารของคุณมีคุณลักษณะและองค์ประกอบย่อยใด ๆ (และเมื่อการสั่งซื้อไม่สำคัญ - ในลำดับใด ๆ ) จุดเริ่มต้นจากเวอร์ชันแรกของโปรแกรม - เมื่ออ่านเอกสารให้ละเว้นแอททริบิวต์และอิลิเมนต์ย่อยที่คุณไม่รู้จักในเวอร์ชันปัจจุบัน

ในอนาคตเมื่อคุณเพิ่มคุณสมบัติใหม่ให้กับโปรแกรมเวอร์ชั่นใหม่แล้วเพิ่มคุณสมบัติหรือองค์ประกอบย่อย รุ่นเก่าจะไม่สนใจ เวอร์ชันใหม่ควรตรวจสอบความสำคัญของคุณสมบัติหรือองค์ประกอบย่อยและจัดการกับมัน

ตัวอย่างเช่นคุณมีบางรายการที่มีข้อความ:

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

และในรุ่นที่ใหม่กว่าคุณต้องการเพิ่มสีให้กับรายการเพื่อให้คุณเพิ่มคุณสมบัติcolor:

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

เวอร์ชันที่เก่ากว่าจะละเว้นcolorคุณสมบัติเมื่อเปิดเอกสาร เวอร์ชันใหม่จะตรวจสอบความสำคัญของcolorคุณลักษณะและหากไม่มีอยู่จะกำหนดสีเริ่มต้น

ด้วยวิธีแก้ปัญหาง่ายๆนี้คุณจะมีทั้งความเข้ากันได้ย้อนหลังและไปข้างหน้า


ปัญหาเล็กน้อยที่เกิดขึ้นกับตัวเลือกนี้เป็น "แบบง่าย" คือคุณจะต้องตัดแอตทริบิวต์ที่ไม่คาดคิดทั้งหมด (หรือไม่เปลี่ยนแปลง) เมื่อบันทึกเอกสาร ดังที่ได้กล่าวไว้ในคำตอบอื่น ๆ วิธีแก้ปัญหาที่ดีกว่าอย่างน้อยก็กำหนดไว้ในบางลักษณะไม่เชื่อเรื่องพระเจ้าว่าควรจะทิ้งแอตทริบิวต์เก็บหรือทำให้เอกสารกลายเป็นแบบอ่านอย่างเดียวสำหรับรุ่นที่ไม่เข้าใจ
Mark Hurd

@ Mark Hudr: ใช่ฉันเงียบ ๆ สมมติว่าความเข้ากันได้แบบย้อนหลังจะต้องมีและความเข้ากันได้ส่งต่อเป็นโบนัส เมื่อมีคนเปิดเอกสารใหม่ในแอปพลิเคชันเวอร์ชันเก่าพวกเขาไม่ควรแปลกใจว่าเมื่อพวกเขาบันทึกมันพวกเขาจะสูญเสียบางสิ่งที่มองไม่เห็นในแอปเก่า การเข้าสู่ระบบเพิ่มเติมดูเหมือนจะถูกครอบงำสำหรับฉัน
user3123061
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.