Strategic Design
มอง domain จากมุมสูง วางรากฐานของ model ก่อนลงรายละเอียด
การจำลอง domain ใน DDD มี 2 เฟสที่เสริมกัน — strategic design และ tactical design Strategic Design คือชุดกิจกรรมและ pattern ระดับสูงที่ตอบคำถาม “ระบบนี้ประกอบด้วยส่วนอะไรบ้าง แต่ละส่วนสำคัญแค่ไหน และส่วนเหล่านั้นสื่อสารกันอย่างไร” — ก่อนที่จะลงไปออกแบบ entity, value object หรือ aggregate ภายในแต่ละส่วน
Eric Evans อธิบายไว้ใน “Domain-Driven Design” (2003) ว่าระบบขนาดใหญ่ไม่มีทางมี model เดียวที่ “รวมเป็นหนึ่ง” ครอบคลุมทั้งองค์กรได้อย่างคุ้มค่า เพราะแต่ละส่วนของธุรกิจมักใช้คำศัพท์เดียวกันในความหมายต่างกัน (polyseme) Strategic Design จึงเป็นเครื่องมือจัดการความซับซ้อนระดับองค์กร โดยทำสามเรื่องหลักไปพร้อมกัน
- แบ่ง domain ใหญ่ (domain) เป็น subdomain และจัดลำดับความสำคัญว่าส่วนไหนคือ core, supporting หรือ generic
- นิยาม bounded context — ขอบเขตของแต่ละ model ย่อยและ ubiquitous language ของมัน
- วาง Context Mapping — อธิบายความสัมพันธ์และการสื่อสารระหว่าง bounded context เหล่านั้น
เทคนิคที่ใช้ค้นหาข้อมูลในเฟสนี้ได้แก่ Domain Storytelling และ EventStorming ซึ่งรวบรวมรายละเอียดจาก domain เอ็กซ์เพิร์ตและทีมงาน เพื่อสร้าง model domain เชิงแนวคิด (conceptual domain model) ก่อนที่จะตัดสินใจเรื่อง code หรือเทคโนโลยีใด ๆ
บทบาทใน DDD
หัวข้อที่มีชื่อว่า “บทบาทใน DDD”Strategic Design ตอบโจทย์ที่ tactical design เพียงอย่างเดียวแก้ไม่ได้ นั่นคือปัญหาระดับ “องค์กรและทีม” ไม่ใช่ระดับ “class และอ็อบเจ็กต์”
- จัดลำดับความสำคัญของการลงทุน — ผ่านการจำแนก subdomain เป็น core (สร้างความได้เปรียบทางการแข่งขัน ควรลงแรงออกแบบมากที่สุด), supporting (จำเป็นต่อธุรกิจแต่ไม่ใช่จุดต่างที่ทำให้ชนะคู่แข่ง) และ generic (ปัญหาที่อุตสาหกรรมแก้ไว้แล้ว ควรซื้อหรือใช้ของสำเร็จรูปแทนสร้างเอง)
- ป้องกัน model ปนเปื้อนกัน — bounded context แต่ละอันมี ubiquitous language ของตัวเอง คำว่า “Customer” ใน Billing context ไม่จำเป็นต้องมี field เหมือนกับ “Customer” ใน Support context การพยายามยัดทุกความหมายไว้ใน class เดียวมักจบด้วย Blob ที่ทุกทีมกลัวจะแก้
- กำหนดหน่วยของสถาปัตยกรรมและทีม — Context Mapping ระบุ pattern ความสัมพันธ์ระหว่างบริบท เช่น Shared Kernel, Customer-Supplier, Conformist, Open Host Service และ Anti-Corruption Layer ซึ่งสอดคล้องกับ Conway’s Law — โครงสร้างการสื่อสารของทีมมักสะท้อนอยู่ในโครงสร้างของระบบ
- เป็นจุดเริ่มต้นของการตัดขอบเขต microservice — แนวทางของ Microsoft Azure Architecture Center แนะนำว่า microservice หนึ่งไม่ควรครอบคลุมมากกว่า1 bounded context และไม่ควรเล็กกว่า1 aggregate strategic design (วิเคราะห์ domain → นิยาม bounded context) จึงมาก่อนขั้นตอน tactical design (นิยาม entity/aggregate/service) เสมอในกระบวนการนี้
ข้อควรระวัง Strategic Design ไม่ใช่ Big Design Up Front (BDUF) มันเป็นกิจกรรมที่ทำซ้ำได้ (iterative) — เมื่อทีมเข้าใจ domain มากขึ้น ขอบเขต bounded context ก็ปรับเปลี่ยนได้ Vaughn Vernon ย้ำใน “Implementing Domain-Driven Design” (2013) ว่า strategic patterns (bounded context, context map, ubiquitous language) ควรมาก่อน tactical patterns เสมอ เพราะถ้าขอบเขตผิดตั้งแต่แรก การออกแบบ entity ที่ดีเพียงใดก็แก้ปัญหาพื้นฐานไม่ได้
ตัวอย่าง
หัวข้อที่มีชื่อว่า “ตัวอย่าง”สมมติบริษัท Fabrikam เปิดบริการส่งของด้วยโดรน (ตัวอย่างจาก Microsoft Azure Architecture Center) ทีมเริ่มจาก strategic design ก่อนเขียน code สักบรรทัด
- วิเคราะห์ domain — ระดมความเห็นกับ domain เอ็กซ์เพิร์ตจนได้แผนภาพความสัมพันธ์ของ function ทางธุรกิจ: Shipping, Drone Management, ETA Analysis, Accounts, Invoicing, Call Center ฯลฯ
- จำแนก subdomain — Shipping และ Drone Management เป็น core subdomain (ต้องลงทุนออกแบบละเอียดที่สุดเพราะคือจุดต่างของธุรกิจ) Invoicing เป็น supporting subdomain ส่วน User Accounts และ Call Center เป็น generic subdomain ที่ใช้ระบบสำเร็จรูปได้เลย
- นิยาม bounded context — แบ่งเป็น Shipping context, Drone Management context, Accounts context โดยแต่ละอันมี model
Droneของตัวเองที่ไม่จำเป็นต้องเหมือนกัน (ระบบซ่อมบำรุงสนใจ mileage/maintenance history ส่วนระบบจัดส่งสนใจแค่ availability/ETA) - วาง context map — ระบุว่า Shipping พึ่งพา Accounts แบบ Customer-Supplier และพึ่งพา Drone Management ผ่าน Open Host Service
code C# ด้านล่างแสดงผลลัพธ์ของการตัดสินใจเชิง strategic: แต่ละ bounded context มีนิยาม Drone เป็นของตัวเอง และมี translator ทำหน้าที่แปลงข้อมูลข้ามขอบเขต — นี่คือสิ่งที่ tactical design จะ “ลงรายละเอียด” ต่อ หลังจาก strategic design “ตัดขอบเขต” ไว้แล้ว
// ===== Shipping bounded context =====// สนใจแค่ว่าโดรนว่างหรือไม่ และ ETA เท่านั้นnamespace Shipping.Domain{ public sealed class AvailableDrone { public Guid DroneId { get; } public bool IsAvailable { get; } public TimeSpan EstimatedTimeToPickup { get; }
public AvailableDrone(Guid droneId, bool isAvailable, TimeSpan estimatedTimeToPickup) { DroneId = droneId; IsAvailable = isAvailable; EstimatedTimeToPickup = estimatedTimeToPickup; } }}
// ===== Drone Management bounded context =====// สนใจรายละเอียดเชิงกายภาพและประวัติซ่อมบำรุงของโดรนnamespace DroneManagement.Domain{ public class Drone { public Guid DroneId { get; } public string ModelNumber { get; } public double MileageKm { get; private set; } public DateTime LastMaintenanceDate { get; private set; } public bool IsGrounded { get; private set; }
public Drone(Guid droneId, string modelNumber) { DroneId = droneId; ModelNumber = modelNumber; }
public void ScheduleMaintenance() { // logic เชิง domain ที่ Shipping context ไม่จำเป็นต้องรู้เลย IsGrounded = true; LastMaintenanceDate = DateTime.UtcNow; } }
// translator ที่ open host service ของ Drone Management เปิดให้ context อื่นเรียกใช้ public static class DroneToAvailabilityTranslator { public static Shipping.Domain.AvailableDrone ToAvailableDrone(Drone drone, TimeSpan eta) { // จงใจคัดลอกเฉพาะข้อมูลที่ Shipping context ต้องใช้ ไม่ยัด field ภายในเข้าไป return new Shipping.Domain.AvailableDrone( drone.DroneId, isAvailable: !drone.IsGrounded, estimatedTimeToPickup: eta); } }}แผนภาพต่อไปนี้แสดงลำดับกิจกรรมของ strategic design ตั้งแต่วิเคราะห์ domain จนถึงส่งต่อให้ tactical design
graph LR
Domain[Domain analysis]
Subdomain[Subdomain classification]
BC[Bounded context definition]
CtxMap[Context mapping]
UL[Ubiquitous language per context]
Tactical[Tactical design]
Domain --> Subdomain
Subdomain --> BC
BC --> UL
BC --> CtxMap
CtxMap --> Tactical
UL --> Tactical
ความสัมพันธ์กับแนวคิดอื่น
หัวข้อที่มีชื่อว่า “ความสัมพันธ์กับแนวคิดอื่น”- Tactical Design — Strategic Design ตอบคำถาม “ขอบเขตอยู่ตรงไหน” ส่วน Tactical Design ตอบคำถาม “ภายในขอบเขตนั้นออกแบบ code อย่างไร” ทั้งสองเฟสทำงานคู่กันเสมอ — strategic มาก่อนเพื่อกำหนดกรอบ แล้ว tactical จึงลงรายละเอียด
- Domain และ Subdomain — domain คือพื้นที่ปัญหาทั้งหมด ซึ่ง strategic design วิเคราะห์แตกเป็น subdomain (core/supporting/generic) เพื่อจัดลำดับความสำคัญของการลงทุน
- Bounded Context และ Ubiquitous Language — ผลลัพธ์หลักของ strategic design คือการนิยาม bounded context แต่ละอันพร้อม ubiquitous language ของตัวเอง
- Context Mapping — เมื่อมีหลาย bounded context strategic design ใช้ Context Mapping อธิบายความสัมพันธ์ระหว่างกัน เช่น Customer-Supplier, Shared Kernel, Anti-Corruption Layer
- EventStorming และ Domain Storytelling — เทคนิคเชิงปฏิบัติที่ใช้ในเฟส strategic design เพื่อดึงความรู้ domain จากผู้เชี่ยวชาญ ได้แก่ EventStorming และ Domain Storytelling
- Conway’s Law — ขอบเขตที่ strategic design กำหนดไว้มักสอดคล้องกับโครงสร้างทีมตาม Conway’s Law และมักใช้เป็นเกณฑ์ตัดขอบเขต microservice ในสถาปัตยกรรมสมัยใหม่
ที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “ที่เกี่ยวข้อง”แหล่งอ้างอิง
หัวข้อที่มีชื่อว่า “แหล่งอ้างอิง”- ที่มา · deviq.com/domain-driven-design/strategic-design
- Bounded Context — Martin Fowler’s bliki
- Use Domain Analysis to Model Microservices — Azure Architecture Center, Microsoft Learn
- Use Tactical DDD to Design Microservices — Azure Architecture Center, Microsoft Learn
- Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software (2003) — ต้นกำเนิดของ strategic design patterns
- Vaughn Vernon, Implementing Domain-Driven Design (2013) — บทที่ 2-3 ว่าด้วย strategic patterns: bounded context, context map และ ubiquitous language