Ubiquitous Language
Ubiquitous LanguageUbiquitous Languageภาษากลางที่ทุกคนในทีม (ทั้งนักพัฒนาและผู้เชี่ยวชาญธุรกิจ) ใช้ร่วมกัน อิงกับ domain model โดยตรง คำเดียวกันต้องหมายถึงสิ่งเดียวกัน และสะท้อนลงใน codeStrategic Design คือภาษากลางที่ “เข้มงวด” ซึ่งทุกคนในทีมใช้ร่วมกัน อิงกับ Domain ModelDomain ModelModel ของ Domain ที่ฝังกฎและกระบวนการทางธุรกิจไว้ใน code จริง หัวใจของ DDD คือการพัฒนา domain model ที่ “เข้าใจธุรกิจอย่างลึกซึ้ง”Strategic Design โดยตรง เหตุที่ต้องเข้มงวดเพราะ “ซอฟต์แวร์รับมือความกำกวมได้ไม่ดี” (Fowler)
ปัญหาคลาสสิกคือ ผู้เชี่ยวชาญธุรกิจพูดภาษาหนึ่ง นักพัฒนาพูดอีกภาษาหนึ่ง แล้วต้อง “แปล” ไปมา ทุกการแปลคือโอกาสที่ความเข้าใจจะคลาดเคลื่อน DDD แก้ด้วยการสร้างภาษาเดียวที่ใช้ทั้งในการคุยและใน code — ชื่อ class method ตัวแปร ควรสะท้อนคำในภาษานี้
คำเดียวกัน อาจหมายถึงคนละสิ่ง (polyseme)
หัวข้อที่มีชื่อว่า “คำเดียวกัน อาจหมายถึงคนละสิ่ง (polyseme)”Fowler ยกตัวอย่างบริษัทไฟฟ้าที่คำว่า “meter” (มิเตอร์) มีความหมายต่างกันเล็กน้อยในแต่ละแผนก ในการสนทนาเราอาจ “กลบ” ความต่างนี้ได้ แต่ในโลกที่แม่นยำของคอมพิวเตอร์ทำไม่ได้ ทางออกไม่ใช่บังคับให้ทุกคนใช้นิยามเดียว แต่คือการยอมรับว่าความหมายขึ้นกับ “บริบท” — ซึ่งนำเราไปสู่ Bounded ContextBounded Contextขอบเขตที่ชัดเจน (มักเป็นระบบย่อยหรือทีมหนึ่ง) ที่ model หนึ่งใช้ได้และมีความหมายแน่นอน ภายในขอบเขตนี้ Ubiquitous Language สอดคล้องกัน 100%Strategic Design ในบทถัดไป
Evans ย้ำว่า การเปลี่ยนภาษาคือการเปลี่ยน model เมื่อทีมพบคำที่อึดอัดหรือสื่อความไม่ตรง ผู้เชี่ยวชาญธุรกิจควร “คัดค้าน” และนักพัฒนาควรจับสัญญาณความกำกวม การปรับภาษาให้คมขึ้นคือการปรับ model ให้ดีขึ้น
เทียบกับ Cargo Shipping
หัวข้อที่มีชื่อว่า “เทียบกับ Cargo Shipping”ในระบบขนส่ง คำว่า “เส้นทาง” อาจหมายถึงสองสิ่งที่ต่างกันมาก: สิ่งที่ลูกค้าต้องการ (ต้นทาง–ปลายทาง–กำหนดเวลา) กับ แผนจริงที่จะเดินทาง (ผ่านท่าไหน เรือลำใด) ถ้าใช้คำเดียวปนกันจะสับสนทันที
DDD จึงตั้งชื่อแยกชัดเจน: Route SpecificationRoute SpecificationValue Object ที่ระบุ “ความต้องการของลูกค้า”: ต้นทาง ปลายทาง และกำหนดเวลาถึง — มี method isSatisfiedBy() ตรวจว่าแผนเดินทางตรงตามนี้หรือไม่Tactical Design = ความต้องการของลูกค้า, ItineraryItineraryValue Object ที่เป็น “แผนการเดินทางจริง” ของ Cargo ประกอบด้วยลำดับของ Leg (ช่วงการขนส่งแต่ละช่วง)Tactical Design = แผนเดินทางจริง คำเหล่านี้กลายเป็นทั้งศัพท์ที่ทีมพูดและชื่อ class ใน code
// ภาษาใน code สะท้อนภาษาที่ทีมพูดclass RouteSpecification { constructor( readonly origin: UnLocode, // ต้นทาง readonly destination: UnLocode, // ปลายทาง readonly arrivalDeadline: Date, // กำหนดถึง ) {}
// “แผนนี้ตรงตามที่ลูกค้าต้องการไหม?” — อ่านได้เหมือนประโยคธุรกิจ isSatisfiedBy(itinerary: Itinerary): boolean { return itinerary.firstLeg().from.equals(this.origin) && itinerary.lastLeg().to.equals(this.destination) && itinerary.finalArrival() <= this.arrivalDeadline; }}เจาะลึกแนวคิดในบทนี้ต่อได้ที่คลังอ้างอิง DevIQ:
- Ubiquitous Language — นิยามและหลักการของภาษากลางที่บทนี้อธิบายโดยตรง
- Bounded Context — บริบทที่ทำให้คำแบบ “meter” หรือ “เส้นทาง” มีความหมายต่างกันได้โดยไม่ขัดแย้งกัน
- Domain Model — model ที่ Ubiquitous Language ต้องสะท้อนตรงกันทั้งในบทสนทนาและใน code
- Specification — pattern เบื้องหลัง class
RouteSpecificationในตัวอย่าง ที่ทำให้กติกาทางธุรกิจอ่านออกเป็นภาษาธุรกิจได้ตรงๆ
เช็กความเข้าใจ — Stage 1
ข้อ 1 / 3ทำไม Ubiquitous Language จึงต้อง “เข้มงวด”?