Open/Closed Principle
👑 หัวใจหลักของ Open/Closed Principle (OCP)
Software entities (classes, modules, functions, etc.) should be open for extension but closed for modification.
"การออกแบบซอฟต์แวร์ จะต้องเพิ่มความสามารถใหม่ๆให้ซอฟต์แวร์เราได้ โดยที่ห้ามไปยุ่งกับโค้ดเดิมนะ!" นี่หัวคือใจหลักในเรื่อง OCP ในรอบนี้ แค่อ่านก็กาวแล้ว ถ้าเราจะเพิ่มความสามารถหรือพฤติกรรมใหม่ๆ ปรกติเราก็ต้องแก้โค้ดเดิมนิ แต่นี่เล่นไม่ให้แก้โค้ดเดิมเลย แล้วมันจะทำยังไงกันล่ะ?
❓ ทำไมต้องห้ามแก้โค้ดล่ะ ?
ในการแก้โค้ดเพียง 1 ครั้ง นั่นหมายถึงอาจะเกิด bug ตามมาในโปรแกรมได้ (บางทีแก้ 1 ครั้ง bug อาจะเกิดเป็นสิบๆตัวเลยก็ได้) ดังนั้นเขาเลยบอกว่าโค้ดที่มันเคยใช้งานได้อยู่แล้ว จงอย่าไปยุ่งกับมันปล่อยให้มันทำงานไป ส่วนถ้าอยากได้ความสามารถใหม่ๆจงเขียนโค้ดตัวใหม่เข้าไปเพิ่มซะ
😕 แล้วจะเพิ่มความสามารถใหม่ๆยังไง โดยไม่แก้โค้ดเดิม ?
โดยปรกติเวลาเราเขียนโค้ด เราจะชอบเขียนให้โค้ดมันดิ้นไม่ได้โดยไม่รู้ตัว เช่น กำหนดว่า method นี้จะต้องรับ parameter เป็น Concrete class นี้นะ ตามตัวอย่างด้านล่าง
Concrete class คือคลาสธรรมดาที่เราสร้างขึ้นมานี่แหละ และเป็นคลาสที่สามารถเอาไปใช้สร้าง object ได้เลย (ในคำนิยามจริงๆมันคือคลาสที่ตายตัวอ่ะนะ อ่านแล้วอาจจะ งงๆ)
ปัญหาจากโค้ดตัวอย่าง เราจะไม่สามารถส่ง object อื่นๆเข้าไปทำงานกับ method ReadAllTextFromFile() ได้เลยนอกเสียจาก object ที่มาจาก PdfFile และลูกๆของมันเท่านั้น ดังนั้นทุกครั้งที่เราอยากให้มันอ่านไฟล์แบบใหม่ได้ เราก็ต้องมาแก้โค้ดตรงนี้เสมอๆ แบบนี้ถือว่าละเมิดกฎ OCP
💡 การแก้ให้โค้ดของเราดิ้นได้
แทนที่เราจะไปผูกติด (coupling) โค้ดของเราเข้ากับ Concrete class เราก็แค่เปลี่ยนมาใช้ Abstraction งุยล่ะ
Abstraction คือคลาสที่ไม่ได้ระบุเฉพาะเจาะจงลงไปว่ามันต้องเป็นตัวไหน เช่น abstract class หรือ interface และรวมถึงการทำ Polymorphism ด้วย
ดังนั้นเราก็แค่เปลี่ยน method ด้านบนให้รับเป็น abstraction ตามโค้ดด้านล่างก็พอแล้ว
จากโค้ดด้านบนจะเห็นว่า เราสามารถส่งคลาสอะไรก็ได้ที่ implement IDocument เข้าไป มันก็จะสามารถทำงานด้วยได้หมดแล้วโดยที่เราไม่ต้องไปแก้ไขโค้ด ReadAllTextFromFile() แม้แต่บรรทัดเดียวเลย นี่แหละพลังแห่งการออกแบบและไม่ผิดกฎ OCP
😒 ควรออกแบบยังไงดี
สมมุติว่าเราต้องเขียนโปรแกรมจัดการไฟล์ PDF โดยที่มีคลาสจัดการไฟล์อยู่ 1 ตัว (DocumentManager) เราจะออกแบบยังไง ?
😟 การออกแบบที่ไม่ดี
ถ้าเราออกแบบให้ตัวจัดการไฟล์มันไปผูกติดอยู่กับ Concrete class เลยนั่นหมายถึง เวลาที่เราจะแก้ไขอะไร เราจะต้องไปแก้ไขเจ้า concrete class ตัวนั่นเท่านั้น นี่คือตัวอย่างการละเมิดกฎ OCP ทำให้ทุกครั้งที่จะเพิ่มไฟล์ประเภทใหม่ๆเข้าไป เช่น Word, Csv, Json ต่างๆ เราจะต้องแก้ไขโค้ดเดิมเสมอ ตามรูปด้านล่าง
😄 การออกแบบที่ควรเป็น
จากที่เราเคยผูกติดกับ Concrete class เราแค่เปลี่ยนมาเป็น Abstraction ซะ เพียงเท่านี้เราก็สามารถเปิดรับการทำงานร่วมกับไฟล์ใหม่ๆในอนาคตได้แล้ว เช่น Word, Csv, Json โดยที่เราไม่ต้องไปแก้ไขโค้ดเดิมเลย
หรือเราจะใช้ Design Pattern 2 ตัวนี้มาช่วยได้นะครับ
🎯 บทสรุป
Open/Closed Principle คือหนึ่งในหัวใจหลักในการออกแบบโค้ดแบบ OOP ซึ่งจะช่วยให้โค้ดเรายืดหยุ่นมากขึ้น reuse ได้และที่สำคัญคือบำรุงรักษาแก้ไขได้ง่ายขึ้นอีกจมเบย ดังนั้นอย่างนิ่งอยู่เฉย จงน้อมรับเอา OCP ไปฉีดเข้าเส้นไปซ๊าาา 🥴
Last updated