Model-Driven Design
ในบทก่อน เราได้กลั่น problem domain จนเห็น Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design และเข้าใจว่าควรทุ่มแรงตรงไหน ตอนนี้ถึงเวลาก้าวเข้าสู่ solution space — แต่มีกับดักรออยู่ กระบวนการพัฒนาแบบดั้งเดิมมักแยก “model ที่ใช้คุยกับธุรกิจ” (analysis model) ออกจาก “model ที่อยู่ใน code จริง” (code model) ผลคือสิ่งที่ build ออกมากลับเบนห่างจากพิมพ์เขียวที่วางไว้แต่แรก
Model-Driven Design คือคำตอบของ DDD ต่อปัญหานี้ — มันคือ กระบวนการผูก analysis model เข้ากับ code model ให้เป็น model เดียวกัน โดยใช้ Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงใน codeStrategic Design เป็นกาวยึดทั้งสองให้ sync กันตลอดอายุของระบบ บทนี้จะพาไปสำรวจว่า domain model คืออะไร ทำไม UL จึงเป็นหัวใจ และเราจะสร้าง domain model ที่ได้ผลจริงได้อย่างไร
Domain Model คืออะไร?
หัวข้อที่มีชื่อว่า “Domain Model คืออะไร?”Domain ModelDomain ModelModel ของ Domain ที่ฝังกฎและกระบวนการทางธุรกิจไว้ใน code จริง หัวใจของ DDD คือการพัฒนา domain model ที่ “เข้าใจธุรกิจอย่างลึกซึ้ง”Strategic Design อยู่ตรงศูนย์กลางของ DDD มันเกิดขึ้นครั้งแรกในรูปของ analysis model จากการที่ทีมพัฒนาและผู้เชี่ยวชาญธุรกิจร่วมกัน บดเคี้ยวความรู้Knowledge Crunchingการบดเคี้ยวความรู้ — ศิลปะการกลั่นข้อมูลที่เกี่ยวข้องออกจาก problem domain ร่วมกับ domain expert เพื่อสร้าง model ที่มีประโยชน์ต่อ business use caseProcess model นี้ไม่ใช่ภาพสะท้อนความจริงทั้งหมด — มันเป็น “มุมมอง” ของ problem domain ที่ออกแบบมาเพื่อตอบ business use case เท่านั้น
คุณค่าของ domain model ไม่ได้อยู่ที่มันเหมือนชีวิตจริงแค่ไหน แต่อยู่ที่ความสามารถในการถ่ายทอดตรรกะและนโยบายอันซับซ้อนของธุรกิจออกมาเพื่อแก้ปัญหา และมันต้อง วิวัฒน์ไปพร้อมกับธุรกิจอยู่เสมอ จึงจะคงคุณค่านั้นเอาไว้ได้

ลองดูรูปที่ 4-1: หน้าจอตะกร้ามีช่องกรอกคูปอง use case คือ “ใส่คูปองเพื่อรับส่วนลด”
- application layer เป็น client ของ domain layer — มันแทน use case ของระบบ รับคำสั่งจาก UI แล้วเรียก domain
- domain model คือที่ที่ตรรกะของคูปองอยู่จริง: คูปองนี้ใช้ได้ไหม คำนวณส่วนลดของตะกร้าอย่างไร
ตรรกะส่วนลดไม่ควรกระจัดกระจายอยู่ใน UI หรือ controller — มันต้องอยู่ใน domain model
Domain กับ Domain Model ต่างกันอย่างไร
หัวข้อที่มีชื่อว่า “Domain กับ Domain Model ต่างกันอย่างไร”นี่คือความแตกต่างที่คนสับสนบ่อย:
- DomainDomainขอบเขตของปัญหาหรือธุรกิจที่ซอฟต์แวร์ของเราเข้าไปแก้ไข เช่น การขนส่งสินค้า การธนาคาร e-commerce — คือ “โลกของผู้ใช้” ที่โปรแกรมต้องเข้าใจStrategic Design คือ ความจริง — ขอบเขตของปัญหาที่เรากำลังทำงานอยู่ มันมีอยู่ก่อนเราจะเขียน code
- Domain ModelDomain ModelModel ของ Domain ที่ฝังกฎและกระบวนการทางธุรกิจไว้ใน code จริง หัวใจของ DDD คือการพัฒนา domain model ที่ “เข้าใจธุรกิจอย่างลึกซึ้ง”Strategic Design คือ abstraction ของ problem domain ที่แสดงออกเป็น code — เป็น “มุมมอง” ไม่ใช่ความจริง

domain model มีอยู่เพื่อช่วยเราแก้ปัญหาเท่านั้น มันจึงต้อง ชัดเจนและปลอดจากความซับซ้อนทางเทคนิค เพื่อให้ทั้งฝั่งธุรกิจและฝั่งพัฒนาออกแบบมันร่วมกันได้
Analysis Model, Code Model และการผูกกันด้วยภาษา
หัวข้อที่มีชื่อว่า “Analysis Model, Code Model และการผูกกันด้วยภาษา”Analysis ModelAnalysis Modelmodel เชิงวิเคราะห์ — ภาพการออกแบบเชิงตรรกะและโครงสร้างของซอฟต์แวร์ที่คนไม่ใช่สายเทคนิคก็เข้าใจได้ (เช่น ภาพร่างหรือ UML) ใน DDD จะถูกผูกเข้ากับ code model ผ่าน Ubiquitous LanguageStrategic Design (บางทีเรียก business model) คือกลุ่มของ artifact ที่อธิบาย model ของระบบ — ตั้งแต่ภาพร่างหลังซองจดหมายไปจนถึง UML แบบไม่เป็นทางการ มันมีอยู่เพื่อช่วยให้ทั้งสองฝ่ายเข้าใจ problem domain ตรงกัน ไม่ใช่พิมพ์เขียวสำหรับ implement
DDD ไม่ได้บอกให้ทิ้ง analysis model — ตรงกันข้าม มันมีคุณค่ามาก แต่ DDD เน้นให้ Code ModelCode Modelmodel ใน code — การแสดงออกของ domain model ใน code จริง DDD ถือว่า code model คือ “การแสดงออกหลัก” (primary expression) ของ domain model ไม่ใช่ไดอะแกรมหรือเอกสารStrategic Design (ตัว implementation จริง) อยู่ใน synergy ใกล้ชิดกับ analysis model โดยให้ทั้งคู่อธิบายด้วย UL ร่วมกัน

code model คือ การแสดงออกหลัก (primary expression) ของ domain model หาก implement แล้วพบว่าตรรกะไม่ลงตัว นั่นคือสัญญาณว่า analysis model มีจุดบกพร่อง — จงกลับไปคุยกับ domain expert แล้วแก้ทั้ง2 model ให้ตรงกันเสมอ “the code is the model; the code is the truth”
Model-Driven Design กับปัญหาของการออกแบบล่วงหน้า
หัวข้อที่มีชื่อว่า “Model-Driven Design กับปัญหาของการออกแบบล่วงหน้า”Model-Driven Design คือกระบวนการ พิสูจน์ model ด้วยการลงมือทำจริง — เพราะการมี model สวยหรูที่ implement ไม่ได้นั้นไร้ความหมาย มันต่างจาก DDD ตรงที่ MDD โฟกัสที่ implementation และข้อจำกัดทางเทคนิคที่อาจบังคับให้ต้องแก้ model ส่วน DDD โฟกัสที่ภาษา การร่วมมือ และความรู้ของ domain — ทั้งสองเสริมกัน
ระหว่างทาง คุณจะเจอ specification บ่อยๆ มันคือ object ที่แทนกฎธุรกิจหนึ่งข้อ ซึ่งบางส่วนของ domain model ต้องทำให้เป็นจริง และยังใช้เป็นเงื่อนไขในการ query ได้ด้วย เช่น “หาทุก object ที่ตรงตาม specification นี้”
ทำไม upfront design ถึงพัง
หัวข้อที่มีชื่อว่า “ทำไม upfront design ถึงพัง”ในอดีต การเก็บ requirement ถูกมองเป็นกิจกรรมที่ทำเสร็จก่อนเริ่มเขียน code นานๆ: business expert คุยกับ business analyst → analyst คุยกับ architect → architect ปั้น analysis model แล้วส่งต่อให้ developer พร้อม wireframe ไปสร้างระบบ
ปัญหาคือเมื่อ developer เริ่ม implement พวกเขามักเจอช่องว่างระหว่าง artifact ระดับสูงกับความจริงของการสร้างระบบ — และมักไม่มี feedback loop ให้กลับไปคุยกับธุรกิจ ผลคือ code ค่อยๆ เบนออกจาก analysis model จนคำศัพท์และแนวคิดสำคัญของ domain หล่นหาย

ปัญหาจะเผยตัวตอนที่การเพิ่ม feature ในอนาคตเริ่มทำได้ยาก เพราะธุรกิจกับ developer ต่างถือ “model คนละตัว” อยู่ในหัว code จึงขาด synergy กับกระบวนการธุรกิจ และไม่อุดมด้วยความรู้ของ domain
ถ้าคุณเป็นคนปั้น analysis model หรือ code model คุณต้องลงมือเขียน code ด้วย DDD เปิดที่ทางให้ architect แต่ architect คนนั้น ต้องเป็นคนที่ code เป็น — ไม่เช่นนั้น analysis model จะหลุดจากความจริงของ implementation
Team Modeling — ออกแบบกันทั้งทีม
หัวข้อที่มีชื่อว่า “Team Modeling — ออกแบบกันทั้งทีม”DDD เสนอวิธีที่ร่วมมือกันมากกว่า: เน้นให้ ทั้งทีม — developer, tester, business analyst, architect และ business expert — ทำงานเป็นหนึ่งเดียวใน knowledge-crunching sessions
หัวใจของการ model ร่วมกันคือ feedback ที่ไหลเวียนอย่างต่อเนื่อง จาก business expert ซึ่งนำไปสู่การค้นพบแนวคิดสำคัญ และช่วยให้ทีมเห็นชัดว่าอะไร “ไม่สำคัญ” แล้วตัดออกจาก model ได้ จุด breakthrough มักมาในรูปของ abstraction เรียบง่ายที่ทำให้แนวคิดอันซับซ้อนกระจ่างขึ้นในพริบตา

ในระบบขนส่งสินค้า ทีมและ domain expert พูดคุยกันผ่านภาพและตัวอย่างจริง จนพบว่า “ความต้องการของลูกค้า” (ต้นทาง ปลายทาง กำหนดเวลาถึง) เป็นแนวคิดที่ควรมีชื่อเรียกชัดเจน — จึงเกิดเป็น Route SpecificationRoute SpecificationValue Object ที่ระบุ “ความต้องการของลูกค้า”: ต้นทาง ปลายทาง และกำหนดเวลาถึง — มี method isSatisfiedBy() ตรวจว่าแผนเดินทางตรงตามนี้หรือไม่Tactical Design ขึ้นใน UL
แนวคิดนี้ไม่ได้โผล่มาจาก wireframe แต่ ผุดขึ้นระหว่างการ model ร่วมกัน แล้วถูกป้อนกลับให้ domain expert ยืนยัน นี่คือ team modeling ในการทำงานจริง
ใช้ Ubiquitous Language ผูก2 model เข้าด้วยกัน
หัวข้อที่มีชื่อว่า “ใช้ Ubiquitous Language ผูก2 model เข้าด้วยกัน”คุณค่าที่แท้จริงของการทำตามปรัชญา DDD อยู่ที่การร่วมมือกันระหว่าง developer และ domain expert เพื่อเข้าใจ domain ให้ลึกขึ้น — code เป็นเพียง artifact ของกระบวนการนั้น และสิ่งที่จะ อยู่ยงคงกระพันแม้ code จะถูกเขียนใหม่ คือ Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงใน codeStrategic Design
ภาษาจะอยู่ยืนยาวกว่าซอฟต์แวร์ของคุณ — มันนิยามชัดๆ ว่าธุรกิจทำอะไร เผยให้เห็น insight ที่ลึกขึ้นของกระบวนการ และทำให้การสื่อสารทางธุรกิจดีขึ้น
ทุก domain มี “ภาษาลับ” ของมัน — ช่างไม้ เทรดเดอร์การเงิน ทหาร หรือแม้แต่ร้านขายผ้าม่าน (pleated, hang length, interlining) ล้วนมีคำเฉพาะที่ทำให้คุยเรื่องซับซ้อนได้กระชับ ทีมพัฒนาต้องเข้าใจและร่วมสร้างภาษานี้ แล้วใช้มัน ตั้งชื่อ class, method และ namespace ใน code ด้วย
ราคาของการแปลภาษา
หัวข้อที่มีชื่อว่า “ราคาของการแปลภาษา”ถ้า developer ไม่ใช้ภาษาของธุรกิจ พวกเขาจะสร้างภาษาและ abstraction ของตัวเองขึ้นมาแทน ผลคือต้องคอย “แปล” จากแนวคิด domain ไปเป็นแนวคิดเชิงเทคนิคอยู่ตลอด — ซึ่งทั้งช้า สิ้นเปลือง และผิดพลาดง่าย และทุกครั้งที่แปล insight สำคัญของ domain ก็มีโอกาสหล่นหายไป โดยเฉพาะเมื่อคนเขียน code กับ domain expert ถือ model กันคนละตัว
เมื่อ developer คิดด้วย “technical abstraction และ design pattern” ขณะที่ domain expert คิดด้วย “กระบวนการธุรกิจ” บทสนทนาย่อมเดินสวนทางกัน และทุกครั้งที่ทีมแปลตรรกะซับซ้อนคลาดเคลื่อน bug ก็แทรกตัวเข้า code ได้ทันที — ทางออกคือ developer ต้องคิดด้วยคำของ domain ไม่ใช่คำทางเทคนิค
ร่วมกันสร้าง Ubiquitous Language
หัวข้อที่มีชื่อว่า “ร่วมกันสร้าง Ubiquitous Language”ภาษาที่ธุรกิจใช้คือ “วัตถุดิบ” อย่างหนึ่งของ UL แต่ตอนสร้าง model และ implement ลง code คุณอาจต้อง สร้างแนวคิดและคำใหม่ ด้วย ทีมต้องไม่เพียงเรียนคำที่ธุรกิจพูดออกมาชัดๆ แต่ต้องช่วยกัน ตั้งชื่อให้แนวคิดที่ซ่อนอยู่ (implicit) ซึ่งยังไม่มีคำเรียก แล้วนำเข้า UL ร่วมกัน
เจียระไนภาษาจากตัวอย่างที่เป็นรูปธรรม
หัวข้อที่มีชื่อว่า “เจียระไนภาษาจากตัวอย่างที่เป็นรูปธรรม”วิธีที่ดีคือหยิบตัวอย่างกระบวนการธุรกิจจริงมาพูดคุยกัน โดยต้องเผย เจตนาของกระบวนการธุรกิจ ไม่ใช่วิธี implement ลองดูคำอธิบายแบบที่ business user มักพูด:
ลูกค้าที่ไม่ได้รับของจะ login เข้าบัญชี กดปุ่ม “ฉันยังไม่ได้รับสินค้า” ถ้าระบบ flag ไว้แล้วว่าเคยได้ของฟรี ก็ขออีกไม่ได้จนกว่าจะคุยกับ customer service ไม่งั้นเราจะส่งของฟรีให้แล้วอัปเดต database…
สังเกตว่าประโยคนี้เต็มไปด้วย “วิธี implement” (login, กดปุ่ม, อัปเดต database, flag) ซึ่งไม่ได้เผย insight ใดๆ เกี่ยวกับ domain เลย หากทีมละเลย domain แล้ว implement ตามคำบอกนั้นตรงๆ สิ่งที่ได้ก็คือ model ที่อ่อนแอและไร้ความหมายเชิงธุรกิจ
ลองเขียนใหม่ด้วยภาษาของ domain ที่โฟกัสที่กระบวนการธุรกิจ:
ถ้าคุณไม่ได้รับคำสั่งซื้อ คุณส่ง “undelivered order notification” ได้ ถ้าเป็นการเคลมครั้งแรก ระบบจะสร้าง “replacement order” ให้ ถ้าเคยเคลมมาก่อน จะเปิด “claim case” มอบหมายให้เจ้าหน้าที่สอบสวน และทุกกรณีจะเปิด “lost mail compensation case” ส่งให้บริษัทขนส่ง
คำอธิบายใหม่นี้เผยแนวคิดสำคัญที่หายไปก่อนหน้า — UndeliveredOrderNotification, ReplacementOrder, ClaimCase, LostMailCompensationCase ล้วนเป็นคำที่ควรเข้า UL และน่าสังเกตว่ามันไม่มีคำว่า “customer” หรือ “ปุ่ม” หรือ “database” เลย
domain expert ส่วนใหญ่ไม่คุ้นกับศัพท์เทคนิค เมื่อพวกเขาพยายามช่วยด้วยการกระโดดไปที่ implementation ให้ค่อยๆ ชวนกลับมาโฟกัสที่ what และ why ของระบบ ส่วน how นั้นปล่อยให้เป็นหน้าที่ของทีมพัฒนา
แนวปฏิบัติในการเจียระไนภาษา
หัวข้อที่มีชื่อว่า “แนวปฏิบัติในการเจียระไนภาษา”- รักษาความสอดคล้องทางภาษา — ถ้าใช้คำใน code ที่ domain expert ไม่เคยพูด ต้องไปเช็ก อาจเป็นแนวคิดใหม่ที่ต้องเพิ่มเข้า UL หรืออาจเป็นเพราะคุณเข้าใจผิด
- ทำ glossary ของคำใน domain ร่วมกับ domain expert
- หนึ่งแนวคิด หนึ่งคำ — อย่าให้มีสองคำเรียกสิ่งเดียวกัน
- เลี่ยงคำกว้างเกินไป อย่าง policy, service, manager — ชื่อที่ยาวขึ้นแต่สื่อความชัดเจนย่อมดีกว่า
- อย่าใช้ชื่อ design pattern ใน model —
decoratorหรือfactoryมีความหมายต่อ business user ไหม? GoF pattern อาจทำให้สับสน - UL ต้องปรากฏทุกที่ ตั้งแต่ namespace ถึง class ถึงชื่อ method และตั้งชื่อ exception ด้วยคำของ UL
- UL จะวิวัฒน์ เมื่อคุณเข้าใจ domain ลึกขึ้น — refactor code ให้สะท้อนชื่อที่เผยเจตนามากขึ้น ถ้าเจอกลุ่มตรรกะซับซ้อนก่อตัว ลองคุยกับ domain expert แล้วแยกออกเป็น specification หรือ policy class
ความสอดคล้องทางภาษาคือเครื่องวัดว่า model ใช้ได้จริงหรือไม่ ลองฟังบทสนทนาเกี่ยวกับ model แล้วจับแนวคิดที่ “ไม่ลงตัว” หรือพูดออกมาแล้วสะดุดลิ้น — “query ถูกส่งไป cache แล้ว match user ด้วย regex เพื่อดูว่าได้ส่วนลดไหม” business user เข้าใจประโยคนี้หรือไม่? ถ้าไม่ ก็แปลว่า model ยังไม่ได้พูดภาษาของ domain
วิธีสร้าง Domain Model ที่ได้ผล
หัวข้อที่มีชื่อว่า “วิธีสร้าง Domain Model ที่ได้ผล”domain model ที่รวยพฤติกรรมRich Domain Modelmodel domain ที่ “รวยพฤติกรรม” — object ที่เก็บทั้งข้อมูลและ business logic ไว้ด้วยกัน เป็นคู่ตรงข้ามของ Anemic Domain Model (ที่มีแต่ getter/setter แล้วผลัก logic ไปไว้ที่อื่น) tactical patterns ของ DDD จะคุ้มค่าก็ต่อเมื่อ model “รวย” พอเช่นนี้Tactical Design สร้างขึ้นเพื่อแก้ปัญหายากๆ ดังนั้นให้โฟกัสที่ส่วนสำคัญต่อธุรกิจ — มองข้ามส่วนที่เป็นแค่การจัดการข้อมูล (CRUD) แล้วไปจับ “ส่วนที่ยาก” ใน core domain ที่ธุรกิจให้ความสำคัญจริงๆ ซึ่งมักเป็นจุดที่สร้างรายได้หรือลดต้นทุน
อย่าให้ “ความจริง” มาขวาง model ที่ดี
หัวข้อที่มีชื่อว่า “อย่าให้ “ความจริง” มาขวาง model ที่ดี”ความเข้าใจผิดที่พบบ่อยคือ domain model ต้องเหมือนชีวิตจริง — ไม่จริง อย่าพยายามจำลองชีวิตจริง แต่จง model abstraction ที่มีประโยชน์ ภายใน problem domain มองหาความเหมือนและความแตกต่าง พิจารณาว่าส่วนไหนมีแนวโน้มจะเปลี่ยนแปลงและซับซ้อน แล้วใช้ข้อมูลนั้นสร้าง model — วิธีนี้ได้ผลกว่าการไล่ล่า “คำนาม/คำกริยา” จากโลกจริงมาแปะลง model มาก
แผนที่รถไฟใต้ดินลอนดอนเป็นตัวอย่างคลาสสิก: มันถูกออกแบบมาเพื่อแก้ปัญหาหนึ่ง — มันไม่สะท้อนระยะทางจริงระหว่างสถานี และคำนวณระยะทางบนดินไม่ได้ แต่มัน มีประโยชน์มากสำหรับการเดินทางใต้ดิน เพราะมันเรียบง่ายและได้ผลใน context ที่มันถูกออกแบบมา
เพราะ domain model ไม่ได้มุ่งจำลองชีวิตจริง เราจึงตัดสินมันว่า “ถูก/ผิด” ไม่ได้ — วัดได้เพียงว่ามัน มีประโยชน์หรือไม่ ต่อปัญหาที่มันถูกสร้างขึ้นมาแก้
หลักการสำคัญในการ model
หัวข้อที่มีชื่อว่า “หลักการสำคัญในการ model”- model เฉพาะสิ่งที่เกี่ยวข้อง — ธุรกิจใหญ่และซับซ้อน อย่าพยายามยัดทุกอย่างลง model เดียว ถ้าระบบใหญ่ ให้แบ่งเป็นส่วนย่อยที่จัดการได้
- อย่า model ความสัมพันธ์จริง — ให้นิยาม association ในแง่ของ InvariantInvariantกฎทางธุรกิจที่ “ต้องเป็นจริงเสมอ” ภายใน Aggregate เช่น ยอดรวมคำสั่งซื้อต้องเท่ากับผลรวมของรายการสินค้า — ต้องถูกต้องภายใน transaction เดียวTactical Design และกฎของระบบแทน (ในชีวิตจริงลูกค้ามีทั้ง credit history และอีเมล แต่จะมีกฎไหนบังคับว่า “ต้อง credit ดีและอีเมลขึ้นต้นด้วย A ถึงซื้อของได้”?)
- model มีประโยชน์เพียงชั่วคราว — model หนึ่งๆ ใช้ได้แค่กับ iteration และชุด use case ช่วงหนึ่งเท่านั้น อย่าหลงรัก model ที่สวยงาม จงพร้อม “โยนทิ้งแล้วเริ่มใหม่” (throw away) เมื่อมันไม่เกี่ยวข้องอีกต่อไป
- จำกัด abstraction — abstraction มีต้นทุน (ก่อให้เกิด dependency และ coupling) จึงควรสร้างเฉพาะเมื่อแนวคิดนั้นมี “ความแตกต่าง (variation)” จริงๆ เท่านั้น และพึงเลือกความชัดเจนไว้ก่อนการเลี่ยง code ซ้ำ (DRY)
- abstract ที่พฤติกรรม ไม่ใช่ implementation — interface ควรแทนแนวคิดของ domain เช่น
IShippingNoteGenerator(มี variation เป็น domestic/international) แต่ courier gateway เป็นเรื่อง infrastructure ไม่ใช่พฤติกรรม domain — เก็บมันให้เป็น concrete นอก model - implement ลง code เร็วและบ่อย — ทดสอบ design กับ domain scenario เพื่อเจอข้อจำกัดทางเทคนิคที่อาจบังคับให้แก้ model
- อย่าหยุดที่ไอเดียดีอันแรก — หยุด model ต่อเมื่อ “หมดไอเดีย” ไม่ใช่ตอนได้ไอเดียดีอันแรก ลองแก้ปัญหาด้วย model ที่ต่างไปโดยสิ้นเชิง
// ✅ abstraction ที่แทน "แนวคิด" ของ domain ที่มี variation จริงpublic interface IShippingNoteGenerator { ShippingNote Generate(Order order);}
public class DomesticShippingNoteGenerator : IShippingNoteGenerator { /* ... */ }public class InternationalShippingNoteGenerator : IShippingNoteGenerator { /* เอกสารต่างกัน */ }
// ❌ อย่า abstract courier gateway — มันเป็น infrastructure ไม่ใช่พฤติกรรม domain// public interface ICourierGateway { ... } // เก็บไว้นอก domain model เป็น concreteควรใช้ Model-Driven Design เมื่อไร
หัวข้อที่มีชื่อว่า “ควรใช้ Model-Driven Design เมื่อไร”ปัญหาง่ายๆ ไม่ต้องการคำตอบซับซ้อน — คุณไม่จำเป็นต้องสร้าง UL ให้ทั้ง app จงทุ่มแรงร่วมกับ domain expert ไปที่ core domain ที่ซับซ้อนและสำคัญ ส่วน genericGeneric Subdomainปัญหาที่แก้กันมาแล้วทั่วไป เช่น ระบบ login บัญชี การแจ้งเตือน — ควรใช้ของสำเร็จรูปหรือ library แทนการเขียนเองStrategic Design / supporting subdomainSupporting Subdomainส่วนที่จำเป็นและเฉพาะกับธุรกิจเรา แต่ไม่ใช่จุดที่สร้างความได้เปรียบ ไม่มีของสำเร็จรูปที่พอดี จึงต้องทำเอง แต่ลงทุนน้อยกว่า coreStrategic Design ที่ไม่มี domain logic นั้นไม่ควรเสียแรง เพราะจะบั่นทอนความร่วมมือของ domain expert จนเขาไม่อยากช่วยในส่วนที่ยากจริงๆ
ในระบบขนส่ง การ routing และ tracking สินค้าคือ core domain ที่ควรลงทุนสร้าง rich model และ UL อย่างเต็มที่ (Route SpecificationRoute SpecificationValue Object ที่ระบุ “ความต้องการของลูกค้า”: ต้นทาง ปลายทาง และกำหนดเวลาถึง — มี method isSatisfiedBy() ตรวจว่าแผนเดินทางตรงตามนี้หรือไม่Tactical Design, ItineraryItineraryValue Object ที่เป็น “แผนการเดินทางจริง” ของ Cargo ประกอบด้วยลำดับของ Leg (ช่วงการขนส่งแต่ละช่วง)Tactical Design, Handling EventHandling Eventการบันทึกการจัดการสินค้าจริง (LOAD, UNLOAD, RECEIVE, CLAIM) เป็น Aggregate “แยกต่างหาก” จาก Cargo เพราะมีปริมาณมากและต้องประมวลผลแบบ asyncTactical Design)
แต่ระบบ login, การส่งอีเมลแจ้งเตือน, หรือรายงาน CRUD ธรรมดาๆ เป็น generic/supporting — ใช้ของสำเร็จรูปหรือเขียนแบบเรียบง่ายก็พอ ไม่ต้องเปลือง knowledge-crunching session ไปกับมัน
ถามตัวเองเสมอว่า: “ฉันอยู่ใน core subdomain หรือเปล่า? ปัญหานี้ต้องใช้ rich domain ไหม? ธุรกิจให้ความสำคัญกับส่วนนี้จริงไหม? หรือเขาเพียงอยากให้มันทำงานได้?” และถ้าเจอ edge case ที่ยุ่งยากในส่วนที่ ไม่ใช่ core — ให้พิจารณาทำเป็น กระบวนการแบบ manual เพราะมนุษย์รับมือ edge case ได้ดี และช่วยให้คุณสงวนแรงไว้ทุ่มกับ core domain
core domain นั้นเล็ก — จงโฟกัสพลังทั้งหมดไปที่มัน อย่าพยายามสร้างภาษาที่ rich ให้ทั้ง domain เพราะ supporting/generic subdomain ส่วนใหญ่ไม่ได้ประโยชน์จาก UL การเกลี่ยแรงบางๆ ไปทั่วทุกที่มีแต่จะสูญเปล่า
Model-Driven Design = ผูก Analysis ModelAnalysis Modelmodel เชิงวิเคราะห์ — ภาพการออกแบบเชิงตรรกะและโครงสร้างของซอฟต์แวร์ที่คนไม่ใช่สายเทคนิคก็เข้าใจได้ (เช่น ภาพร่างหรือ UML) ใน DDD จะถูกผูกเข้ากับ code model ผ่าน Ubiquitous LanguageStrategic Design เข้ากับ Code ModelCode Modelmodel ใน code — การแสดงออกของ domain model ใน code จริง DDD ถือว่า code model คือ “การแสดงออกหลัก” (primary expression) ของ domain model ไม่ใช่ไดอะแกรมหรือเอกสารStrategic Design ให้เป็น model เดียวกัน โดยมี Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงใน codeStrategic Design เป็นกาวยึด — “code คือ model, code คือความจริง” domain model คือ abstraction ที่มีประโยชน์ ไม่ใช่ภาพจำลองชีวิตจริง และจะคุ้มค่าที่จะลงแรงทำ MDD + UL ก็ต่อเมื่อทำ เฉพาะกับ core domain เท่านั้น
เจาะลึกแนวคิดในบทนี้ต่อได้ที่คลังอ้างอิง DevIQ:
- Domain Model — นิยามและตัวอย่างของ domain model ในฐานะ abstraction ที่มีประโยชน์ ไม่ใช่ภาพจำลองชีวิตจริง ตรงกับใจความหลักของบทนี้
- Ubiquitous Language — ขยายความว่าทำไม UL คือกาวที่ผูก analysis model กับ code model เข้าด้วยกัน และจะสร้างมันร่วมกับทีมอย่างไร
- Specification — รายละเอียดของ pattern ที่บทนี้แนะนำไว้สั้นๆ สำหรับห่อกฎธุรกิจให้เป็น object ที่ตรวจสอบและ query ได้
- Anemic Domain Model — ภาพตรงข้ามของ rich domain model ที่บทนี้ตั้งเป้าหมายไว้ ช่วยให้เห็นชัดว่า model แบบไหนที่ควรหลีกเลี่ยง
- Subdomain — อธิบายความต่างระหว่าง core กับ generic/supporting subdomain ที่บทนี้ใช้ตัดสินใจว่าควรทุ่มแรงทำ MDD + UL ตรงไหน
เช็กความเข้าใจ — บทที่ 4
ข้อ 1 / 4Model-Driven Design มีเป้าหมายหลักคืออะไร?