หลังจากทำการ review code ไปนิดหน่อย
พบว่าได้เจอ code ที่น่าสนใจ เนื่องจากจะขัดกับ
Law of Demeter พอควร
ผลที่ตามมาคือ
code ทำงานได้
แต่มีการเรียกต่อกันเป็นทอด ๆ ยาวมาก ๆ
ยกตัวอย่างเช่น game.Board.Size.X และ g.Board.Slots[i][j].Number เป็นต้น
แต่ตามจริงเราต้องการเพียงค่าสุดท้ายเท่านั้นเอง
ทำไมเราต้องเขียน code ยาวขนาดนี้กันด้วย ?
น่าคิดมาก ๆ
หรือเราคิดว่า มันคือเรื่องปกติ เพราะว่า โครงสร้างของระบบเราเป็นแบบนี้ ?
ดังนั้นมาปรับปรุง code ชุดนี้กันหน่อยดีไหม ?
เริ่มต้นด้วยการทำความเข้าใจกับ Law of Demeter
ง่าย ๆ คือ
เราสามารถเรียกใช้งาน method จาก class ที่ต้องการตรง ๆ ได้เลย ไม่ต้องอ้อมค้อม
ยกตัวอย่างเช่น
ต้องการดึงข้อมูลที่อยู่ของพนักงานก็ใช้ผ่าน employee.getAddress() ได้เลย
จะไม่มีการเรียกซ้อนกันไปเยอะ ๆ (Chain of message)
ดังเช่นตัวอย่างเช่น
employee.getAddress().getCountry().getName()
employee.getAddress().getProvince().getName()
employee.getAddress().getCurrentAddress()
ผลเสียที่ตามมาคือ
class ต่าง ๆ จะผูกมัดกันอย่างมาก
เมื่อจะแก้ไขอะไรก็ตาม จะกระทบกันมากมาย
อารมณ์คล้าย ๆ โครงสร้างขององค์ที่ที่มีลำดับชั้นเยอะ ๆ นั่นเอง
เขียน code ก็เยอะ
แก้ไขอย่างไรดี ?
ถ้าสร้าง method ใน employee เพื่อส่งค่าที่ต้องการออกมาเลยดีไหม ?
employee.getCurrentAddress()
employee.getAddressCountry()
employee.getAddressProvince()
มุมมองของคนเรียกใช้งาน จะได้ไม่ต้องสนใจว่า employee ใช้งานอะไรบ้าง
เพื่อแค่เรียก method ที่มีใน employee ก็ใช้ได้เลย
ง่ายกว่าไหม ?
อันนี้คงต้องตอบกันเองแล้วนะ
กลับมาดูในภาษา Go กันบ้าง
การใช้งาน struct มักจะมีการใช้งาน embedd type
หรือ struct ซ้อน struct นั่นเอง
แต่พอมาเจอ code จริง ๆ มีซ้อนกันจำนวนมาก ลึกมาก ๆ
[gist id="28ccd86fe3ecf3d0d0ab211505adf1a4" file="1.go"]
ถ้าต้องการดูข้อมูลของ state ต้องเรียกใช้งานผ่าน game.board.state
แต่เราต้องการเพียง state นะ
ดังนั้นมาแก้ไขกัน เพราะว่าเราเปิดเผยการทำงานมากไป
การแก้ไขมีทั้งลบทิ้งไป กับทำการซ่อนไปซะ
ตัวอย่างเป็นการซ่อนดังนี้
[gist id="28ccd86fe3ecf3d0d0ab211505adf1a4" file="2.go"]
นี่เป็นเพียงการแก้ไขหรือปรับปรุง code ให้ดีขึ้นมาอีกนิด
น่าจะทำให้ทีมเข้าใจ code ได้ง่ายขึ้น
แต่ code จะดีเพียงใด แต่คนในทีมไม่เข้าใจ ก็ไร้ค่านะครับ
ขอให้สนุกกับการเขียน code ครับ