/ OOD

[365 วันแห่งโปรแกรม #day10] Accessors

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


ในภาษาโปรแกรมที่เป็น OOP จะมีหลักการเกี่ยวกับการปกปิด state ของวัตถุ แต่ใน best practice ของภาษาต่างๆ ยังกลับมีคำแนะนำให้ใช้ Accessors หรือที่เรารู้จักกันในนามของ Getter/Setter หรือ Property

Accessors นั้นถูกใช้เพื่อทดแทน public member กันหลายแพร่หลาย ทั้งๆ ที่ก็รู้กันว่ามันละเมิดหลักการของ OO อย่างน้อยก็ในเรื่องของ encapsulation แล้วเพราะอะไรเราถึงยังใช้กันอยู่ละ ? เพราะไม่รู้ ? เพราะชินกับการเขียนโปรแกรมแบบ Procedural ? เข้าใจว่าคลาสคือ struct แบบใหม่ ?

เราลองเปลี่ยนมามองอีกมุมกันก่อนดีกว่า ทำไมถึงบอกว่า Accessors นั้นมีปัญหา ทั้งๆ ที่เราใช้ไปมันก็ work ดีนะ ปิดแค่ที่อยากจะปิด เปิดแค่ที่อยากจะเปิด เรามาลองนึกถึงเหตุผลที่ทุกวันนี้เรายังใช้ Accessors อยู่ก็คือ

  • เราต้องการนำ state ของวัตถุนั้นๆ มาใช้ในการตัดสินใจอะไรบางอย่าง เอ.. แล้วทำไมเราไม่ให้วัตถุนั้นตัดสินใจเองซะเลยล่ะ?

  • เราต้องการ export ค่าบางอย่างออกมาจากวัตถุนั้นๆ หัวใจหลักของโปรแกรมคือการสื่อสารกันระหว่าง component การขอดูค่าบางอย่างก็ไม่น่าผิดอะไร?

ทั้งสองข้อก็ล้วนมีเหตุผลของตัวเองทั้งนั้น แต่ช้าก่อน ใน OO บอกว่า state ของโปรแกรมน่ะต้องถูกซ่อนจากภายนอกนะ และโปรแกรมควรจะมองวัตถุแบบ abstract ไม่ใช่มอง detail (state มักถูกรวมอยู่ใน implementation เสมอ) เพราะอะไร? ลองทบทวนดูอีกครั้ง OO นั้นถูกออกแบบมาเพื่อความเป็น modular หมายถึงว่าชิ้นส่วนหนึ่งๆ ควรจะถูกทดแทนด้วยชิ้นส่วนชนิดเดียวกันได้โดยไม่ต้องแก้ไขโปรแกรม ลองคิดดูว่าถ้าในโปรแกรมของเรามีการดึงค่า X ที่มีชนิดเป็น int ออกมาจากวัตถุหนึ่ง 1000 ครั้ง แล้วอยู่ๆ วันหนึ่ง เรามีความจำเป็นต้องเปลี่ยนวิธี implement วัตถุนั้นใหม่ โดยมี behavior เหมือนเดิม (สร้างคลาสใหม่จาก base cass เดียวกัน) โดยที่ไม่มีตัวแปร X นั้นอีกแล้ว หรือ เปลี่ยนชนิดตัวแปรเป็น double เราก็ต้องมานั่งแก้ 1000 จุด ที่เรียกใช้ X แทนที่จะ implement แค่คลาสนั้นใหม่

"Don't ask for the information you need to do the work; ask the object that has the information to do the work for you." - Allen Holub

แต่เดี๋ยวก่อน มันยังมีกรณีที่จะอัพเดท UI เราจำเป็นต้องดึงค่ามาแสดง เราอาจจะสามารถโยน UI Element เข้าไป ให้อัพเดตจากใน object นั้นก็ทำได้ แต่บางคนก็บอกว่าขัดกับหลักการเรื่องแยก business model ออกจาก view ซึ่งก็เป็นปัญหาใหม่อีก อีกทั้งในหลายๆ แพลตฟอร์มที่มี UI แบบ bind to property ยังไม่อนุญาตให้ bind กับ property ที่เป็น private อีก

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

อยากอ่านเพิ่ม ไปที่นี่เลยครับ javaworld หรือไม่ก็ search ว่า getter and setter are evil ก็จะเห็นคน discuss เรื่องนี้กันเยอะแยะมากมาย

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