บทที่ 4 · Part 1 — Foundations and Economics
Ubiquitous Language in Practice
สร้างภาษาที่ใช้จริงใน conversation, examples, model, code และ tests พร้อมจัดการคำเดียวหลายความหมาย
Ubiquitous Language in Practice
ใน incident เดียว ทีม Operations บอกว่า transfer ถูก “ reversed” ทีม Accounting บอกว่าเป็น
“ adjustment” และ provider ส่งสถานะ reversed ซึ่งจริง ๆ หมายถึง payment authorization ถูกคืน
หากทุกคนแปลคำเป็น field เดียว ระบบอาจทำ financial correction ผิดชนิด Ubiquitous Language
ไม่ได้มีไว้ตกแต่ง glossary แต่มีกติกาว่าคำที่ทีมพูดต้องเชื่อมกับ model และ behavior จริง
จบบทนี้คุณจะ
สร้าง Ubiquitous Language ที่มีขอบเขต เก็บทั้ง noun, verb, state, rule และ counterexample ตรวจ language drift ระหว่าง conversation, document, code และ tests และจัดการคำเดียวหลายความหมาย โดยไม่สร้าง enterprise-wide canonical vocabulary
ภาษาที่ใช้ทุกที่ใน Context
DDD Reference และ
Ubiquitous Language ของ Martin Fowler
เน้นว่าภาษาถูกใช้ร่วมกันโดย developer กับ domain experts ทั้งในการพูด การเขียน model และ code
ถ้าเอกสารใช้ Beneficiary แต่ code ใช้ receiverUser และ database ใช้ customer2 การแปลยังเกิด
ทุกครั้งและแต่ละคนอาจแปลไม่เหมือนกัน
Language entry ที่ใช้ได้ควรมี:
| ช่อง | ตัวอย่าง |
|---|---|
| Term | Transfer Intent |
| Context | Customer Transfer |
| Definition | คำขอของลูกค้าให้ส่ง Money ไปยัง Beneficiary ภายใต้เงื่อนไขที่ระบุ |
| Example statement | Customer confirms a Transfer Intent |
| State/verbs | draft, confirm, expire, cancel |
| Counterexample | provider request ไม่ใช่ Intent |
| Owner | Transfer Product + Operations |
| Open question | ยกเลิกได้ถึงเหตุการณ์ใด |
Glossary ที่มีแต่ Transfer: การโอนเงิน ไม่ช่วยตัดสินอะไร ต้องมี statement และ counterexample
เพื่อให้เห็น grammar ของ domain เช่น “ Intent expires” กับ “ Provider Attempt times out”
ภาษามีขอบเขต
คำว่า Account อาจหมายถึง:
- Customer Profile: ความสัมพันธ์กับบุคคล/นิติบุคคล
- Wallet: container ที่ถือสิทธิ์ใช้ funds
- Ledger: หน่วยจัดกลุ่ม entries ตาม accounting semantics
- Identity: credential หรือ login subject
- Provider: merchant account ที่ vendor ออกให้
เป้าหมายไม่ใช่บังคับให้ทุก context ใช้ definition เดียว แต่ให้แต่ละ context สอดคล้องภายใน
และแปลตรง boundary ชื่อที่ qualifier ชัด เช่น LedgerAccountID หรือ ProviderMerchantRef
ลดการอ้าง accountID ที่ไม่มีใครรู้ authority
เส้นประแสดงคำที่ยังคลุมเครือ ส่วนเส้นทึบคือ contract ที่ตั้งใจแปลแล้ว Diagram จึงไม่ได้เสนอ
Account กลาง แต่แสดงว่าทุก boundary ต้องระบุ reference และความหมายที่ผู้รับใช้ได้
Shared Word ไม่ได้แปลว่า Shared Model
คำเดียวกันอาจมี identity reference ร่วมแต่ behavior ต่างกัน การแชร์ struct Customer
ระหว่าง Billing, Risk และ Wallet ทำให้ field ที่ไม่เกี่ยวกับแต่ละ decision รั่วและบังคับ release
ร่วมกัน ให้แชร์ผ่าน contract ที่ตั้งใจหรือ map reference/snapshot ตาม semantics
หา Language จาก Conversation
ฟังคำที่เกิดใน 5 จุด:
- คำที่ผู้เชี่ยวชาญแก้ทันทีเมื่อคนอื่นใช้ผิด
- คำกำกวมอย่าง success, active, balance, cancel, post
- verb ที่เปลี่ยน state เช่น reserve, authorize, settle, reconcile
- policy sentence ที่มี “ถ้า…จึง…” หรือ “ห้าม…เมื่อ…”
- exception และ workaround ที่ไม่มีชื่อแต่ Operations ทำทุกวัน
อย่า normalize เร็วเกินไป หาก Finance พูด reverse entry และ Support พูด undo transfer
ให้ขอ scenario จริงก่อน อาจเป็น action เดียวกัน หรืออาจคนละ context ซึ่งผลทางบัญชีต่างกัน
Language Test
ใช้ test 4 ชั้น:
- Conversation test: Domain Expert เล่า scenario โดยใช้คำเหล่านี้หรือไม่
- Example test: Given/When/Then ระบุ state และ result โดยไม่ใช้คำกำกวมหรือไม่
- Code test: type/method/event สื่อ verb และ rule เดียวกันหรือไม่
- Operation test: dashboard, alert และ runbook ใช้คำที่ชี้ owning context ได้หรือไม่
ตัวอย่างที่ drift:
Conversation: Transfer became indeterminate
Code: status = FAILED
Dashboard: payment_error_total
Runbook: retry transaction
แก้ด้วยการตกลงว่า Indeterminate Execution หมายถึงไม่มี evidence พอจะสรุป success/failure
และ operation ต่อไปคือ Reconcile Execution ไม่ใช่ retry แบบสร้าง side effect ใหม่ทันที
รักษา Language ให้มีชีวิต
เก็บ glossary ใกล้ context owner และ version ร่วมกับ examples/code เมื่อทำได้ แต่ไม่ต้องบังคับ format เดียวทั้งองค์กร ตั้ง owner และ review trigger:
- feature เพิ่ม state transition ใหม่
- incident พบคำไม่ตรงกัน
- provider/standard เปลี่ยน contract
- policy version หรือ jurisdiction เปลี่ยน
- context ถูก split/merge หรือทีม ownership เปลี่ยน
หากคำเก่าเลิกใช้ ให้ deprecate พร้อมเหตุผลและ migration ไม่แก้ history เงียบ เอกสาร contract อาจยังต้องรองรับชื่อเก่าแม้ model ภายในใช้ภาษาใหม่
Language กับ Translation Boundary
Published Language เช่น ISO 20022 message หรือ provider schema ช่วยสื่อสารข้ามองค์กร แต่ไม่ควร
ถูกใช้เป็น model ภายในทั้งหมด ACL แปล external status, identifiers และ amounts เป็น concept
ที่ context เป็นเจ้าของ พร้อมเก็บ source version ถ้า semantics เปลี่ยนได้
คำทาง Compliance ต้องมี Authority
Verified, Eligible, High Risk และ Approved ห้ามกำหนดจากความรู้สึกของ Engineer
ต้องระบุ policy owner, source, version, jurisdiction และ effective date Language ช่วยทำให้การตัดสิน
trace ได้ แต่ไม่แทน Legal/Risk interpretation
แบบฝึกปฏิบัติ: Balance Language Clinic
เก็บคำว่า Balance จาก 4 ฝ่าย: Customer Support, Wallet, Accounting และ Portal แล้วกรอก:
Statement actually spoken:
Meaning in this context:
Time axis / freshness:
Authoritative source:
Decision allowed:
Decision forbidden:
Example:
Counterexample:
Preferred qualified term:
Owner:
ต้องได้อย่างน้อย 3 terms เช่น Posted Balance, Available Funds, Displayed Balance
แล้วเขียน scenario ที่ทั้ง 3 ค่าไม่เท่ากันเพื่อพิสูจน์ว่าความแตกต่างมีผลจริง
รายการตรวจสอบ
- Language มี boundary และ owner
- เก็บ noun, verb, state, rule และ exception
- ทุก term มี statement กับ counterexample
- คำเดียวต่าง context ไม่ถูกแชร์ model อัตโนมัติ
- Conversation, examples, code และ operation ใช้ความหมายสอดคล้อง
- External/standard language ถูกแปลที่ boundary
- Language drift มี review trigger และ deprecation path
สรุปบทนี้
Ubiquitous Language คือระบบ feedback ระหว่างคนกับ model ไม่ใช่พจนานุกรมกลาง เมื่อคำถูกใช้จริง ใน scenario, code, tests และ operation ความกำกวมจะปรากฏเร็วขึ้น ภาษาที่ดีมีขอบเขต ยอมรับ polysemy และเปลี่ยนได้เมื่อความเข้าใจเปลี่ยน
อ่านเพิ่มเติม
- Ubiquitous Language — Martin Fowler
- DDD Reference — Ubiquitous Language และ Bounded Context
- Monzo: How We Calculate Balances — first-party case เรื่อง balance definitions