Observer Pattern: จัดการอีเวนต์และลดการผูกมัดโค้ด PHP
เจาะลึก Observer Pattern ในการพัฒนาซอฟต์แวร์ PHP ช่วยแยกตรรกะธุรกิจออกจากแคชและการแจ้งเตือน พร้อมข้อดี-ข้อเสียที่นักพัฒนาต้องรู้

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
- การใส่โค้ดจัดการแคชและแจ้งเตือนใน save() ละเมิด Single Responsibility Principle
- Observer Pattern แยก Subject ออกจาก Observer ทำให้อ็อบเจกต์ไม่ผูกมัดกันโดยตรง
- Soft PHP MVC ใช้การทำงานแบบซิงโครนัสเพื่อความเรียบง่ายและง่ายต่อการดีบัก
- การใช้ pattern มีข้อแลกเปลี่ยนด้านความซับซ้อนในการแกะรอยการทำงานของโค้ด
เมื่อบันทึกบทความ คุณต้องล้างแคช เมื่อลบผู้ใช้ คุณต้องลบเซสชัน การกระทำทุกอย่างย่อมก่อให้เกิดปฏิกิริยาลูกโซ่ และความอยากรู้อยากเห็นมักผลักดันให้นักพัฒนายัดเยียดทุกอย่างลงในเมธอด save() ของโมเดล ส่งผลให้เมธอดเดียวต้องทำงานถึงสิบอย่างและรู้จักโค้ดส่วนอื่นทั้งหมด ซึ่งถือเป็นการละเมิด Single Responsibility Principle อย่างชัดเจน โดยหน้าที่หลักของโมเดลควรดูแลเรื่องการจัดเก็บข้อมูล ไม่ใช่การจัดการแคช การส่งการแจ้งเตือน หรือระบบตรวจสอบบันทึก
รูปแบบ Observer Pattern เข้ามาช่วยทำลายลูกโซ่ความสัมพันธ์อันตรงไปตรงมานี้ โมเดลจะไม่รู้ว่าใครกำลังเฝ้าดูมันอยู่และไม่จำเป็นต้องสนใจด้วยซ้ำ โมเดลรู้เพียงแค่ว่าเมื่อสถานะของมันเปลี่ยนไป จะต้องแจ้งเตือนไปยังผู้ที่ลงทะเบียนไว้ การล้างแคช การบันทึกประวัติการตรวจสอบ หรือการส่งอีเมลแจ้งเตือน ล้วนเป็นผู้สังเกตการณ์ที่ทำงานแยกส่วนต่างหากจากโมเดลที่เป็นตัวกระตุ้น ผู้สังเกตการณ์แต่ละรายจะมีหน้าที่รับผิดชอบเพียงอย่างเดียว ขณะที่โมเดลก็จะได้หน้าที่ของตนเองคืนกลับมา
ตามนิยามของ Gang of Four (GoF) อธิบายว่า Observer คือพฤติกรรมแพตเทิร์นที่กำหนดความสัมพันธ์แบบหนึ่งต่อหลายระหว่างอ็อบเจกต์ เพื่อให้เมื่ออ็อบเจกต์ตัวหนึ่งเปลี่ยนสถานะ อ็อบเจกต์ที่พึ่งพากันทั้งหมดจะได้รับการแจ้งเตือนและอัปเดตโดยอัตโนมัติ โดยมีองค์ประกอบหลักคือ Subject (อ็อบเจกต์ที่ถูกสังเกต), Observer (อินเทอร์เฟซสำหรับผู้สังเกต), และ ConcreteObserver (การ implement จริงที่ตอบสนองต่อการเปลี่ยนแปลง)
Subject ทำหน้าที่เก็บรายชื่อของ Observer ที่ลงทะเบียนไว้ พร้อมทั้งมีเมธอดสำหรับเพิ่มและลบผู้สังเกตการณ์ เมื่อสถานะเปลี่ยนไป Subject จะวนลูปรายชื่อและเรียกใช้งานเมธอดแจ้งเตือนของ Observer แต่ละตัว หัวใจสำคัญคือการกลับด้านการพึ่งพา (Dependency Inversion) โดยที่ Subject ไม่ได้ขึ้นอยู่กับ ConcreteObserver แต่ขึ้นอยู่กับอินเทอร์เฟซ Observer แทน การเพิ่มผู้สังเกตการณ์รายใหม่จึงไม่ต้องแก้ไขโค้ดใน Subject เพียงแค่ลงทะเบียนการ implement ใหม่เท่านั้น

ภาพประกอบจากคลังภาพสต็อก ไม่ใช่ภาพจากเหตุการณ์จริง
ในทางสถาปัตยกรรมซอฟต์แวร์ การใช้ Dependency Inversion ผ่าน Observer Pattern ช่วยให้ระบบมีความยืดหยุ่นสูงมาก คล้ายกับการใช้ Event Dispatcher ในเฟรมเวิร์กสมัยใหม่อย่าง Laravel หรือ Symfony ซึ่งช่วยลดการแก้ไขโค้ดเดิม (Open/Closed Principle) แต่ในขณะเดียวกัน นักพัฒนาต้องระวังปัญหา 'Callback Hell' หรือความยากในการติดตามการทำงานแบบ Asynchronous หากระบบเติบโตขึ้นจนซับซ้อนเกินไป
ในเฟรมเวิร์ก โมเดลทุกตัวจะต้องผ่านวงจรชีวิต (Lifecycle) ที่มีฮุกระบุไว้ชัดเจน เช่น beforeSave, afterSave, beforeDelete และ afterDelete ซึ่งฮุกเหล่านี้ไม่ใช่ event แบบดั้งเดิมในความหมายของ event dispatcher แต่เป็นเทมเพลตเมธอดที่คลาสลูกสามารถเขียนทับได้ คล้ายกับรูปแบบ Template Method ที่เฟรมเวิร์กวางโครงกระดูกไว้และให้โมเดลรูปธรรมเติมรายละเอียดลงไป
ตัวอย่างการใช้งานจริงคือ QueryCacheObserver เมื่อโมเดลที่มีเทรท HasQueryCache ถูกบันทึกหรือถูกลบ แคชของคิวรีที่เกี่ยวข้องจะถูกยกเลิกโดยอัตโนมัติ โมเดลไม่ต้องเรียกคำสั่ง Cache::forget() ด้วยตัวเอง แต่เทรทจะเป็นตัวลงทะเบียน Observer และ Observer จะจัดการทำความสะอาดให้ หากในอนาคตกลยุทธ์การแคชเปลี่ยนไป โมเดลก็จะไม่ได้รับผลกระทบใดๆ ทั้งสิ้น
ที่มา: Dev.to
พบข้อมูลผิดพลาดในบทความนี้? แจ้งปัญหาบทความนี้
ความคิดเห็น
แสดงความคิดเห็น