บทนำ
เมื่อพูดถึงคำว่า Repository นักพัฒนาจำนวนมากมักจะนึกถึงไฟล์ที่มีแต่ create, read, update, delete
แต่ใน Domain-Driven Design (DDD) นั้น Repository มีความหมายและบทบาทที่ลึกกว่านั้นมาก
บทความตอนนี้จะอธิบายว่า Repository ใน DDD คืออะไร, แตกต่างจาก CRUD แบบทั่วไปอย่างไร และควรออกแบบอย่างไรให้ Domain สะอาดและยั่งยืน โดยใช้ตัวอย่าง ระบบพนักงาน (Employee Management System)
Repository ใน Domain-Driven Design คืออะไร
Repository คือ abstraction ที่ทำหน้าที่:
- ทำให้ Domain รู้สึกเหมือนกำลังทำงานกับ object ในหน่วยความจำ
- ซ่อนรายละเอียดของ database, ORM, API หรือ storage ใด ๆ
- ให้ Domain Model โฟกัสกับ business logic โดยไม่ผูกกับเทคโนโลยี
Repository คือ “ภาพลวงตา” ที่ทำให้ Domain คิดว่า object ยังมีชีวิตอยู่ตลอดเวลา
Repository ไม่ใช่ DAO และไม่ใช่ CRUD
ความเข้าใจผิดที่พบบ่อยคือ:
Repository = DAO + CRUD
ใน DDD แนวคิดนี้ ผิดโดยหลักการ
เปรียบเทียบ Repository vs CRUD
| หัวข้อ | Repository (DDD) | CRUD / DAO |
|---|---|---|
| มุมมอง | Domain-centric | Database-centric |
| คืนค่า | Aggregate | Record / Row |
| เมธอด | ใช้ภาษา Domain | ใช้ภาษาเทคนิค |
| ผู้ใช้งาน | Domain / Application Service | Controller / Service |
Repository ถูกออกแบบมาเพื่อ Aggregate ไม่ใช่ table
ตัวอย่างจากระบบพนักงาน
Aggregate: Employee
สิ่งที่ Repository ควรมี:
- findById(EmployeeId id)
- save(Employee employee)
- findActiveEmployees()
สิ่งที่ Repository ไม่ควรมี:
- updateSalaryById()
- deleteByDepartmentId()
- findBySalaryGreaterThan() (ถ้าไม่ใช่ภาษา Domain)
ถ้า method ไหนอ่านแล้วไม่ใช่ภาษาของธุรกิจ นั่นคือสัญญาณเตือน
Repository ทำงานร่วมกับ Application Service อย่างไร
Repository ไม่ควรถูกเรียกโดย UI หรือ Controller โดยตรง
โครงสร้างที่เหมาะสมคือ:
UI / API
↓
Application Service / Use Case
↓
Repository
↓
Domain Model (Aggregate)
Application Service:
- ตัดสินใจว่า use case ต้องโหลดอะไร
- เรียก Repository
- ส่ง Aggregate ให้ Domain ทำงานต่อ
ทำไม Repository ควรคืนค่าเป็น Aggregate
เพราะ:
- Aggregate คือ boundary ของ consistency
- Business rule ถูกคุมอยู่ภายใน
- ป้องกันการแก้ state แบบข้ามกฎ
ถ้า Repository คืนค่าเป็น DTO หรือ Map:
- Domain จะอ่อนแรง
- Invariant จะถูกละเมิดง่าย
- Logic จะไหลไปอยู่ผิดที่
Repository กับ Infrastructure
ใน DDD:
- Interface ของ Repository อยู่ใน Domain Layer
- Implementation อยู่ใน Infrastructure Layer
Domain:
- ไม่รู้จัก database
- ไม่รู้จัก ORM
- ไม่รู้จัก framework
Infrastructure:
- แปลง Aggregate ↔ persistence model
- จัดการ transaction ระดับเทคนิค
สัญญาณว่า Repository ของคุณเริ่มผิดทาง
- Repository มี method เยอะผิดปกติ
- Method name เต็มไปด้วยเงื่อนไขเชิง query
- Business logic เริ่มไหลเข้า Repository
- Aggregate กลายเป็น data holder
ถ้าเห็นสัญญาณเหล่านี้ แปลว่าคุณกำลังหลุดจาก DDD
สรุป
- Repository ใน Domain-Driven Design ไม่ใช่ CRUD
- ถูกออกแบบเพื่อ Aggregate ไม่ใช่ table
- ใช้ภาษา Domain ไม่ใช่ภาษา database
- ช่วยปกป้อง business rule และโครงสร้างของ Domain
ในตอนถัดไป เราจะพูดถึง Domain Event – เมื่อระบบธุรกิจขับเคลื่อนด้วยเหตุการณ์ ซึ่งเป็นก้าวสำคัญของระบบที่ scale ได้จริง

