/ OOD

[365 วันแห่งโปรแกรม #day43] Object Oriented Design & Principles

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


เมื่อวานไม่ได้เขียนบทความเพราะว่านั่งคิดทบทวนอยู่นานว่าจะเขียนเรื่องนี้ดีไหม มันเป็นเรื่องง่ายที่ยากที่สุด เรื่องนั้นก็คือ Object Oriented Design & Principles ครับ จริงๆ แล้วผมเคยเขียนเรื่องนี้ไว้นิดหน่อยในบล็อก 2BeDev.com แล้วล่ะ แต่จนถึงตอนนี้ก็ยังไม่แน่ในว่าผมจะนำเสนอได้ถูกต้องแค่ไหน คือเมื่อเราลองอ่านๆ ดูเนี่ย ก็เห็นว่ามันง่ายนะใครๆ ก็ทำได้แหละ แต่พอเอาเข้าจริงกลับไม่สามารถทำตามได้เลย ยุ่งยากไปหมด เยอะ มองภาพไม่ออก ไม่รู้ความต้องการ ขี้เกียจ แต่ไม่ว่ายังไงผมก็ต้องเขียนเรื่องนี้ก่อน เพราะเรื่องอื่นมันต้องใช้ความรู้จากเรื่องนี้หมดเลย ><

Object Oriented Design คืออะไร?

อย่างที่เราได้พูดกันไปแล้วในเรื่องคุณสมบัติของ OOP ว่ามันมีอะไรบ้าง แต่ละอันใช้ทำอะไร ซึ่งเวลาเราเขียนโปรแกรมจริงๆ เราก็ต้องออกแบบใช่มั้ยครับ ว่าคลาสไหนจะเป็นยังไง แล้วมีความสัมพันธ์กับสิ่งอื่นอย่างไร นั่นเรียกว่า Object Oriented Design หรือ OOD ครับ ซึ่ง OOD เนี่ยเป็นส่วนหนึ่งของกระบวนการทำ Object-oriented analysis

ในการทำ OOD เราก็ต้องรู้ requirement ก่อน หลังจากนั้นเราก็จะสร้าง Conceptual Model, Use case diagram อะไรก็ว่าไป แล้วเราก็เอาของพวกนี้มีวิเคราะห์ ร่วมกับ OOP's Principles ผลลัพธ์ที่ได้ออกมาก็คือ Sequence diagram และ Class diagram ซึ่งเจ้าสองตัวนี้จะเป็นตัวที่บอกว่า Object ของเรามีหน้าตายังไง แล้วมีปฏิสัมพันธ๋กับ Object อื่นๆ หรือ ระบบอื่นๆ อย่างไร

อย่างไรก็ตามการใช้ความรู้อันน้อยนิดของเราทำสิ่งที่กล่าวมามันก็อาจจะไม่ได้ design ที่ดี เช่นมี coupling เยอะ แก้ไขลำบาก หรืออะไรก็แล้วแต่ ซึ่งวิธีแก้ตรงนี้ก็คือไปดูสิ่งที่คนอื่นเค้าเขียนไว้เป็นแนวทาง สิ่งนั้นเรียกว่า Object Oriented Design Principles

Object Oriented Design Principles คืออะไร?

การที่เราจะลองไปลองผิดลองถูกดูว่าเขียนยังไงถึงดีก็ทำให้เสียเวลาเกินไป เราก็ดูคนอื่นเลยละกันว่าเค้าเขียนกันยังไง ในเมื่อทุกคนก็เจอปัญหาแบบเดียวกับเรา มันก็เลยมีคนสรุปแนวทางการ design ออกมาเลยครับ เราเรียกแนวทางพวกนี้ว่า Object Oriented Design Principles หรือ OOD's Principles ซึ่งแนวทางพวกนี้ก็บอกว่าเราควรสร้าง Object อย่างไร จัดหมวดหมู่ยังไง การทำ interaction ระหว่าง objects ควรเป็นแบบไหน แนวทางเหล่านี้ก็มีอยู่หลายสำนักครับ แต่ที่ดังๆ และใช้กันเป็นสากลเลยก็คือ SOLID

SOLID เนี่ย เกิดกจากการเอา Principles 5 ตัวมารวมกัน ก็คือ

  • Single responsibility

  • Open/closed

  • Liskov substitution

  • Interface segregation

  • Dependency inversion

ซึ่งเดี๋ยวเราจะพูดถึงในวันถัดไปครับ แต่วันนี้เรามาดูวิธีการทำ Object Oriented Design กันก่อนดีกว่าครับ

การทำ Object Oriented Design

จริงๆ แล้วที่เราเรียนกันมาก็มีอยู่เยอะใช่ไหมครับ พวกการเขียน diagram เขียน document ต่างๆ แต่อันที่สำคัญจริงๆ ก็จะมีแค่ Use case แหละครับ เพราะมันบอกถึงการ interaction ของ user กับระบบ ซึ่งก็คือ requirement นั่นเอง พอเรารู้ละว่าเรามี input เป็น Use case นะ ต่อไปจะใช้วิธีไหนสร้าง output ดีล่ะ (output ที่คาดหวังจริงๆ มีแค่ class diagram) ผมเองชอบวิธีของ
Cunningham ครับ วิธีนี้เรียกว่า CRC Card

วิธี CRC Card ของ Cunningham

CRC นั้นย่อมาจาก classes, responsibilities, และ collaboration วิธีการทำก็เริ่มจากการเตรียมกระดาษครับ ขนาด 4x6 นิ้ว (ตัดไว้หลายๆ ใบ) แล้วก็แบ่งกระดาษแต่ละใบออกเป็น 3 ส่วน สำหรับ classes, responsibilities, และ collaboration นั่นแหละครับ เราเลยเรียกกระดาษใบนี้ว่า CRC Card

  • Class ส่วนนี้ใส่แค่ชื่อ Class เลยครับ อาจจะเล็กหน่อย

  • Responsibilities เขียนหน้านี่ของ Class นี้ลงไปครับ แต่ควรใส่แค่หน้าที่เดียว (หลายอันแต่เป็นกลุ่มเดียวกันได้) นะครับ

  • Collaborators เขียนชื่อคลาสอื่นที่สามารถคุยกับคลาสนี้ได้ ซึ่งส่วนนี้ควรจะเขียนให้น้อยที่สุดเท่าที่จะทำได้ (สรุปก็เขียนนิดเดียวทั้ง 3 ส่วน 555+)

เริ่มต้นก็ทำการ์ดขึ้นมาสองใบก่อนครับ ก็ใส่ชื่อคลาสที่เรานึงออกไปก่อน (ต้องมีคลาสหลักของโปรแกรมเป็นหนึ่งในนั้นนะครับ ไม่งั้นเดี๋ยวเริ่มไม่ถูก) หลังจากนั้นก็จะเริ่มใส่ Responsibilities และ Collaborators โดยมีกฎดังนี้ครับ

  1. ดูตาม use case ว่าคลาสแต่ละ action อะไรบ้าง และต้องคุยกับคลาสไหนบ้าง (อย่าเพิ่งใส่ อ่านข้อถัดไปก่อน)

  2. แต่ละคลาสสามารถคุยกับคลาสที่เป็น collaborators ของมันเองเท่านั้น ถ้ามีต้องการคุยกับคลาสอื่นนอกจากนั้น ให้คุยกับ collaborator ที่ติดต่อกับคลาสนั้นได้แทน แต่ถ้ายังไม่ได้ หรือดูแล้วไม่ make sense ก็ให้ใส่ชื่อคลาสที่ต้องการคุยด้วยในส่วน collaborators ซะ

  3. ห้ามเรียกคลาสอื่นเพื่อขอข้อมูลที่ถืออยู่ (พวก accessor ต่างๆ) แต่ให้เรียกคลาสอื่นเพื่อทำงานตามข้อมูลที่มันถืออยู่แทน โดยสามารถส่งข้อมูลเข้าไปยัง collaborators ได้ แต่ก็ขอให้น้อยที่สุด

  4. หากต้องการทำ Action ที่ไม่มีคลาสไหนทำได้เลย ให้เพิ่ม responsibility ให้คลาสที่เหมาะสม หรือหากไม่มีคลาสไหนเหมาะให้สร้างคลาสใหม่

  5. ถ้า CRC Card นั้นเต็มแล้ว (มีข้อมูลเยอะเกินไปแล้ว) แล้วดันมี responsibility ที่อยากใส่เพิ่ม ห้ามใส่นะครับ ต้องทำการสร้างคลาส และ CRC card ใหม่ เพื่อ handle responsibility นั้นแทน (เพื่อลดความซับซ้อนจึงต้องกำหนดขนาดกระดาษไว้) แล้วอาจจะ refactor ใหม่เพื่อจัดระเบียบอีกครั้ง

เมื่อทำเสร็จแล้ว (ครบทุก Use case) เราก็จะสามารถเขียน Class diagram ได้แล้วครับ ซึ่งพอได้ class diagram แล้ว ก็อยู่ที่ว่าเราจะเอาไปเขียน UML ตัวอื่นต่อมั้ย หรือว่าจะหยุดแค่นั้นแล้วไปเขียนโค้ดเลย

ปล. อย่าไปดูวิธีทำ CRC Card แบบที่เรียนกัะนมานะครับ มันดีเกินไปครับ เสียเวลาเปล่า

ปล. CRC card ใช้แค่ด้านหน้าอย่างเดียวพอ ถ้าอยากใช้ด้านหลังด้วย ก็หน้าคลาสนึง หลังอีกคลาสนึง เพื่อจำกัดพื้นที่ให้เล็กครับ

ปล. เรื่อง CRC แบบนี้ เอามาจาก javaworld อาจจะแปลไม่ตรงบ้าง แต่ผลที่ได้ก็ไม่ต่างกัน

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