ตอนที่ 3 ของซีรีส์ Domain-Driven Design ฉบับระบบธุรกิจจริง
Theme หลัก: ระบบบริหารพนักงาน (Staff / Employee Management System)
ในตอนที่ 2 เราเห็นแล้วว่า Domain Thinking คือการให้ domain เป็นผู้ตัดสินกฎของธุรกิจ
แต่ถึง domain จะอยู่ถูกที่แล้ว ระบบก็ยังพังได้ ถ้าเราใช้ “ภาษา” ผิด
DDD เรียกภาษานี้ว่า Ubiquitous Language
ปัญหาที่แท้จริง: เราคุยกันคนละภาษา
ลองนึกถึงบทสนทนาแบบนี้ในระบบพนักงาน:
- ฝ่าย HR: “พนักงานยื่น คำขอเปลี่ยนกะ ได้วันละ 1 ครั้ง”
- Developer: “โอเค เดี๋ยวเช็ค field request_count”
- Code: canEdit = status != 2 && role != 3
ทุกคนคิดว่าตัวเองเข้าใจตรงกัน แต่จริง ๆ แล้ว:
- ธุรกิจพูดถึง คำขอ (Request)
- โค้ดพูดถึง ตัวเลขและสถานะลอย ๆ
ผลลัพธ์คือ ระบบที่:
ไม่มีใครมั่นใจว่าโค้ดสะท้อนกฎจริงครบหรือยัง
Ubiquitous Language คืออะไร
Ubiquitous Language (Ubiquitous อ่านว่า ยูบิค ควิเทิส) คือ:
ภาษาชุดเดียว ที่ถูกใช้ ร่วมกัน ระหว่าง
- คนธุรกิจ
- เอกสาร
- โค้ด
- การทดสอบ
ถ้าธุรกิจเรียกว่า “คำขอเปลี่ยนกะ”
โค้ดก็ต้องเรียกว่า:
- ShiftChangeRequest
- ไม่ใช่ RequestModel
- ไม่ใช่ Transaction
ชื่อในโค้ด ไม่ควรแปล หรือย่อความหมายของธุรกิจ
ตัวอย่างชื่อที่ทำให้ Domain พัง
ในระบบพนักงาน มักเจอชื่อแบบนี้:
- status = 1, 2, 3
- type = ‘A’
- flag = true
- role = 99
โค้ดอาจทำงานได้ แต่คำถามคือ:
- status = 2 แปลว่าอะไร?
- ใครเป็นคนตัดสิน?
- กฎนี้มาจากไหน?
ถ้าต้องเปิดเอกสารหรือถามคนอื่นทุกครั้ง แปลว่า ภาษาไม่ ubiquitous
เปลี่ยนตัวเลขให้เป็นภาษาธุรกิจ
แทนที่จะเขียนแบบนี้:
if (request.status != 1) return;
ให้เขียนแบบนี้:
enum ShiftRequestStatus {
pending,
approved,
rejected,
cancelled,
}
if (request.status != ShiftRequestStatus.pending) return;
ตอนนี้โค้ด:
- อ่านแล้วรู้ความหมายทันที
- ตรงกับภาษาที่ HR ใช้
- ลดการตีความผิด
Ubiquitous Language ต้องอยู่ทุกที่
ภาษานี้ไม่ควรอยู่แค่ใน code
แต่ควรอยู่ใน:
- ชื่อ class / method
- test case
- commit message
- document
ตัวอย่าง test:
test('manager can approve pending shift request', () {
// ...
});
ถ้าอ่าน test แล้ว HR เข้าใจได้ แปลว่าคุณมาถูกทางแล้ว
ระวังคำที่ดู technical เกินไป
คำบางคำดูเหมือนจะโอเค แต่จริง ๆ แล้วอันตราย:
- process
- handle
- manage
- data
เช่น:
- processRequest() → ทำอะไร?
- handleStaff() → handle ยังไง?
ให้ถามตัวเองว่า:
ธุรกิจใช้คำนี้จริงไหม?
ถ้าไม่ ให้เปลี่ยน
สร้างภาษาไปพร้อมกับธุรกิจ
Ubiquitous Language ไม่ใช่สิ่งที่คิดครั้งเดียวแล้วจบ
มันต้อง:
- evolve ตามความเข้าใจ
- ถูกแก้เมื่อพบว่าคำเดิมไม่ชัด
- กล้าลบชื่อเก่า แม้จะเขียนไปแล้ว
การ refactor ชื่อ:
ไม่ใช่งาน cosmetic แต่เป็นงานออกแบบ domain
สรุปตอนที่ 3
- ภาษา คือโครงสร้างของความคิด
- ชื่อที่ไม่ชัด = domain ที่พัง
- โค้ดควรอ่านเหมือนประโยคธุรกิจ
ถ้าคุณอธิบายระบบโดยเปิดโค้ดให้ฝ่ายธุรกิจดูไม่ได้
นั่นแปลว่าภาษาของระบบยังไม่ ubiquitous
ตอนต่อไป
ตอนที่ 4: Entity vs Value Object – สิ่งไหนควรมีตัวตนในระบบพนักงาน
เราจะเริ่มแตก domain model ของระบบพนักงานอย่างจริงจัง ว่าอะไรคือ entity อะไรคือ value object

