/ OOP

[365 วันแห่งโปรแกรม #day11] ปัญหาของ Implementation inheritance

วันที่สิบเอ็ดของ ‪#‎365วันแห่งโปรแกรม‬ วันนี้เราจะมีคุยกันเรื่อง ปัญหาของ Implementation inheritance


จากบทความเรื่อง Why getter and setter methods are evil ของ Allen Holub ที่ผมนำมาเล่าเมื่อวาน ในนั้นมีการพูดถึงอีกบทความหนึ่งของเขาคือ Why extends is evil ซึ่งชื่อมันดูน่าสนใจดี ผมลองอ่านดูแล้วก็เห็นว่าดีเลยเอามาแชร์

ใน OOP วัตถุจะมีคุณสมบัติของการสืบทอด (Inheritance) ซึ่งก็มีหลาย implementation ของคุณสมบัติที่ว่านี้ หลักๆ ก็คือ implementation inheritance (สืบทอดจาก class) และ interface inheritance (สืบทอดจาก abstraction) ความต่างของสองอันที่กล่าวมาคืออันแรกคลาสที่สืบทอดไปจะได้ concrete method ไปด้วย ไม่ต้อง implement ใหม่ แต่สามารถ override ทับได้ ส่วนอันที่สองคลาสที่สืบตอบไปจะได้ abstract method ซึ่งต้อง implement วิธีการทำงานเองทั้งหมดก่อน ถึงจะใช้งานได้

บิดาแห่งภาษาจาวา (James Gosling) เคยกล่าวไว้ว่าถ้าย้อนกลับไปทำจาวาใหม่ได้เขาจะเอาคลาสออกไป เขาอธิบายว่าปัญหาจริงๆ ไม่ใช่เรื่องคลาส แต่เป็นเรื่องของการสืบทอดจากคลาส (implementation inheritance) และเขายังแนะนำอีกว่าให้ใช้วิธีสืบทอดจาก abstraction (interface inheritance) ทุกครั้งที่ทำได้ คำถามคือทำไมเข้าถึงพูดอย่างนั้น?

Implementation inheritance

  • Implementation inheritance ทำให้เสียความยืดหยุ่น การอ้างถึง concrete class ทำให้เราถูดล็อคติดอยู่กับ implementation นั้นๆ ทำให้การปรับเปลี่ยนต่างๆ ยุ่งยาก

  • Implementation inheritance ทำให้เกิดปัญหาการผูกติดของโค้ด (Coupling) ซึ่งใน OO นั้นบอกว่าเราควรจะลดการ Coupling ลงให้เหลือน้อยที่สุดเท่าที่จะทำได้

  • Implementation inheritance ทำให้เกิด fragile base-class problem คือภาวะที่เราไม่สามารถบอกได้เลยว่าหากเราแก้คลาสๆ นึงแล้ว มันจะไปกระทบต่อความถูกต้องของคลาสอื่นหรือไม่ เพราะว่าคลาสใหม่ของเรานั้นผูกติดอยู่กับ behavior ของอีกคลาสหนึ่ง ซึ่งอาจจะโดนแก้เมื่อไหร่ก็ไม่รู้

  • Implementation inheritance ทำให้เราได้ behavior บางอย่างที่ไม่ต้องการเป็นของแถม เช่นการ implement Stack จาก ArrayList เราย่อมได้ฟังก์ชัน insert แบบกำหนดตำแหน่ง ฟังก์ชันสำหรับดึงค่าแบบกำหนดตำแหน่ง ซึ่งเราไม่ได้ต้องการ แต่ก็ไม่สามารถปิดการเข้าถึงได้เลย ทำได้ดีที่สุดแค่ override ทับทุก function ที่ไม่ต้องการแล้วให้คืนเป็น exception แทน

แล้วควรทำยังไง?

ทางออกของปัญหาเหล่านี้คือเลี่ยงไป inherit จาก interface (interface inheritance) แทน หรือกล่าวคือสร้าง interface ของสร้างคลาสทุกครั้ง แต่เดี๋ยวก่อน การสืบทอดจากคลาสสู่คลาสมันไม่ได้เลวร้ายขนาดนั้น ข้อดีที่เห็นได้ชัดๆ คือทำให้เราสามารถลดการซ้ำซ้อนของโค้ดได้เพราะเราสามารถเขียนทีเดียวแล้วใช้วิธีสืบทอดไปยังลูกหลานไม่ต้องทำใหม่เรื่อยๆ

อยากอ่านต้นฉบับ? ไปที่นี่เลย javaworld

‪#‎day11‬ #365วันแห่งโปรแกรม ‪#‎โครงการ365วันแห่ง‬...