เหตุใดเบอร์ทรานด์เมเยอร์จึงคิดว่าการแบ่งคลาสย่อยเป็นวิธีเดียวที่จะขยายโมดูล“ ปิด”?


19

ในการสร้างซอฟต์แวร์เชิงวัตถุของเมเยอร์(1988) เขาได้กำหนดหลักการเปิด / ปิดดังต่อไปนี้:

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

เขาพูดต่อไปว่า:

หากคุณเปิดโมดูลอีกครั้งคุณจะต้องเปิดไคลเอนต์ทั้งหมดอีกครั้งเพื่ออัปเดตโมดูลเนื่องจากใช้รุ่นเก่า … [ปัญหานี้] เกิดขึ้นทุกครั้งที่โมดูลจะต้องถูกขยายโดยฟังก์ชั่นใหม่หรือองค์ประกอบข้อมูลทำให้เกิดการเปลี่ยนแปลงในไคลเอนต์ทั้งทางตรงและทางอ้อม ... ด้วยวิธีการคลาสสิกในการออกแบบและการเขียนโปรแกรมจึงไม่มีวิธีเขียนโมดูลที่เปิดและปิด

วิธีการแก้ปัญหาของเมเยอร์ในภาวะที่กลืนไม่เข้าคายไม่ออกนี้คือ: ไม่ขยายโมดูลห้องสมุดโดยการปรับเปลี่ยนคลาสที่มีอยู่; ให้เขียนโมดูลใหม่แทนคลาสย่อยที่มีอยู่แล้วและให้ไคลเอนต์ใหม่พึ่งพาโมดูลใหม่นั้น

ตอนนี้ในปี 1988 ฉันเขียนโปรแกรมของเล่น (ขั้นตอน) ใน Turbo Pascal และ Blankenship Basic และประสบการณ์ระดับมืออาชีพในศตวรรษที่ 21 ของฉันคือ JVM, CLR และในภาษาไดนามิกดังนั้นฉันจึงไม่รู้ว่า Meyer แปลว่าอะไร โดย "แนวทางคลาสสิคเพื่อการออกแบบและการเขียนโปรแกรม"

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

มีเหตุผลทางประวัติศาสตร์ที่การยืนยันนี้ดูเหมือนชัดเจนในปี 1988? พูดหรือไม่ว่าการเพิ่มฟังก์ชั่นหรือโครงสร้างข้อมูลไปยัง C static library เปลี่ยนรูปแบบดังกล่าวแม้ว่าจะใช้ API ที่เข้ากันได้แบบย้อนหลังไคลเอนต์จะต้องทำการคอมไพล์ใหม่หรือไม่? หรือเมเยอร์กำลังพูดถึงกลไกเพื่อบังคับใช้ความเข้ากันได้ของ API ย้อนหลังจริง ๆ


3
คำถามที่น่าสนใจ! ฉันรู้สึกว่าคำตอบนั้นจะเกี่ยวข้องกับความแตกต่างพื้นฐานระหว่าง Abstract Data Types และ Object-Oriented Data Abstractionซึ่งเป็นกลไกสองของData Abstraction Dataที่โดดเด่นในการเขียนโปรแกรม Modular (สิ่งที่ Betrand Meyer อ้างถึงคือ "แนวทางแบบดั้งเดิม" ") และการเขียนโปรแกรมเชิงวัตถุ (อ่านความคิดเห็น!) ตามลำดับ
Jörg W Mittag

นั่นเป็นเรื่องแปลก ดูเหมือนว่าจะขัดแย้งกับความจริงอย่างโจ๋งครึ่ม (แม้กระทั่งในปี 1988) นอกจากนี้วิธีการที่ได้รับการสนับสนุนของเขาจะส่งผลให้มีการเพิ่มจำนวนโมดูลอย่างไม่ช่วยเหลือ

@ dan1111: วิธีการของ Eiffel ในการสืบทอดซึ่งรวมถึง แต่ไม่ จำกัด เพียงวิธีการในการสืบทอดหลายแบบนั้นแตกต่างจาก C ++, Java, C # ฯลฯ ดังนั้นจึงไม่น่าแปลกใจที่แนวทางจะแตกต่างกัน เขาพัฒนาหอไอเฟลโดยเฉพาะเพื่อสนับสนุนมุมมองของเขาใน OO หลังจากทั้งหมด
Jörg W Mittag

คำตอบ:


18

เท่าที่ฉันสามารถบอกได้คำถามนี้ได้รับการตอบโดย Bertrand Meyer ตัวเองและคำตอบคือคำสั่งนี้ไม่ถูกต้อง ด้วยวิธีคลาสสิกในการออกแบบและการเขียนโปรแกรมมีแน่นอนสามารถเป็นวิธีที่จะเขียนโมดูลที่มีทั้งเปิดและปิด

หากต้องการค้นหาสิ่งนี้คุณต้องศึกษาฉบับที่สองของหนังสือเล่มนี้ (เผยแพร่เก้าปีต่อมาในปี 1997) ตามคำนำของรุ่นที่สองก็คือ

ไม่ใช่การอัปเดต แต่เป็นผลมาจากการทำงานซ้ำอย่างละเอียด ไม่มีย่อหน้าของเวอร์ชันดั้งเดิมที่ถูกทิ้งไว้โดยไม่มีใครแตะต้อง (แทบจะไม่บรรทัดเดียวจริงๆแล้ว)

โดยเฉพาะอย่างยิ่งข้อความที่ทำให้คุณสับสน ยังมีบทเปิดหลักการปิดใน ".33.3 ห้าหลักการ" และมีการถกเถียงกันอย่างละเอียดในหัวข้อนี้ใน "§14.7บทนำสู่การรับมรดก" แต่คำแถลงจากฉบับพิมพ์ครั้งแรกไม่ได้อยู่ที่นั่นอีกต่อไป

มีอะไรมุ่งเน้นไปที่วิธีที่สะดวกกว่าและใช้สำนวนในแนวทาง OO มากกว่าวิธีก่อน ๆ

ต้องขอบคุณการสืบทอดผู้พัฒนา OO สามารถนำวิธีการพัฒนาซอฟต์แวร์มาใช้เพิ่มขึ้นมากกว่าที่เคยเป็นมาก่อนด้วยวิธีการก่อนหน้านี้ ... (§3.3)

ความต้องการสองเท่านี้(เปิดและปิด)ดูเหมือนภาวะที่กลืนไม่เข้าคายไม่ออกและโครงสร้างโมดูลแบบคลาสสิกไม่มีเงื่อนงำ แต่มรดกแก้มันได้ คลาสถูกปิดเนื่องจากอาจถูกรวบรวมจัดเก็บในไลบรารีที่เป็นพื้นฐานและถูกใช้โดยคลาสไคลเอ็นต์ แต่มันยังเปิดอยู่เนื่องจากคลาสใหม่ใด ๆ อาจใช้เป็นพาเรนต์เพิ่มคุณสมบัติใหม่และประกาศคุณสมบัติที่สืบทอดใหม่ ในกระบวนการนี้ไม่จำเป็นต้องเปลี่ยนต้นฉบับหรือรบกวนลูกค้า ... (§14.7)

ตั้งแต่คุณยังดูเหมือนจะสงสัยเกี่ยวกับสิ่งที่ "วิธีคลาสสิก" เมเยอร์หมายที่นี่คุณสามารถหาคำอธิบายเหล่านี้ใน§4.7โครงสร้างแบบดั้งเดิม Modular ส่วนนี้อธิบายว่า "ไลบรารี่ของกิจวัตร" และ "แพ็คเกจ" หมายถึงเหล่านี้ (สำหรับอันหลังผู้เขียนบอกว่าคำนี้มาจาก Ada และกล่าวถึงภาษาอื่นที่มีคุณลักษณะนี้ - กลุ่มใน CLU และโมดูลใน Modula)

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


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

ภาษาคลาสสิกเช่น Fortran ไม่ใช่ OO เลย แต่คนที่ยังต้องใช้พวกเขา ... อาจต้องการใช้แนวคิด OO มากที่สุดเท่าที่จะทำได้ภายใต้ข้อ จำกัด ของวิธีการแบบเก่าเหล่านี้

โดยเฉพาะอย่างยิ่งในส่วนนี้เมเยอร์อธิบายในรายละเอียดว่ามันจะเป็นไปได้อย่างไรที่จะนำมรดกมาใช้ (มีข้อแม้และข้อ จำกัด บางประการ แต่ยังคงอยู่) ใน C และแม้แต่ใน Fortran

คุณจะเห็นว่าสิ่งนี้เรียกร้องให้มีการแก้ไขคำแถลงนั้นตั้งแต่รุ่นแรก ดูเหมือนว่าเป็นไปไม่ได้ในทางปฏิบัติที่จะอธิบายวิธีการกระทบยอด "ด้วยวิธีการแบบคลาสสิก ... ไม่มีทาง" ด้วยตัวอย่างที่เหมือนจริงเกี่ยวกับวิธีการที่สามารถทำได้


ที่น่าสนใจและแน่นอนฉันจะต้องพยายามที่จะได้รับการดูแลของรุ่นที่สอง แต่ก็ยังไม่ชัดเจนสำหรับฉันว่าทำไมแม้แต่ห้องสมุด "คลาสสิค" ที่ไม่ใช่ OO ก็ไม่สามารถเพิ่มคุณสมบัติ (อย่างน้อยบางประเภท) ได้โดยไม่รบกวน ลูกค้า
David Moles

@DavidMoles สิ่งที่เป็นไปได้และส่วนสุดท้ายของคำตอบของฉันอธิบายว่าและ Meyer เองก็ตระหนักว่า (เมื่อเขาทำงานซ้ำสำหรับ 2nd Edition) และยังให้ตัวอย่างของวิธีการที่สามารถทำได้ "สำหรับสิ่งที่ทำให้ผู้แต่งเปลี่ยนใจ ... " ฯลฯ
ริ้น

อืมมม ฉันไม่เห็น "รุ่น 2 ของไลบรารีนี้ซึ่งแทนที่รุ่น 1 และเข้ากันได้กับมันย้อนกลับเพิ่มฟังก์ชันต่อไปนี้ ... " เป็น "การสืบทอด" ยกเว้นในแนวความคิดที่เป็นไปได้ที่กว้างที่สุด
David Moles

(สำหรับฉันโดยนัยหมายถึงรุ่นที่ 1 ยังอยู่ใกล้และเรียกตามรุ่นที่ 2)
David Moles

@DavidMoles แทนที่ด้วยเวอร์ชัน 2 (ในขณะที่เปลี่ยนซอร์สโค้ดและคอมไพล์ใหม่ ) จะไม่ถือว่าเป็น "ปิดการแก้ไข" คุณสามารถตรวจสอบได้ในบทความ Wikipedia : "เอนทิตีสามารถอนุญาตให้ขยายพฤติกรรมได้โดยไม่ต้องแก้ไขซอร์สโค้ด ... "
ริ้น
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.