Strategic Design ด้วย Subdomain
เวลาลงมือทำ project DDDDomain-Driven Design (DDD)แนวทางพัฒนาซอฟต์แวร์ที่เน้นสร้าง domain model ซึ่งเข้าใจกฎและกระบวนการของธุรกิจอย่างลึกซึ้ง แล้วเขียนลงใน code จริง บัญญัติโดย Eric Evans (2003) แบ่งเป็น Strategic และ Tactical DesignStrategic Design จะมี Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design หลายตัวทำงานอยู่ด้วยกันเสมอ หนึ่งในนั้นคือ Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design และยังมี SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design อีกหลายตัวกระจายอยู่ใน Bounded Context อื่นๆ บทก่อนหน้าได้ชี้ให้เห็นความสำคัญของการแบ่ง model ต่างๆ ตาม Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงใน codeStrategic Design เฉพาะของมัน แล้วก่อร่างขึ้นเป็นหลาย Bounded Context
ลองนึกถึงภาพรวมของระบบบริหาร project แบบ Agile ที่หนังสือยกมาเป็นตัวอย่างหลัก — ในภาพนั้นมี Bounded Context หกตัวและ Subdomain หกตัว เพราะใช้ Strategic Design ของ DDD ออกแบบ ทีมจึงได้องค์ประกอบของ model ที่ลงตัวที่สุด นั่นคือ 1 Subdomain ต่อ1 Bounded Context และ1 Bounded Context ต่อ1 Subdomain พูดอีกอย่างคือ “แกนหลักของระบบบริหาร project แบบ Agile” (Agile Project Management Core) เป็นทั้ง Bounded Context ที่สะอาดหนึ่งตัว และเป็น Subdomain ที่สะอาดหนึ่งตัวในเวลาเดียวกัน บางสถานการณ์อาจมีหลาย Subdomain อยู่ใน Bounded Context เดียว แต่นั่นยังไม่ใช่ผลลัพธ์ของการสร้าง model ที่ดีที่สุด
graph LR
subgraph BC1["Bounded Context #1 — Agile PM Core"]
SD1["Subdomain (Core Domain)"]
end
subgraph BC2["Bounded Context #2"]
SD2["Subdomain"]
end
subgraph BC3["Bounded Context #3"]
SD3["Subdomain"]
end
subgraph BC4["Bounded Context #4"]
SD4["Subdomain"]
end
subgraph BC5["Bounded Context #5"]
SD5["Subdomain"]
end
subgraph BC6["Bounded Context #6"]
SD6["Subdomain"]
end
BC1 --- BC2
BC2 --- BC3
BC3 --- BC4
BC4 --- BC5
BC5 --- BC6
จำให้แม่นว่า SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design อยู่ใน พื้นที่ปัญหา (Problem Space)Problem Space“พื้นที่ปัญหา” — สิ่งที่ธุรกิจต้องการแก้ไข อยู่ในรูปของ Domain และ Subdomain (ยังไม่พูดถึงวิธีแก้)Strategic Design — มันคือ “สิ่งที่ธุรกิจต้องแก้” ส่วน Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design อยู่ใน พื้นที่คำตอบ (Solution Space)Solution Space“พื้นที่คำตอบ” — วิธีที่เราเลือกแก้ปัญหา อยู่ในรูปของ Bounded Context และ model 1 subdomain อาจมีได้หลายคำตอบStrategic Design — มันคือ “วิธีที่เราเลือกแก้” เป้าหมายของ DDD คือทำให้ทั้งสองฝั่งจับคู่กันแบบหนึ่งต่อหนึ่งให้ได้มากที่สุด
Subdomain คืออะไร? (What Is a Subdomain?)
หัวข้อที่มีชื่อว่า “Subdomain คืออะไร? (What Is a Subdomain?)”SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design คือ ส่วนย่อยของ โดเมน (Domain)Domainขอบเขตของปัญหาหรือธุรกิจที่ซอฟต์แวร์ของเราเข้าไปแก้ไข เช่น การขนส่งสินค้า การธนาคาร e-commerce — คือ “โลกของผู้ใช้” ที่โปรแกรมต้องเข้าใจStrategic Design ทางธุรกิจโดยรวม มองมันเป็น “model ของ domain เชิงตรรกะหนึ่งชุด” ได้เลย domain ทางธุรกิจส่วนใหญ่มักใหญ่และซับซ้อนเกินกว่าจะคิดทั้งก้อนพร้อมกันได้ ฉะนั้นโดยทั่วไปจึงสนใจเฉพาะ Subdomain ที่จำเป็นต้องใช้ภายใน project เดียวเท่านั้น Subdomain จึงเป็นเครื่องมือ แบ่ง domain ทั้งหมดออกเป็นส่วนๆ ในเชิงตรรกะ เพื่อให้เข้าใจพื้นที่ปัญหาบน project ขนาดใหญ่ที่ซับซ้อนได้
อีกมุม1 Subdomain คือ พื้นที่ความเชี่ยวชาญที่ชัดเจน โดยถือว่ามันรับผิดชอบการให้คำตอบกับส่วนหลักส่วนหนึ่งของธุรกิจ นั่นแปลว่า Subdomain หนึ่งๆ จะมี ผู้เชี่ยวชาญธุรกิจ (Domain Expert)Domain Expertผู้เชี่ยวชาญธุรกิจที่รู้กฎ กระบวนการ และความต้องการของ domain อย่างลึกซึ้ง เป็นแหล่งความรู้สำคัญที่ทีมพัฒนาต้องร่วมงานด้วยอย่างใกล้ชิดใน DDDStrategic Design อย่างน้อยหนึ่งคนที่เข้าใจแง่มุมของธุรกิจซึ่ง Subdomain นั้นรองรับเป็นอย่างดี และแต่ละ Subdomain ก็มี ความสำคัญเชิงกลยุทธ์ต่อธุรกิจมากน้อยต่างกัน
ถ้าใช้ DDD พัฒนาขึ้นมา Subdomain นั้นจะถูก implement ออกมาเป็น Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design ที่สะอาด และผู้เชี่ยวชาญธุรกิจที่ชำนาญในพื้นที่นั้นโดยเฉพาะก็จะเป็นสมาชิกของทีมที่พัฒนา Bounded Context ตัวนั้นด้วย แม้การใช้ DDD สร้าง Bounded Context ที่สะอาดจะเป็นทางเลือกที่ดีที่สุด แต่ในความเป็นจริงบางครั้งก็ได้แค่ “หวังว่ามันจะเป็นอย่างนั้น” เท่านั้น
ประเภทของ Subdomain (Types of Subdomains)
หัวข้อที่มีชื่อว่า “ประเภทของ Subdomain (Types of Subdomains)”ภายใน project หนึ่ง มี Subdomain หลักๆ สามประเภท:
-
Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design: จุดที่เราลงทุนเชิงกลยุทธ์กับ model ของ domain ชุดเดียวที่นิยามไว้อย่างดี ทุ่มทรัพยากรจำนวนมากเพื่อประดิษฐ์ Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงใน codeStrategic Design อย่างพิถีพิถันใน Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design ที่ชัดเจน นี่คือสิ่งที่อยู่อันดับต้นๆ ในรายการ project ขององค์กร เพราะมันคือสิ่งที่ทำให้องค์กร แตกต่างจากคู่แข่งทั้งหมด ในเมื่อองค์กรไม่อาจโดดเด่นในทุกเรื่องที่ทำ Core Domain จึงเป็นเส้นแบ่งที่บอกว่า “องค์กรต้องเก่งที่สุดตรงไหน” การจะไปถึงระดับการเรียนรู้และความเข้าใจที่ลึกพอจะตัดสินเรื่องนี้ได้ ต้องอาศัยทั้งความมุ่งมั่น การร่วมมือกัน และการทดลอง นี่คือจุดที่องค์กรควรลงทุนกับซอฟต์แวร์อย่างไม่กั๊กที่สุด
-
Supporting SubdomainSupporting Subdomainส่วนที่จำเป็นและเฉพาะกับธุรกิจเรา แต่ไม่ใช่จุดที่สร้างความได้เปรียบ ไม่มีของสำเร็จรูปที่พอดี จึงต้องทำเอง แต่ลงทุนน้อยกว่า coreStrategic Design: สถานการณ์ที่ต้องพัฒนาขึ้นเอง (custom development) เพราะไม่มีของสำเร็จรูปที่ตอบโจทย์ แต่ก็ยังไม่ลงทุนหนักเท่ากับที่ลงให้ Core Domain อาจพิจารณาจ้างทำภายนอก (outsource) สำหรับ Bounded Context ประเภทนี้ เพื่อไม่ให้เผลอเข้าใจผิดว่ามันเป็นจุดสร้างความแตกต่างเชิงกลยุทธ์แล้วทุ่มลงทุนมากเกินไป ถึงอย่างนั้นมันก็ยังเป็น model ซอฟต์แวร์ที่สำคัญ เพราะ Core Domain จะสำเร็จไม่ได้เลยหากขาดมัน
-
Generic SubdomainGeneric Subdomainปัญหาที่แก้กันมาแล้วทั่วไป เช่น ระบบ login บัญชี การแจ้งเตือน — ควรใช้ของสำเร็จรูปหรือ library แทนการเขียนเองStrategic Design: ทางออกประเภทที่อาจหาซื้อสำเร็จรูปได้ หรือจ้างทำภายนอก หรือแม้แต่พัฒนาเองภายในโดยทีมที่ไม่จำเป็นต้องเป็นนักพัฒนาระดับหัวกะทิแบบที่จัดให้ Core Domain หรือแม้แต่ Supporting Subdomain ที่สำคัญรองลงมา ระวังอย่าเข้าใจผิดว่า Generic Subdomain เป็น Core Domain เพราะเราไม่ควรทุ่มลงทุนแบบนั้นที่นี่
เมื่อพูดถึง project ที่นำ DDD มาใช้ เรามักกำลังพูดถึง Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design
SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design คือเครื่องมือแยก domain ใหญ่ออกเป็นส่วนเชิงตรรกะใน พื้นที่ปัญหา และแบ่งเป็นสามประเภทตามความสำคัญเชิงกลยุทธ์ — Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design คือจุดที่ต้องโดดเด่นเหนือคู่แข่ง (ทุ่มทีมเก่งที่สุด), Supporting SubdomainSupporting Subdomainส่วนที่จำเป็นและเฉพาะกับธุรกิจเรา แต่ไม่ใช่จุดที่สร้างความได้เปรียบ ไม่มีของสำเร็จรูปที่พอดี จึงต้องทำเอง แต่ลงทุนน้อยกว่า coreStrategic Design จำเป็นแต่ไม่ใช่จุดต่าง (ทำเองแต่ลงทุนน้อยกว่า), Generic SubdomainGeneric Subdomainปัญหาที่แก้กันมาแล้วทั่วไป เช่น ระบบ login บัญชี การแจ้งเตือน — ควรใช้ของสำเร็จรูปหรือ library แทนการเขียนเองStrategic Design เป็นปัญหาทั่วไป (ควรซื้อหรือ outsource) กฎทองคือ อย่าเข้าใจผิดว่าของทั่วไปคือแก่น
รับมือกับความซับซ้อน (Dealing with Complexity)
หัวข้อที่มีชื่อว่า “รับมือกับความซับซ้อน (Dealing with Complexity)”ขอบเขตบางส่วนของระบบภายใน domain ทางธุรกิจมีโอกาสสูงมากที่จะเป็น ระบบ legacy ไม่ว่าจะเป็นระบบที่องค์กรสร้างเองหรือซื้อ license มา ณ จุดนี้เราอาจทำอะไรกับการปรับปรุงระบบ legacy เหล่านั้นไม่ได้มากนัก แต่ก็ยังต้อง “คิดถึงมัน” เมื่อมันส่งผลกระทบต่อ project Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design ของเรา และวิธีคิดถึงมันก็คือ — ใช้ SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design เป็นเครื่องมือในการพูดคุยเกี่ยวกับพื้นที่ปัญหา
น่าเสียดายแต่ก็เป็นความจริงว่า ระบบ legacy บางตัวขัดกับวิถี DDD ที่ออกแบบด้วย Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design ถึงขนาดที่เรียกมันได้ว่าเป็น “ระบบ legacy ที่ไร้ขอบเขต (unbounded legacy systems)” เพราะระบบแบบนั้นก็คือสิ่งที่เรียกกันว่า Big Ball of MudBig Ball of Mudระบบที่ปนเปกันยุ่งเหยิงไม่มีขอบเขตชัด ให้ลากเส้นล้อมไว้แล้วยอมรับสภาพ ไม่พยายามทำ model ละเอียดในนั้น และระวังไม่ให้ลามไป context อื่นStrategic Design เอาเข้าจริงระบบเดียวนั้นเต็มไปด้วย model หลายชุดที่พันกันยุ่งเหยิง ทั้งที่ควรถูกออกแบบและ implement แยกจากกัน แต่กลับถูกยำรวมกันเป็นกองที่ซับซ้อนและเกี่ยวพันกันไปหมด
graph TB
subgraph BBOM["Unbounded Legacy — Big Ball of Mud"]
direction LR
subgraph S1["Accounts Subdomain (บัญชี)"]
A1[" "] --> A2[" "]
end
subgraph S2["Orders Subdomain (คำสั่งซื้อ)"]
B1[" "] --> B2[" "]
end
subgraph S3["Catalog Subdomain (catalog)"]
C1[" "] --> C2[" "]
end
subgraph S4["Fulfillment Subdomain (การเตรียมจัดส่ง)"]
D1[" "] --> D2[" "]
end
subgraph S5["Shipping Subdomain (การจัดส่ง)"]
E1[" "] --> E2[" "]
end
A2 -.->|"พันกันข้าม model"| B1
B2 -.-> C1
C2 -.-> D1
D2 -.-> E1
end
พูดอีกแบบหนึ่งคือ เมื่อพูดถึงระบบ legacy หนึ่งตัว ภายในนั้นมีแนวโน้มจะมี model ของ domain เชิงตรรกะอยู่บ้าง หรือกระทั่งมากมายหลายชุด ให้มอง model เชิงตรรกะแต่ละชุดเป็น Subdomain หนึ่งตัว ในภาพข้างต้น Subdomain เชิงตรรกะแต่ละตัวที่อยู่ในระบบ legacy แบบ monolith ไร้ขอบเขต (Big Ball of MudBig Ball of Mudระบบที่ปนเปกันยุ่งเหยิงไม่มีขอบเขตชัด ให้ลากเส้นล้อมไว้แล้วยอมรับสภาพ ไม่พยายามทำ model ละเอียดในนั้น และระวังไม่ให้ลามไป context อื่นStrategic Design) ถูกขีดล้อมไว้ด้วยกรอบเส้นประ ทั้งหมดมี model เชิงตรรกะหรือ Subdomain อยู่ห้าชุด การปฏิบัติต่อ Subdomain เชิงตรรกะในลักษณะนี้ช่วยให้จัดการกับความซับซ้อนของระบบขนาดใหญ่ได้ เพราะมันทำให้เรามองพื้นที่ปัญหาราวกับว่ามันถูกพัฒนาด้วย DDD และมีหลาย Bounded Context
ระบบ legacy จะดู “เป็นก้อนเดียวและขุ่นมัว” น้อยลง ถ้าจินตนาการว่ามี Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงใน codeStrategic Design แยกกันหลายชุด — อย่างน้อยก็เพื่อให้เข้าใจว่าต้องเชื่อมต่อ (integrate) กับมันอย่างไร การคิดและพูดคุยถึงระบบ legacy แบบนี้ด้วยแนวคิด Subdomain ช่วยให้รับมือกับความจริงอันโหดร้ายของ model ก้อนใหญ่ที่พันกันยุ่งได้ และเมื่อใช้เครื่องมือนี้ในการคิด ก็จะระบุได้ว่า Subdomain ใดมีค่าต่อธุรกิจมากกว่าและจำเป็นต่อ project ของเรา ส่วนตัวไหนจัดให้อยู่ในสถานะรองลงไปได้
จากตรงนี้แนวคิด Subdomain เดียวกันยังพา Core Domain ที่เรากำลังทำมาวางเทียบกับ Subdomain ตัวอื่นในภาพเดียวกันได้ด้วย เรื่องนี้จะชัดขึ้นในหัวข้อถัดไปเมื่อจับแต่ละ Bounded Context ให้ตรงกับ Subdomain หนึ่งตัว
ลองนึกถึงระบบ retail e-commerce รุ่นเก่าที่เขียนยำรวมกันมาเป็นก้อนเดียว ทั้งบัญชี (Accounts) คำสั่งซื้อ (Orders) catalog สินค้า (Catalog) การเตรียมจัดส่ง (Fulfillment) และการจัดส่ง (Shipping) ปนกันอยู่ในฐาน code เดียว เรายังแก้ code เก่าไม่ได้ในตอนนี้ แต่ขีดกรอบเส้นประรอบ model เชิงตรรกะแต่ละก้อนเพื่อมองมันเป็น SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design ได้ จากนั้นจึงค่อยพา Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design ตัวใหม่ (เช่น “คำสั่งซื้อ” ที่สร้างด้วย DDD) มาเชื่อมต่อกับระบบ legacy เดิม — แทนที่จะรื้อทั้งก้อนในคราวเดียว
จับ Bounded Context ให้ตรงกับ Subdomain แบบ 1:1
หัวข้อที่มีชื่อว่า “จับ Bounded Context ให้ตรงกับ Subdomain แบบ 1:1”พอมีแนวคิด Subdomain อยู่ในมือ เรายังวาด Core Domain ที่กำลังทำอยู่ลงไปในแผนภาพง่ายๆ ภาพเดียวกับ Subdomain ตัวอื่นๆ ได้ด้วย ตัวอย่างจากหนังสือวาด Subdomain ทั้งสามประเภทไว้ข้างๆ กัน — Core Domain คือ “Agile Project Management Context”, Generic Subdomain คือ “Identity and Access Context” (ระบบยืนยันตัวตนและสิทธิ์การเข้าถึง) และ Supporting Subdomain คือ “Collaboration Context” (ระบบทำงานร่วมกัน) ภาพแบบนี้ช่วยให้เห็นความเกี่ยวพันและการพึ่งพากันระหว่าง Subdomain ต่างๆ ส่วนรายละเอียดเชิงลึกขอยกไปไว้ในบทว่าด้วย Context MappingContext Mappingกิจกรรมการระบุ Bounded Context และนิยามความสัมพันธ์ระหว่างกัน (เช่น Partnership, Shared Kernel, ACL) เพื่อจัดการการเชื่อมต่อระหว่างทีม/ระบบStrategic Design
graph LR
subgraph GEN["Generic Subdomain"]
IAC(["Identity and Access Context"])
end
subgraph CORE["Core Domain"]
APM(["Agile Project Management Context"])
end
subgraph SUP["Supporting Subdomain"]
COL(["Collaboration Context"])
end
classDef dashed stroke-dasharray:6 6;
class GEN,CORE,SUP dashed;
เมื่อใช้ DDD Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design ควรจับคู่แบบ หนึ่งต่อหนึ่ง (1:1) กับ SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design เพียงตัวเดียว นั่นคือ ถ้ามี Bounded Context หนึ่งตัว เป้าหมายคือให้มี model Subdomain หนึ่งชุดอยู่ใน Bounded Context นั้น มันอาจไม่ได้ทำได้เสมอไปหรือทำได้จริงแต่ตรงไหนที่ทำได้ก็สำคัญที่จะออกแบบไปในทางนั้น เพราะจะทำให้ Bounded Context สะอาดและโฟกัสอยู่กับความริเริ่มเชิงกลยุทธ์ที่เป็นแกนหลัก
ถ้าจำเป็นต้องสร้าง model ตัวที่สองใน Bounded Context เดียวกัน (ภายใน Core Domain) ควรแยก model รองนั้นออกจาก Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design ด้วย โมดูล (Module)Moduleการจัดกลุ่มแนวคิดที่เกี่ยวข้องกันไว้ด้วยกัน (เช่น package) ตั้งชื่อให้เป็นส่วนหนึ่งของ Ubiquitous Language จัดตามธุรกิจ ไม่ใช่ตามชนิดทางเทคนิคTactical Design ที่แยกออกจากกันโดยสิ้นเชิง (module ใน DDD โดยพื้นฐานก็คือ package ใน Scala และ Java และคือ namespace ใน F# และ C#) วิธีนี้เป็นการประกาศในเชิงภาษาอย่างชัดเจนว่า model หนึ่งคือแกนหลัก ส่วนอีก model เป็นเพียงตัวสนับสนุน การใช้การแยก Subdomain ในลักษณะนี้คือสิ่งที่จะนำมาใช้ใน พื้นที่คำตอบ (Solution Space)Solution Space“พื้นที่คำตอบ” — วิธีที่เราเลือกแก้ปัญหา อยู่ในรูปของ Bounded Context และ model 1 subdomain อาจมีได้หลายคำตอบStrategic Design
graph TB
subgraph BC["Bounded Context (Core Domain)"]
CORE["module: model Core (แกนหลัก)"]
SUPP["module: model Supporting (ตัวสนับสนุน)"]
CORE -.->|"แยกด้วย Module ชัดเจน"| SUPP
end
อันตรายที่พบบ่อยคือการ เข้าใจผิดว่า Generic SubdomainGeneric Subdomainปัญหาที่แก้กันมาแล้วทั่วไป เช่น ระบบ login บัญชี การแจ้งเตือน — ควรใช้ของสำเร็จรูปหรือ library แทนการเขียนเองStrategic Design หรือ Supporting SubdomainSupporting Subdomainส่วนที่จำเป็นและเฉพาะกับธุรกิจเรา แต่ไม่ใช่จุดที่สร้างความได้เปรียบ ไม่มีของสำเร็จรูปที่พอดี จึงต้องทำเอง แต่ลงทุนน้อยกว่า coreStrategic Design เป็น Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design แล้วทุ่มทีมเก่งที่สุดและงบประมาณก้อนใหญ่ลงไป ผลคือไปสร้างของที่ “ซื้อสำเร็จรูปก็ได้” ขึ้นมาเอง ขณะที่แก่นจริงๆ กลับขาดแรง จงระบุให้ชัดว่าจุดไหนทำให้ธุรกิจ “ชนะ” แล้วลงแรงตรงนั้น
สรุป (Summary)
หัวข้อที่มีชื่อว่า “สรุป (Summary)”ในบทนี้เราได้เรียนรู้ว่า SubdomainSubdomainส่วนย่อยของ Domain ใหญ่ เช่น Domain e-commerce แตกเป็น subdomain การสั่งซื้อ การชำระเงิน คลังสินค้า ฯลฯ อยู่ใน “พื้นที่ปัญหา” (problem space)Strategic Design คืออะไรและถูกใช้อย่างไร ทั้งใน พื้นที่ปัญหาProblem Space“พื้นที่ปัญหา” — สิ่งที่ธุรกิจต้องการแก้ไข อยู่ในรูปของ Domain และ Subdomain (ยังไม่พูดถึงวิธีแก้)Strategic Design และ พื้นที่คำตอบSolution Space“พื้นที่คำตอบ” — วิธีที่เราเลือกแก้ปัญหา อยู่ในรูปของ Bounded Context และ model 1 subdomain อาจมีได้หลายคำตอบStrategic Design เราเห็นความแตกต่างระหว่าง Core DomainCore Domainsubdomain ที่สำคัญและสร้างความได้เปรียบในการแข่งขันมากที่สุด เป็นเหตุผลที่เราต้องสร้างซอฟต์แวร์เองแทนการซื้อ ควรทุ่มทีมเก่งที่สุดลงตรงนี้Strategic Design (จุดที่ต้องโดดเด่นเหนือคู่แข่งและทุ่มลงทุนมากที่สุด), Supporting SubdomainSupporting Subdomainส่วนที่จำเป็นและเฉพาะกับธุรกิจเรา แต่ไม่ใช่จุดที่สร้างความได้เปรียบ ไม่มีของสำเร็จรูปที่พอดี จึงต้องทำเอง แต่ลงทุนน้อยกว่า coreStrategic Design (จำเป็นต่อความสำเร็จของแกนหลักแต่ไม่ใช่จุดสร้างความต่าง), และ Generic SubdomainGeneric Subdomainปัญหาที่แก้กันมาแล้วทั่วไป เช่น ระบบ login บัญชี การแจ้งเตือน — ควรใช้ของสำเร็จรูปหรือ library แทนการเขียนเองStrategic Design (ปัญหาทั่วไปที่ควรซื้อหรือ outsource)
เราได้เห็นว่าจะใช้ Subdomain ช่วยคิดเรื่องการเชื่อมต่อกับระบบ legacy แบบ Big Ball of MudBig Ball of Mudระบบที่ปนเปกันยุ่งเหยิงไม่มีขอบเขตชัด ให้ลากเส้นล้อมไว้แล้วยอมรับสภาพ ไม่พยายามทำ model ละเอียดในนั้น และระวังไม่ให้ลามไป context อื่นStrategic Design ได้อย่างไร — ด้วยการมอง model เชิงตรรกะแต่ละก้อนในระบบไร้ขอบเขตนั้นเป็น Subdomain หนึ่งตัว เพื่อให้รับมือกับความซับซ้อนของระบบใหญ่ได้ราวกับมันถูกออกแบบมาด้วย DDD และยังย้ำถึงความสำคัญของการจับ Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design ให้ตรงกับ Subdomain เดียวแบบหนึ่งต่อหนึ่ง รวมถึงวิธีแยก model Supporting Subdomain ออกจาก model Core Domain ด้วย โมดูล (Module)Moduleการจัดกลุ่มแนวคิดที่เกี่ยวข้องกันไว้ด้วยกัน (เช่น package) ตั้งชื่อให้เป็นส่วนหนึ่งของ Ubiquitous Language จัดตามธุรกิจ ไม่ใช่ตามชนิดทางเทคนิคTactical Design ของ DDD ในกรณีที่แยกออกเป็นคนละ Bounded Context ไม่สะดวก
สำหรับเนื้อหาเชิงลึกครบถ้วนเรื่อง Subdomain ดูได้ในบทที่ 2 ของหนังสือ Implementing Domain-Driven Design ของ Vaughn Vernon
— Vaughn Vernon, Domain-Driven Design Distilled
เจาะลึกแนวคิดในบทนี้ต่อได้ที่คลังอ้างอิง DevIQ:
- Subdomain — นิยามและตัวอย่างของ Subdomain ในฐานะส่วนย่อยเชิงตรรกะของ domain ทางธุรกิจ ตรงกับหัวใจของบทนี้
- Domain — เปรียบเทียบ Subdomain กับ Core Domain ช่วยขยายความแตกต่างระหว่างสามประเภทของ Subdomain ที่บทนี้อธิบาย
- Bounded Context — อธิบายฝั่งพื้นที่คำตอบที่ต้องจับคู่แบบ 1:1 กับ Subdomain ตามที่บทนี้เน้นย้ำ
- Big Ball of Mud — แอนตี้แพทเทิร์นของระบบ legacy ไร้ขอบเขตที่บทนี้ใช้ Subdomain ช่วยแบ่งพื้นที่ปัญหาให้จัดการได้
เช็กความเข้าใจ — บทที่ 3
ข้อ 1 / 4Subdomain อยู่ในพื้นที่ใดของ DDD?