ข้ามไปยังเนื้อหา

DDD คืออะไร และทำไมต้องใช้

Domain-Driven Design (DDD)Domain-Driven Design (DDD)แนวทางพัฒนาซอฟต์แวร์ที่เน้นสร้าง domain model ซึ่งเข้าใจกฎและกระบวนการของธุรกิจอย่างลึกซึ้ง แล้วเขียนลงในโค้ดจริง บัญญัติโดย Eric Evans (2003) แบ่งเป็น Strategic และ Tactical DesignStrategic Design คือแนวทางการพัฒนาซอฟต์แวร์ที่ให้ความสำคัญกับการ “สร้างแบบจำลองของธุรกิจ” (Domain ModelDomain ModelModel ของ Domain ที่ฝังกฎและกระบวนการทางธุรกิจไว้ในโค้ดจริง หัวใจของ DDD คือการพัฒนา domain model ที่ “เข้าใจธุรกิจอย่างลึกซึ้ง”Strategic Design) ที่เข้าใจกฎและกระบวนการของ DomainDomainขอบเขตของปัญหาหรือธุรกิจที่ซอฟต์แวร์ของเราเข้าไปแก้ไข เช่น การขนส่งสินค้า การธนาคาร อีคอมเมิร์ซ — คือ “โลกของผู้ใช้” ที่โปรแกรมต้องเข้าใจStrategic Design อย่างลึกซึ้ง แล้วเขียนแบบจำลองนั้นลงไปในโค้ดจริง ชื่อนี้มาจากหนังสือปี 2003 ของ Eric Evans

flowchart LR
  D["โดเมน (ธุรกิจจริง)"] --> M["Domain Model"]
  M --> C["โค้ดที่รันได้"]
  C -->|ค้นพบความเข้าใจใหม่| M
  M -->|ปรับ Ubiquitous Language| D

Martin Fowler สรุปไว้ว่า DDD เหมาะอย่างยิ่งกับ DomainDomainขอบเขตของปัญหาหรือธุรกิจที่ซอฟต์แวร์ของเราเข้าไปแก้ไข เช่น การขนส่งสินค้า การธนาคาร อีคอมเมิร์ซ — คือ “โลกของผู้ใช้” ที่โปรแกรมต้องเข้าใจStrategic Design ที่ “ซับซ้อน” ซึ่งมีตรรกะยุ่งเหยิงจำนวนมากที่ต้องจัดระเบียบ หัวใจไม่ได้อยู่ที่เครื่องมือหรือเฟรมเวิร์ก แต่อยู่ที่ “วิธีคิด” ในการมองธุรกิจและสื่อสารกับผู้เชี่ยวชาญธุรกิจ

ในการพัฒนาซอฟต์แวร์สำหรับ domain ที่ซับซ้อน เราต้องสร้างภาษากลางที่ฝังคำศัพท์ของธุรกิจลงไปในระบบที่เราสร้าง

— ใจความจาก Eric Evans / Martin Fowler

ใน DDD Reference (2015) Evans สรุป DDD เป็นการพัฒนาซอฟต์แวร์ที่ซับซ้อนโดย:

  1. โฟกัสที่ [[Core Domain]] — ทุ่มเทกับส่วนที่สร้างคุณค่าและความได้เปรียบมากที่สุด
  2. สำรวจ [[Model]] ร่วมกัน — ระหว่างผู้เชี่ยวชาญธุรกิจกับนักพัฒนา อย่างสร้างสรรค์
  3. พูด [[Ubiquitous Language]] ภายใน [[Bounded Context]] ที่ชัดเจน — ใช้ภาษาเดียวกันในขอบเขตที่กำหนด
DDD แบ่งเป็นสองครึ่ง

Strategic Design (เชิงกลยุทธ์): มองภาพใหญ่ — Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงในโค้ดStrategic Design, Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design, SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain อีคอมเมิร์ซ แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design, Context MappingContext Mappingกิจกรรมการระบุ Bounded Context และนิยามความสัมพันธ์ระหว่างกัน (เช่น Partnership, Shared Kernel, ACL) เพื่อจัดการการเชื่อมต่อระหว่างทีม/ระบบStrategic Design เป็นส่วนที่ Fowler ยกย่องว่าเป็น “คุณูปการที่สำคัญที่สุด” ของ Evans และใช้ได้กับทุกภาษา/ทุกกระบวนทัศน์

Tactical Design (เชิงปฏิบัติ): building blocks ระดับโค้ด — EntityEntityอ็อบเจ็กต์ที่มี “ตัวตน” (identity) ต่อเนื่องตามเวลา แม้ค่าภายในเปลี่ยน ก็ยังเป็นสิ่งเดิม เช่น ลูกค้า, คำสั่งซื้อ — แยกแยะด้วย id ไม่ใช่ด้วยค่าTactical Design, Value ObjectValue Objectอ็อบเจ็กต์ที่สำคัญที่ “ค่า” ของมัน ไม่มีตัวตนเฉพาะ สองตัวที่ค่าเท่ากันถือว่าเท่ากัน ควรเป็น immutable (เปลี่ยนค่าไม่ได้) เช่น เงิน, วันที่, พิกัดTactical Design, AggregateAggregateกลุ่มของ Entity และ Value Object ที่ถูกมองเป็นหนึ่งหน่วยเดียวเพื่อรักษาความถูกต้องของข้อมูล มีขอบเขตชัดเจน และเป็นหน่วยของ transactionTactical Design, RepositoryRepositoryตัวที่ทำให้เราเข้าถึง Aggregate ราวกับเป็นคอลเลกชันในหน่วยความจำ ซ่อนรายละเอียดฐานข้อมูล มีหนึ่ง repository ต่อหนึ่ง Aggregate RootTactical Design, Domain EventDomain Eventสิ่งที่ “เกิดขึ้นแล้ว” ใน domain ซึ่งส่วนอื่นสนใจ แทนด้วยอ็อบเจ็กต์ที่เปลี่ยนแปลงไม่ได้ ตั้งชื่อเป็นอดีต เช่น CargoWasRouted ใช้สื่อสารข้าม AggregateTactical Design ฯลฯ เป็นเครื่องมือสร้าง domain model ที่ “รวยพฤติกรรม”

ตัวอย่างที่จะเดินไปด้วยกันทั้งคอร์ส: การขนส่งสินค้า

หัวข้อที่มีชื่อว่า “ตัวอย่างที่จะเดินไปด้วยกันทั้งคอร์ส: การขนส่งสินค้า”

ตลอดคอร์สนี้เราจะใช้ตัวอย่างเดียวกับในหนังสือของ Evans คือ ระบบขนส่งตู้คอนเทนเนอร์ (Cargo Shipping) ค่อย ๆ สร้างขึ้นทีละชั้นในแต่ละบท ควบคู่กับตัวอย่างเสริมที่คุ้นเคยกว่าอย่าง อีคอมเมิร์ซ เพื่อให้เห็นภาพชัด

🚢 Cargo Shipping — โจทย์ตั้งต้น

บริษัทขนส่งต้องการระบบที่: รับ “จอง” การขนส่งสินค้าจากต้นทางไปปลายทางภายในกำหนด, วาง “แผนเดินทาง” ที่ผ่านท่าเรือและเรือหลายลำ, และ “ติดตามสถานะ” ของสินค้าระหว่างทาง ฟังดูเหมือน CRUD แต่กฎทางธุรกิจซับซ้อนกว่าที่คิดมาก — นี่คือสนามที่ DDD เปล่งประกาย

🛒 ลองคิดคู่ขนาน — อีคอมเมิร์ซ

ในโลกอีคอมเมิร์ซ “คำสั่งซื้อ (Order)” ก็มีกฎทำนองเดียวกัน เช่น ยอดรวมต้องตรงกับรายการสินค้า, เปลี่ยนสถานะได้ตามลำดับที่ถูกต้องเท่านั้น เราจะเทียบเคียงสองโลกนี้ไปเรื่อย ๆ


[quiz: เช็กความเข้าใจ — Stage 0 — coming soon]