ในการอภิปรายเกี่ยวกับโมเดลโดเมน Rich and Anemic อินเทอร์เน็ตเต็มไปด้วยคำแนะนำทางปรัชญา แต่ย่อมาจากตัวอย่างที่เชื่อถือได้ วัตถุประสงค์ของคำถามนี้คือการหาแนวทางที่ชัดเจนและตัวอย่างที่เป็นรูปธรรมของโมเดลการออกแบบที่ขับเคลื่อนด้วยโดเมนที่เหมาะสม (นึกคิดใน C #.)
สำหรับตัวอย่างในโลกแห่งความจริงการใช้ DDD นี้ดูเหมือนจะผิด:
โดเมน WorkItem รุ่นด้านล่างไม่มีอะไรนอกจากถุงคุณสมบัติซึ่ง Entity Framework ใช้สำหรับฐานข้อมูลรหัสแรก ต่อฟาวเลอร์ก็เป็นโรคโลหิตจาง
เห็นได้ชัดว่าชั้น WorkItemService เป็นความเข้าใจผิดทั่วไปของบริการโดเมน มันมีพฤติกรรม / ตรรกะทางธุรกิจทั้งหมดสำหรับ WorkItem ต่อ Yemelyanov และคนอื่น ๆ ก็เป็นขั้นตอน (หน้า 6)
ดังนั้นถ้าด้านล่างผิดฉันจะทำให้ถูกต้องได้อย่างไร
พฤติกรรมเช่นAddStatusUpdateหรือCheckoutควรเป็นของคลาส WorkItem ที่ถูกต้องหรือไม่
แบบจำลอง WorkItem ควรพึ่งพาอะไร?
public class WorkItemService : IWorkItemService {
private IUnitOfWorkFactory _unitOfWorkFactory;
//using Unity for dependency injection
public WorkItemService(IUnitOfWorkFactory unitOfWorkFactory) {
_unitOfWorkFactory = unitOfWorkFactory;
}
public void AddStatusUpdate(int workItemId, int statusId) {
using (var unitOfWork = _unitOfWorkFactory.GetUnitOfWork<IWorkItemUnitOfWork>()) {
var workItemRepo = unitOfWork.WorkItemRepository;
var workItemStatusRepo = unitOfWork.WorkItemStatusRepository;
var workItem = workItemRepo.Read(wi => wi.Id == workItemId).FirstOrDefault();
if (workItem == null)
throw new ArgumentException(string.Format(@"The provided WorkItem Id '{0}' is not recognized", workItemId), "workItemId");
var status = workItemStatusRepo.Read(s => s.Id == statusId).FirstOrDefault();
if (status == null)
throw new ArgumentException(string.Format(@"The provided Status Id '{0}' is not recognized", statusId), "statusId");
workItem.StatusHistory.Add(status);
workItemRepo.Update(workItem);
unitOfWork.Save();
}
}
}
(ตัวอย่างนี้ทำให้ง่ายต่อการอ่านมากขึ้นรหัสยังคงเป็น clunky แน่นอนเพราะมันเป็นความพยายามที่สับสน แต่พฤติกรรมโดเมนคือ: อัปเดตสถานะโดยการเพิ่มสถานะใหม่ให้กับประวัติศาสตร์ที่เก็บถาวรในที่สุดฉันเห็นด้วยกับคำตอบอื่น ๆ นี้ สามารถจัดการได้โดย CRUD)
ปรับปรุง
@AlexeyZimarev ให้คำตอบที่ดีที่สุดวิดีโอที่สมบูรณ์แบบเกี่ยวกับเรื่องใน C # โดย Jimmy Bogard แต่เห็นได้ชัดว่ามันถูกย้ายไปเป็นความคิดเห็นด้านล่างเพราะมันไม่ได้ให้ข้อมูลมากไปกว่าลิงก์ ฉันมีร่างคร่าวๆของการสรุปวิดีโอในคำตอบของฉันด้านล่าง โปรดแสดงความคิดเห็นเกี่ยวกับคำตอบด้วยการแก้ไขใด ๆ วิดีโอยาวหนึ่งชั่วโมง แต่ดูคุ้มค่ามาก
อัพเดท - 2 ปีต่อมา
ฉันคิดว่ามันเป็นสัญญาณบ่งบอกถึงการเติบโตของการกำเนิด DDD ที่แม้หลังจากศึกษาเป็นเวลา 2 ปีฉันก็ยังไม่สามารถสัญญาได้ว่าฉันรู้ "วิธีที่ถูกต้อง" ในการทำมัน ภาษาที่ใช้แพร่หลายรากเหง้ารวมและแนวทางการออกแบบที่ขับเคลื่อนด้วยพฤติกรรมเป็นการสนับสนุนที่มีค่าของ DDD ต่ออุตสาหกรรม ความไม่รู้ที่คงอยู่และการหาแหล่งเหตุการณ์ทำให้เกิดความสับสนและฉันคิดว่าปรัชญาเช่นนั้นที่ยึดมันกลับมาจากการยอมรับที่กว้างขึ้น แต่ถ้าฉันต้องทำรหัสนี้ซ้ำอีกครั้งกับสิ่งที่ฉันได้เรียนรู้ฉันคิดว่ามันจะเป็นดังนี้:
ฉันยังคงยินดีต้อนรับคำตอบใด ๆ สำหรับโพสต์นี้ (ใช้งานมาก) ที่ให้รหัสแนวทางปฏิบัติที่ดีที่สุดสำหรับรูปแบบโดเมนที่ถูกต้อง
"I don't want to duplicate all my entities into DTOs simply because I don't need it and it violates DRY, and I also don't want my client application to take a dependency on EntityFramework.dll"
ทั้งหมดทฤษฎีปรัชญาสิทธิที่จะตกพื้นเมื่อคุณบอกพวกเขา "เอนทิตี" ในศัพท์แสงของเอนทิตีกรอบไม่เหมือนกับ "เอนทิตี" เหมือนกับใน "โดเมนโมเดล"