บทนำ
โรเบิร์ต แอล. กลาสส์ ได้โต้แย้งว่าการปฏิบัติจริงนั้นมาก่อนทฤษฎี โดยเฉพาะอย่างยิ่งในด้านการพัฒนาซอฟต์แวร์ การปฏิบัติจริงเป็นสาขาที่โดดเด่นกว่าทฤษฎี โดยที่นักพัฒนาจะได้รับประโยชน์มากที่สุดเมื่อได้ลงมือเขียนโค้ดจริง ดังนั้นเราจึงจะพิจารณาโปรแกรมง่ายๆ สักตัวก่อน โดยละทิ้งทฤษฎีและแนวคิดไว้ก่อนชั่วคราว
การสร้างแอปพลิเคชันจำหน่ายตั๋ว
- เราต้องการจัดกิจกรรมเล็กๆ เพื่อประชาสัมพันธ์โรงละครขนาดเล็ก
- เนื้อหาของกิจกรรม: จัดการจับฉลากเพื่อมอบบัตรเชิญให้กับผู้ชมที่ได้รับเลือก เพื่อเข้าชมการแสดงโดยไม่เสียค่าใช้จ่าย
- เราจำเป็นต้องแยกผู้ชมที่ได้รับรางวัลจากกิจกรรมออกจากผู้ที่ไม่ได้รับรางวัล
- ผู้ชมที่ได้รับรางวัลจากกิจกรรม: แลกเปลี่ยนบัตรเชิญเป็นตั๋วเข้าชม
- ผู้ชมที่ไม่ได้รับรางวัลจากกิจกรรม: ซื้อตั๋วโดยใช้เงินสด
ปัญหาอยู่ที่ไหน
โรเบิร์ต มาร์ติน ได้อธิบายถึงฟังก์ชันทั้งสามอย่างที่โมดูลซอฟต์แวร์ (ไม่ว่าจะมีขนาดเท่าใดก็ตาม เช่น คลาส แพ็กเกจ หรือไลบรารี องค์ประกอบใดๆ ที่ประกอบเป็นโปรแกรม)
- ทำงานได้อย่างถูกต้องในระหว่างการรัน
- มีไว้เพื่อการแก้ไข
- ต้องสามารถแก้ไขได้โดยใช้ขั้นตอนง่ายๆ
- สื่อสารกับผู้ที่อ่านโค้ด
- นักพัฒนาต้องสามารถอ่านและทำความเข้าใจได้ง่าย
แอปพลิเคชันจำหน่ายตั๋วที่กล่าวถึงก่อนหน้านี้ตรงตามข้อจำกัดแรกที่ว่าทำงานได้อย่างถูกต้อง แต่ไม่สามารถตรงตามวัตถุประสงค์ด้านความสะดวกในการแก้ไขและการสื่อสารได้
โค้ดที่ไม่ตรงตามที่คาดหวัง
ลองมาดูเหตุผลที่ไม่ตรงตามวัตถุประสงค์ด้านการสื่อสารกัน
- สิ่งที่เมธอด enter() ของคลาส Theater ทำ
- โรงละครจะเปิดกระเป๋าของผู้ชมเพื่อตรวจสอบว่ามีบัตรเชิญอยู่ภายในหรือไม่
- หากพบว่ามีบัตรเชิญอยู่ภายในกระเป๋า โรงละครจะสั่งให้พนักงานขายตั๋ว ย้ายตั๋วที่เก็บไว้ในห้องจำหน่ายตั๋วไปไว้ในกระเป๋าของผู้ชม
- หากไม่พบว่ามีบัตรเชิญอยู่ภายในกระเป๋า โรงละครจะหยิบเงินสดออกจากกระเป๋าของผู้ชมตามจำนวนเงินค่าตั๋ว ซื้อตั๋ว และใส่ตั๋วลงในกระเป๋าของผู้ชม
- ในมุมมองของผู้ชม ผู้ชมจะต้องนั่งเฝ้าดูโรงละคร ซึ่งเป็นบุคคลที่สาม เปิดกระเป๋าของตนเองหยิบเงินของตนเอง และใส่ตั๋วลงไป
- ในมุมมองของพนักงานขายตั๋ว พนักงานขายตั๋วจะต้องนั่งเฝ้าดูโรงละคร ซึ่งเป็นบุคคลที่สาม จัดการกับตั๋วและเงินสดในห้องจำหน่ายตั๋วโดยไม่ได้รับอนุญาต
- โค้ดที่เข้าใจได้ง่าย หมายถึงโค้ดที่การทำงานไม่เบี่ยงเบนไปจากที่เราคาดหวังมากนัก แต่โรงละครในตัวอย่างนี้เบี่ยงเบนไปจากที่เราคาดหวัง
- ผู้ชมควรหยิบเงินสดจากกระเป๋าของตนเองเพื่อจ่ายให้กับพนักงานขายตั๋ว และรับตั๋วจากพนักงานขายตั๋ว
- พนักงานขายตั๋วควรหยิบตั๋วจากห้องจำหน่ายตั๋ว มอบให้กับผู้ชม และรับเงินจากผู้ชมเพื่อเก็บไว้ในห้องจำหน่ายตั๋ว
- นอกจากนี้ เพื่อให้เข้าใจเมธอด enter() เราต้องจดจำรายละเอียดต่างๆ มากมาย
- Audience มี Bag
- Bag บรรจุเงินสดและตั๋ว
- TiketSellet ขายตั๋วจาก TicketOffice และ TicketOffice เก็บเงินสดและตั๋ว
โค้ดที่อ่อนไหวต่อการเปลี่ยนแปลง
เมธอด enter() สันนิษฐานเงื่อนไข 2 ข้อ
- ผู้ชมจะพกกระเป๋าติดตัวไปเสมอเพื่อเก็บเงินสดและบัตรเชิญ
- พนักงานขายตั๋วจะขายตั๋วเฉพาะที่ห้องจำหน่ายตั๋วเท่านั้น
แล้วสถานการณ์ต่อไปนี้ล่ะ
- ผู้ชมอาจไม่มีกระเป๋า
- ผู้ชมอาจใช้บัตรเครดิตแทนเงินสด
- พนักงานขายตั๋วอาจขายตั๋วข้างนอกห้องจำหน่ายตั๋วได้
ยกตัวอย่างเช่น หากต้องการตรงตามข้อกำหนดแรก เราต้องลบคลาส Bag ของ Audience และแก้ไขเมธอด enter() ของคลาส Theater เนื่องจากคลาส Theater ขึ้นอยู่กับข้อมูลรายละเอียดมากเกินไป เช่น ผู้ชมมีกระเป๋า และพนักงานขายตั๋วขายตั๋วเฉพาะที่ห้องจำหน่ายตั๋วเท่านั้น หากมีการเปลี่ยนแปลงข้อมูลรายละเอียดใดๆ แม้เพียงรายละเอียดเดียว เราจำเป็นต้องแก้ไขทั้งคลาสที่เกี่ยวข้องและคลาสที่ขึ้นอยู่กับคลาสดังกล่าว (เช่น Theater)
นี่คือปัญหาที่เกี่ยวข้องกับการพึ่งพาระหว่างออบเจ็กต์ และการพึ่งพาบ่งบอกถึงผลกระทบจากการเปลี่ยนแปลง อย่างไรก็ตาม เป้าหมายของการออกแบบเชิงวัตถุคือการสร้างชุมชนของออบเจ็กต์ที่ทำงานร่วมกันโดยการพึ่งพาอาศัยกัน ดังนั้นเราจึงไม่ควรพยายามกำจัดการพึ่งพาทั้งหมด แต่ควรรักษาการพึ่งพาให้น้อยที่สุดและกำจัดการพึ่งพาที่ไม่จำเป็นออกไป
กรณีที่ออบเจ็กต์พึ่งพาอาศัยกันมากเกินไป เราเรียกว่ามีความสัมพันธ์สูงโดยที่ยิ่งออบเจ็กต์สองตัวมีความสัมพันธ์สูงมากเท่าใด ก็ยิ่งมีโอกาสที่จะต้องเปลี่ยนแปลงไปพร้อมกันมากขึ้นเท่านั้น ดังนั้นเป้าหมายของการออกแบบจึงคือการลดความสัมพันธ์ระหว่างออบเจ็กต์ เพื่อให้การออกแบบมีความยืดหยุ่นในการแก้ไข
การปรับปรุงการออกแบบ
Theater ไม่จำเป็นต้องรู้ว่าผู้ชมมีกระเป๋าหรือพนักงานขายตั๋วขายตั๋วที่ห้องจำหน่ายตั๋ว Theater ต้องการเพียงให้ผู้ชมเข้ามาในโรงละครเท่านั้น ดังนั้นเราควรสร้างผู้ชมและพนักงานขายตั๋วให้เป็นอิสระต่อกัน โดยที่ผู้ชมจัดการเงินสดและบัตรเชิญในกระเป๋าของตนเอง และพนักงานขายตั๋วจัดการตั๋วและค่าตั๋วในห้องจำหน่ายตั๋วของตนเอง
เพิ่มความเป็นอิสระ
ออบเจ็กต์ที่ดำเนินการเฉพาะงานที่เกี่ยวข้องอย่างใกล้ชิด และมอบหมายงานที่ไม่เกี่ยวข้องให้กับออบเจ็กต์อื่น เราเรียกว่าออบเจ็กต์ที่มีการรวมกลุ่มสูง การสร้างออบเจ็กต์ที่เป็นอิสระที่สามารถจัดการข้อมูลของตนเองได้ จะช่วยลดความสัมพันธ์และเพิ่มการรวมกลุ่ม
การเขียนโปรแกรมเชิงกระบวนการและการเขียนโปรแกรมเชิงวัตถุ
- การเขียนโปรแกรมเชิงกระบวนการ
- เมธอด enter() ของ Theater เป็นกระบวนการ และ Audience, TicketSeller, Bag, TicketOffice เป็นข้อมูล
- การวางกระบวนการและข้อมูลในโมดูลที่แยกจากกัน เรียกว่าการเขียนโปรแกรมเชิงกระบวนการ
- มีโค้ดที่ขัดแย้งกับสัญชาตญาณของเรามากมาย (เช่น ผู้ชมจัดการเงินและบัตรเชิญด้วยตนเอง)
- ยากที่จะจำกัดผลกระทบจากการเปลี่ยนแปลงข้อมูล
- จัดการความรับผิดชอบแบบรวมศูนย์ (Theater จัดการทุกอย่าง)
- การเขียนโปรแกรมเชิงวัตถุ
- การวางข้อมูลและกระบวนการไว้ในโมดูลเดียวกัน เรียกว่าการเขียนโปรแกรมเชิงวัตถุ
- สามารถเขียนโค้ดที่สอดคล้องกับสัญชาตญาณของเราได้
- สามารถจำกัดผลกระทบจากการเปลี่ยนแปลงข้อมูลได้อย่างมีประสิทธิภาพผ่านการห่อหุ้ม
- ออบเจ็กต์แต่ละตัวรับผิดชอบตัวเอง
ยังสามารถปรับปรุงได้อีก
- คลาส Bag ของคลาส Audience ยังคงเป็นออบเจ็กต์แบบพาสซีฟที่ถูกควบคุมโดยคลาส Audience ดังนั้นเราจึงจำเป็นต้องสร้างคลาส Bag ให้เป็นออบเจ็กต์แบบแอคทีฟ
- TicketOffice ของคลาส TicketSeller ก็ถูกควบคุมโดย TicketSeller เช่นกัน เราจำเป็นต้องสร้าง TicketOffice ให้เป็นออบเจ็กต์แบบแอคทีฟ
- แต่หลังจากการเปลี่ยนแปลง TicketOffice มีความสัมพันธ์กับ Audience เพิ่มขึ้น
- การออกแบบจำเป็นต้องพิจารณาการแลกเปลี่ยนผลประโยชน์ ในกรณีนี้ เราอาจตกลงที่จะสร้าง TicketOffice ให้เป็นออบเจ็กต์แบบพาสซีฟบางส่วน เพื่อลดความสัมพันธ์กับ Audience
ไม่จริงหรอก!
- ในโลกแห่งความเป็นจริง แม้ว่าออบเจ็กต์จะเป็นแบบพาสซีฟ แต่เมื่อเข้าสู่โลกของการเขียนโปรแกรมเชิงวัตถุ ออบเจ็กต์ทุกอย่างจะกลายเป็นแบบแอคทีฟและเป็นอิสระ
- การใช้การเปรียบเทียบกับมนุษย์ (Anthropomorphism) เพื่อจินตนาการถึงออบเจ็กต์แบบพาสซีฟว่าเป็นสิ่งที่มีความรู้สึก สามารถหัวเราะ พูดคุย และโกรธ เป็นสิ่งที่ดี
การออกแบบเชิงวัตถุ
ทำไมต้องออกแบบ
- การออกแบบคือการจัดวางโค้ด
- การออกแบบที่ดีคือการที่สามารถทำงานตามฟังก์ชันที่ต้องการในปัจจุบันได้อย่างสมบูรณ์ และสามารถรองรับการเปลี่ยนแปลงในอนาคตได้อย่างราบรื่น
การออกแบบเชิงวัตถุ
- โค้ดที่สามารถแก้ไขได้ง่ายคือโค้ดที่เข้าใจง่าย
- พาราไดม์เชิงวัตถุช่วยให้เราสามารถเขียนโค้ดได้ตามวิธีที่เราเห็นโลก
- ออบเจ็กต์เป็นสิ่งที่มีความเป็นอิสระที่รับผิดชอบข้อมูลของตัวเอง
- การออกแบบเชิงวัตถุที่ดีคือการจัดการการพึ่งพาระหว่างออบเจ็กต์ที่ทำงานร่วมกันอย่างเหมาะสม
แหล่งที่มา
- ออบเจ็กต์
ความคิดเห็น0