Software Design

🤰 Creational Patterns

ตัวช่วยในการสร้าง object

Best Practice Program to an interface and not to an implementation. หรือเราสามารถแปลง่ายๆได้ว่า การเขียนโค้ดต่างๆ ไม่ควรไปทำงานกับของระดับล่าง แต่จงทำงานกับระดับ abstraction เท่านั้น

🤔 ทำไมต้องเป็นแบบนั้น ?

ขออธิบายให้เห็นภาพก่อนว่า ในชีวิตจริงถ้าเราจะสร้างบ้านซักหลัง เราจะเดินไปบอก กรรมกร หรือ ผู้รับเหมา เพื่อให้เขาสร้างบ้านให้เรากัน? ... คำตอบก็คือผู้รับเหมายังไงล่ะ เพราะเขามีหน้าที่รับผิดชอบสร้างบ้านให้เรา ซึ่งเขาก็จะไปสั่งงานกรรมกรมาสร้างบ้านให้เราอีกทีหนึ่ง ซึ่งถ้ากรรมกพวกนั้นเกเร ผู้รับเหมาก็อาจจะเปลี่ยนกรรมกรก็ได้ ซึ่งก็ไม่เกี่ยวข้องอะไรกับเรานั่นเอง (Builder Patterns)

กลับมาที่โค้ดกันบ้าง สมมุติว่าเราอยากจะสร้าง object ของ หมา มาใช้งานซักตัว ปรกติเราก็มักจะเขียนโค้ดออกมาราวๆนี้

Dog dog = new Dog();

ซึ่งเจ้าโค้ดด้านบนก็ไม่ได้ผิดอะไรนะ แต่มันผิดหลักในการออกแบบ 😲 เพราะโค้ดของเราตอนนี้กำลังทำงานกับของระดับล่างอยู่ เพราะเราใช้คำสั่ง new ยังไงล่ะ และคลาส Dog มันก็เป็นการทำงานระดับล่าง หรือที่เราเรียกว่าระดับ Implementation แล้วยังไงล่ะ

👎 ข้อเสียในการทำงานกับของระดับล่าง

จากโค้ดด้านบน มันจะเป็นการผูกการทำงานของเราให้ต้องทำงานกับคลาส Dog เท่านั้น ไม่สามารถทำงานกับคลาสอื่นได้ ซึ่งถ้าเราอยากเปลี่ยนให้มันทำงานกับคลาสอื่นๆ เช่น คลาสแมว คลาสหมู ไรงี้ เราจะต้องเขียนโค้ดและ Compile มันใหม่ยกชุดเท่านั้น ซึ่งเราเรียกโค้ดลักษณะนี้ว่า Hardcode นั่นเอง

ข้อแนะนำ การเขียนโค้ดโดยใช้คำสั่ง new ก็ไม่ได้ผิดอะไรร้ายแรงหรอก เพียงแค่โค้ดมันไม่ยืดหยุ่นต่อการเปลี่ยนแปลงเฉยๆ ซึ่งข้อดีของมันคือ Developer ทุกคนทำได้ง่าย และไม่ซับซ้อน

👍 ข้อดีในการทำงานกับระดับ Abstraction

แทนที่เราจะทำงานกับคลาสที่เป็นระดับการทำงานจริงๆ (Implementation) ให้เราเปลี่ยนมาทำงานกับของที่เป็น Abstraction ของมันจะดีกว่า เพราะเราจะสามารถเปลี่ยนไปทำงานกับคลาสอื่นๆที่เป็นตระกูลนั้นได้ทุกตัวเลย

ข้อแนะนำ ความหมายของการ ทำงานกับระดับ Abstraction ไม่ได้หมายถึง abstract class นะ แต่เป็นการเหมารวมของที่เป็น ต้นแบบ หรือเรียกอีกแบบว่า Concept เช่น Abstract, Interface

เพราะการโค้ดของเราจะมีลักษณะของการทำ Polymorphism อยู่ภายในตัวเองอยู่แล้ว ดังนั้นมันจะสามารถรองรับการทำงานอื่นๆในอนาคตได้ทันที โดยที่เราเขียนโค้ดเพียงแค่ครั้งเดียวเท่านั้น เช่น เมื่อเราเพิ่มคลาส สิงห์โต, วัว และ หมีเข้าไป โค้ดเดิมที่ทำงานกับ Animal ที่เป็น Abstraction ก็จะรองรับเจ้าคลาสใหม่ๆพวกนั้นทันที โดยที่เราไม่ต้องไปแก้โค้ดอะไรทั้งสิ้นเลยนั่นเอง ตามรูปด้านล่าง

แนะนำให้อ่าน ใครจำเรื่อง Polymorphism ไม่ได้แล้วให้กดกลับไปทบทวนได้จากลิงค์นี้เลย 💖 Polymorphism

😭 ใครช่วยแก้ปัญหานี้ได้บ้าง ?

ในกุล่มของ Creational Patterns นี้มีพระเอกหลายตัวเลยที่จะมาช่วยแก้ปัญหาในการสร้าง object ซึ่งแต่ละตัวนั้น มันจะเหมาะกับปัญหาแต่ละแบบ ดังนั้นไปดูว่าแต่ละตัวมันช่วยแก้ปัญหาอะไรเลยละกัน

ช่วยสร้าง object ที่เหมาะสมกับสถานะการณ์ที่กำลังเป็นอยู่

ช่วยสร้างกลุ่มของ object ที่มีความเกี่ยวข้องกัน

ช่วยให้ object ตัวนั้นมีได้เพียงแค่ตัวเดียวเท่านั้น และใครๆสามารถเข้าถึงได้

ช่วยสร้าง object ที่มีขั้นตอนในการสร้างอันวุ่นวายให้ง่ายขึ้น

ช่วยในการก๊อปปี้ object หนึ่ง ออกไปเป็นอีก object ได้แบบง่ายๆ

คำเตือน ไม่ควรนำ Design Patterns ไปใช้ โดยไม่ได้ชั่ง ผลดี/ผลเสีย ให้เรียบร้อยก่อน เพราะมันจะทำให้โค้ดเราซับซ้อนโดยไม่จำเป็น แล้วจะแก้ไขปรับปรุงอะไรต่างๆก็จะกลายเป็นเต่า แต่จงศึกษา Design Patterns เพื่อเรียนรู้หลักในการออกแบบ เพื่อจะได้รู้ว่าเมื่อไหร่ไม่ควรใช้ Pattern

คอร์สนี้กำลังค่อยๆเขียนอยู่ ใครที่ไม่อยากพลาดอัพเดทก็เข้าไปกดติดตามที่ลิงค์ Mr.Saladpuk ได้เลย ส่วนใครที่อยากศึกษา pattern ตัวไหนล่วงหน้าก็ไปอ่านบทความเก่าได้ที่ลิงค์นี้ 🤴 Design Patterns (อ่านแล้วเมากาวไม่รู้ด้วยนะ) + ในคอร์สนี้จะเริ่มอธิบาย Pattern แต่ละตัวจากกลุ่มนี้ก่อนนะครัช