รูปแบบโดเมนที่หลากหลาย - พฤติกรรมนั้นเข้ากันได้อย่างไร


84

ในการอภิปรายเกี่ยวกับโมเดลโดเมน 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 ต่ออุตสาหกรรม ความไม่รู้ที่คงอยู่และการหาแหล่งเหตุการณ์ทำให้เกิดความสับสนและฉันคิดว่าปรัชญาเช่นนั้นที่ยึดมันกลับมาจากการยอมรับที่กว้างขึ้น แต่ถ้าฉันต้องทำรหัสนี้ซ้ำอีกครั้งกับสิ่งที่ฉันได้เรียนรู้ฉันคิดว่ามันจะเป็นดังนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันยังคงยินดีต้อนรับคำตอบใด ๆ สำหรับโพสต์นี้ (ใช้งานมาก) ที่ให้รหัสแนวทางปฏิบัติที่ดีที่สุดสำหรับรูปแบบโดเมนที่ถูกต้อง


6
"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"ทั้งหมดทฤษฎีปรัชญาสิทธิที่จะตกพื้นเมื่อคุณบอกพวกเขา "เอนทิตี" ในศัพท์แสงของเอนทิตีกรอบไม่เหมือนกับ "เอนทิตี" เหมือนกับใน "โดเมนโมเดล"
Federico Berasategui

ฉันตกลงกับการทำสำเนาโดเมนของฉันเป็น DTO โดยใช้เครื่องมืออัตโนมัติเช่น Automapper ถ้าเป็นสิ่งที่ต้องทำ ฉันแค่ไม่แน่ใจว่าควรจะเป็นอย่างไรในตอนท้ายของวัน
RJB

16
ฉันจะแนะนำให้คุณดูจิมมี่ Bogard ของ NDC 2012 เซสชั่น "รุ่นหัตถกรรมชั่วร้ายโดเมน" บนVimeo เขาอธิบายว่าโดเมนใดควรเป็นโดเมนที่มีมากมายและวิธีการนำไปใช้ในชีวิตจริงโดยมีพฤติกรรมในองค์กรของคุณ ตัวอย่างเป็นจริงมากและทั้งหมดใน C #
Alexey Zimarev

ขอบคุณฉันผ่านวิดีโอไปครึ่งทางแล้วมันก็สมบูรณ์แบบมาก ผมรู้ว่าถ้าเรื่องนี้เป็นเรื่องที่ผิดมีคนที่จะเป็น "สิทธิ" ตอบออกมีบาง ....
RJB

2
ฉันต้องการความรักสำหรับ Java ด้วย: /
uylmz

คำตอบ:


59

คำตอบที่เป็นประโยชน์มากที่สุดได้รับจาก Alexey Zimarev และได้รับอย่างน้อย 7 upvotes ก่อนที่ผู้ดำเนินรายการย้ายมันไปเป็นความคิดเห็นด้านล่างคำถามเดิมของฉัน ....

คำตอบของเขา:

ฉันอยากจะแนะนำให้คุณดูเซสชั่น "งานหัตถกรรม Wicked Domain Models" ของ Jimmy Bogard ใน Vimeo เขาอธิบายว่าโดเมนใดควรเป็นโดเมนที่มีมากมายและวิธีการนำไปใช้ในชีวิตจริงโดยมีพฤติกรรมในหน่วยงานของคุณ ตัวอย่างเป็นจริงมากและทั้งหมดใน C #

http://vimeo.com/43598193

ฉันใช้บันทึกย่อเพื่อสรุปวิดีโอเพื่อประโยชน์ของทั้งสองทีมและเพื่อให้รายละเอียดเพิ่มเติมเล็กน้อยในโพสต์นี้ (วิดีโอยาวหนึ่งชั่วโมง แต่คุ้มทุกนาทีถ้าคุณมีเวลา Jimmy Bogard สมควรได้รับเครดิตมากมายสำหรับคำอธิบายของเขา)

  • "สำหรับแอปพลิเคชั่นส่วนใหญ่ ... เราไม่ทราบว่าพวกเขากำลังจะซับซ้อนเมื่อเราเริ่มต้นพวกเขากลายเป็นอย่างนั้น"
    • ความซับซ้อนจะเพิ่มขึ้นตามธรรมชาติเมื่อมีการเพิ่มรหัสและข้อกำหนด แอปพลิเคชันสามารถเริ่มต้นได้ง่ายมากเช่น CRUD แต่พฤติกรรม / กฎสามารถกลายเป็นสิ่งที่น่าสนใจ
    • "สิ่งที่ดีคือเราไม่ต้องเริ่มต้นที่ซับซ้อนเราสามารถเริ่มต้นด้วยโมเดลโดเมนโลหิตจางนั่นเป็นเพียงแค่ถุงสมบัติและด้วยเทคนิคการรีแฟคเตอร์มาตรฐานเราสามารถก้าวไปสู่โมเดลโดเมนที่แท้จริง"
  • รูปแบบโดเมน = วัตถุธุรกิจ พฤติกรรมโดเมน = กฎเกณฑ์ทางธุรกิจ
  • พฤติกรรมมักจะซ่อนอยู่ในแอปพลิเคชันซึ่งสามารถอยู่ใน PageLoad, Button1_Click หรือบ่อยครั้งในคลาสตัวช่วยเช่น 'FooManager' หรือ 'FooService'
  • กฎทางธุรกิจที่แยกต่างหากจากวัตถุโดเมน "กำหนดให้เราต้องจำ" กฎเหล่านั้น
    • ในตัวอย่างส่วนตัวของฉันข้างต้นกฎข้อหนึ่งของธุรกิจคือ WorkItem.StatusHistory.Add () เราไม่เพียงแค่เปลี่ยนสถานะ แต่เรากำลังเก็บถาวรเพื่อการตรวจสอบ
  • พฤติกรรมโดเมน "กำจัดข้อผิดพลาดในแอปพลิเคชันได้ง่ายกว่าการเขียนการทดสอบมากมาย" การทดสอบกำหนดให้คุณต้องรู้เพื่อเขียนการทดสอบเหล่านั้น พฤติกรรมโดเมนให้สิทธิ์แก่คุณในเส้นทางที่จะทดสอบ
  • บริการโดเมนคือ "คลาสตัวช่วยในการประสานงานกิจกรรมระหว่างเอนทิตีโมเดลโดเมนที่ต่างกัน"
    • บริการโดเมน! = พฤติกรรมของโดเมน เอนทิตีมีพฤติกรรมบริการโดเมนเป็นเพียงตัวกลางระหว่างเอนทิตี
  • วัตถุโดเมนไม่ควรมีโครงสร้างพื้นฐานที่ต้องการ (เช่น IOfferCalculatorService) บริการโครงสร้างพื้นฐานควรส่งผ่านไปยังรูปแบบโดเมนที่ใช้
  • แบบจำลองโดเมนควรเสนอที่จะบอกคุณว่าพวกเขาสามารถทำอะไรได้บ้างและพวกเขาควรจะทำสิ่งเหล่านั้นได้
  • คุณสมบัติของรุ่นโดเมนควรได้รับการปกป้องด้วย setters ส่วนตัวเพื่อให้เพียงรูปแบบสามารถตั้งค่าคุณสมบัติของตัวเองผ่านพฤติกรรมของตัวเอง มิฉะนั้นจะเป็น "promiscuous"
  • วัตถุโมเดลโดเมน Anemic ที่เป็นเพียงคุณสมบัติถุงสำหรับ ORM เป็นเพียง "แผ่นไม้อัดบาง ๆ - เป็นรุ่นที่พิมพ์ลงบนฐานข้อมูล"
    • "อย่างไรก็ตามมันง่ายที่จะนำแถวฐานข้อมูลไปสู่วัตถุนั่นคือสิ่งที่เรามี"
    • 'แบบจำลองวัตถุที่คงทนถาวรส่วนใหญ่เป็นแบบนั้น สิ่งที่สร้างความแตกต่างของโมเดลโดเมนโลหิตจางเมื่อเทียบกับแอปพลิเคชันที่ไม่มีพฤติกรรมจริง ๆ คือถ้าวัตถุมีกฎเกณฑ์ทางธุรกิจ แต่ไม่พบกฎเหล่านั้นในรูปแบบโดเมน '
  • "สำหรับแอปพลิเคชันจำนวนมากไม่จำเป็นต้องสร้างเลเยอร์ตรรกะแอปพลิเคชันธุรกิจจริง ๆ จริง ๆ เป็นเพียงบางสิ่งที่สามารถพูดคุยกับฐานข้อมูลและอาจเป็นวิธีง่ายๆในการนำเสนอข้อมูลที่อยู่ในนั้น"
    • ดังนั้นในคำอื่น ๆ ถ้าสิ่งที่คุณทำคือ CRUD โดยไม่มีวัตถุทางธุรกิจพิเศษหรือกฎพฤติกรรมคุณไม่จำเป็นต้อง DDD

โปรดแสดงความคิดเห็นกับจุดอื่น ๆ ที่คุณรู้สึกว่าควรจะรวมหรือถ้าคุณคิดว่าบันทึกเหล่านี้ใด ๆ ที่ออกเครื่องหมาย พยายามที่จะพูดโดยตรงหรือถอดความมากที่สุด


วิดีโอที่ยอดเยี่ยมโดยเฉพาะอย่างยิ่งเพื่อดูว่า refactoring ทำงานอย่างไรในเครื่องมือ มีหลายสิ่งที่เกี่ยวกับการห่อหุ้มวัตถุโดเมนที่เหมาะสม (เพื่อให้แน่ใจว่าสอดคล้องกัน) เขาทำงานได้อย่างยอดเยี่ยมในการบอกกฎเกณฑ์ทางธุรกิจเกี่ยวกับข้อเสนอสมาชิกและอื่น ๆ เขากล่าวถึงคำที่ไม่เปลี่ยนแปลงสองครั้ง (ซึ่งเป็นการสร้างแบบจำลองโดเมนตามสัญญา) ฉันหวังว่ารหัส. net จะสื่อสารได้ดีขึ้นว่าอะไรคือกฎเกณฑ์ทางธุรกิจที่เป็นทางการเนื่องจากการเปลี่ยนแปลงเหล่านั้นและคุณต้องรักษาไว้
Fuhrmanator

6

ไม่สามารถตอบคำถามของคุณได้เนื่องจากตัวอย่างของคุณผิด โดยเฉพาะเพราะไม่มีพฤติกรรม อย่างน้อยไม่ได้อยู่ในพื้นที่ของโดเมนของคุณ ตัวอย่างของAddStatusUpdateวิธีการไม่ใช่ตรรกะโดเมน แต่ตรรกะที่ใช้โดเมนนั้น ตรรกะชนิดนั้นเหมาะสมที่จะอยู่ในบริการบางประเภทที่จัดการกับคำขอภายนอก

ตัวอย่างเช่นถ้ามีความต้องการที่เฉพาะเจาะจงรายการงานสามารถมีสถานะที่เฉพาะเจาะจงหรือว่ามันจะมีเพียงสถานะ N แล้วว่าเป็นตรรกะโดเมนและควรเป็นส่วนหนึ่งของการอย่างใดอย่างหนึ่งWorkItemหรือStatusHistoryเป็นวิธีการที่

เหตุผลที่ทำให้คุณสับสนเพราะคุณกำลังพยายามนำแนวทางไปใช้กับโค้ดที่ไม่ต้องการ แบบจำลองโดเมนมีความเกี่ยวข้องเฉพาะในกรณีที่คุณมีตรรกะของโดเมนที่ซับซ้อนจำนวนมาก เช่น. ตรรกะที่ทำงานกับหน่วยงานเองและเกิดจากความต้องการ หากรหัสเกี่ยวกับการจัดการเอนทิตีจากข้อมูลภายนอกนั่นอาจไม่ใช่ตรรกะโดเมน แต่ช่วงเวลาที่คุณได้รับจำนวนมากifขึ้นอยู่กับข้อมูลและเอนทิตีที่คุณทำงานด้วยนั่นคือตรรกะของโดเมน

หนึ่งในปัญหาของการสร้างแบบจำลองโดเมนที่แท้จริงคือการจัดการข้อกำหนดที่ซับซ้อน และด้วยเหตุนี้พลังที่แท้จริงและผลประโยชน์ที่แท้จริงจึงไม่สามารถแสดงบนโค้ดอย่างง่ายได้ คุณต้องการเอนทิตีจำนวนมากที่มีข้อกำหนดมากมายรอบตัวพวกเขาเพื่อรับประโยชน์อย่างแท้จริง อีกครั้งตัวอย่างของคุณง่ายเกินไปสำหรับรุ่นโดเมนที่จะส่องแสงอย่างแท้จริง

ในที่สุดสิ่ง OT ที่ฉันจะพูดถึงก็คือรูปแบบโดเมนที่แท้จริงที่มีการออกแบบ OOP จริงจะยากที่จะคงอยู่โดยใช้ Entity Framework ในขณะที่ ORMs ได้รับการออกแบบด้วยการทำแผนที่โครงสร้าง OOP ที่แท้จริงไปยังวัตถุเชิงสัมพันธ์ แต่ก็ยังมีปัญหามากมายและโมเดลเชิงสัมพันธ์มักจะรั่วไหลไปยังโมเดล OOP แม้ว่า nHibernate ซึ่งฉันคิดว่ามีประสิทธิภาพมากกว่า EF ก็อาจเป็นปัญหาได้


จุดที่ดี AddStatusUpdate จะอยู่ที่ไหนใน Data หรือโครงการอื่นใน Infrastrcture ตัวอย่างของพฤติกรรมใด ๆ ที่อาจเป็นของทฤษฎีใน WorkItem คืออะไร รหัส psuedo ใด ๆ หรือจำลองจะได้รับการชื่นชมอย่างมาก ตัวอย่างของฉันง่ายจริงที่จะอ่านง่ายขึ้น มีเอนทิตีอื่น ๆ และตัวอย่างเช่น AddStatusUpdate มีพฤติกรรมพิเศษบางอย่าง - จริง ๆ แล้วมันใช้ชื่อหมวดหมู่สถานะและหากหมวดหมู่นั้นไม่มีอยู่หมวดหมู่นั้นจะถูกสร้างขึ้น
RJB

@RJB อย่างที่ฉันบอกว่า AddStatusUpdate เป็นรหัสที่ใช้โดเมน ดังนั้นเว็บเซอร์วิซหรือแอพพลิเคชั่นบางประเภทที่ใช้คลาสโดเมน และอย่างที่ฉันบอกไว้คุณไม่สามารถคาดหวัง mockup หรือ pseudocode ใด ๆ ได้เพราะคุณจะต้องทำให้โครงการทั้งหมดมีความซับซ้อนมากพอที่จะแสดงประโยชน์ที่แท้จริงของรูปแบบโดเมน OOP
ร่าเริง

5

สมมติฐานของคุณที่รวมเอาตรรกะทางธุรกิจของคุณที่เกี่ยวข้องกับ WorkItem เข้ากับ "บริการไขมัน" เป็นรูปแบบการต่อต้านโดยธรรมชาติซึ่งฉันจะโต้แย้งไม่จำเป็น

โดยไม่คำนึงถึงความคิดของคุณเกี่ยวกับโมเดลโดเมนโลหิตจางรูปแบบมาตรฐานและการปฏิบัติตามแบบฉบับของแอปพลิเคชัน Line of Business .NET สนับสนุนวิธีการทำทรานแซคชันแบบเลเยอร์ที่ประกอบด้วยองค์ประกอบต่างๆ พวกเขาสนับสนุนให้แยกตรรกะทางธุรกิจออกจากรูปแบบโดเมนโดยเฉพาะเพื่ออำนวยความสะดวกในการสื่อสารของรูปแบบโดเมนทั่วไปทั่วส่วนประกอบ NET อื่น ๆ รวมทั้งส่วนประกอบในกองเทคโนโลยีที่แตกต่างกันหรือข้ามระดับทางกายภาพ

ตัวอย่างหนึ่งของสิ่งนี้คือบริการเว็บ SOAP แบบ. NET ที่สื่อสารกับแอปพลิเคชันไคลเอนต์ Silverlight ที่เกิดขึ้นกับ DLL ที่มีชนิดข้อมูลอย่างง่าย โครงการเอนทิตีโดเมนนี้สามารถสร้างขึ้นในแอสเซมบลี. NET หรือแอสเซมบลี Silverlight โดยที่ส่วนประกอบ Silverlight ที่สนใจที่มี DLL นี้จะไม่ได้รับพฤติกรรมของวัตถุที่อาจขึ้นอยู่กับคอมโพเนนต์ที่พร้อมใช้งานสำหรับบริการเท่านั้น

นี่เป็นรูปแบบที่ได้รับการยอมรับและได้รับการยอมรับจาก Microsoft และในความเห็นของฉันไม่ใช่มืออาชีพ แต่แล้วรูปแบบวัตถุที่กำหนดพฤติกรรมของตัวเองก็ไม่จำเป็นต้องเป็นรูปแบบการต่อต้าน หากคุณไปข้างหน้าด้วยการออกแบบนี้เป็นการดีที่สุดที่จะตระหนักและเข้าใจถึงข้อ จำกัด และจุดปวดที่คุณอาจพบหากคุณจำเป็นต้องทำงานร่วมกับส่วนประกอบอื่น ๆ ที่จำเป็นต้องดูโมเดลโดเมนของคุณ ในกรณีนั้นบางทีคุณอาจต้องการให้นักแปลแปลงโมเดลโดเมนสไตล์เชิงวัตถุของคุณเป็นวัตถุข้อมูลแบบง่ายที่ไม่ได้เปิดเผยวิธีการทำงานบางอย่าง


1
1) คุณจะแยกตรรกะทางธุรกิจออกจากรูปแบบโดเมนได้อย่างไร มันเป็นโดเมนที่ตรรกะทางธุรกิจนี้อาศัยอยู่ เอนทิตีในโดเมนนั้นกำลังประมวลผลพฤติกรรมที่เกี่ยวข้องกับตรรกะทางธุรกิจนั้น โลกแห่งความจริงไม่มีบริการและไม่มีอยู่ในหัวของผู้เชี่ยวชาญด้านโดเมน 2) ส่วนประกอบใด ๆ ที่ต้องการรวมเข้ากับคุณจำเป็นต้องสร้างรูปแบบโดเมนของตัวเองเนื่องจากความต้องการจะแตกต่างกันและจะมีมุมมองที่แตกต่างกันในรูปแบบโดเมนของคุณ มันเป็นเรื่องระยะยาวที่คุณสามารถสร้างรูปแบบโดเมนที่สามารถแบ่งปันได้
Stefan Billiet

1
@StefanBilliet สิ่งเหล่านี้เป็นจุดที่ดีเกี่ยวกับการเข้าใจผิดของโมเดลโดเมนสากล แต่เป็นไปได้ในส่วนประกอบที่ง่ายกว่าและการโต้ตอบกับส่วนประกอบตามที่ฉันเคยทำมาก่อน ความคิดเห็นของฉันคือตรรกะการแปลระหว่างแบบจำลองโดเมนสามารถสร้างรหัสที่น่าเบื่อและรหัสสำเร็จรูปได้มากมายและหากสามารถหลีกเลี่ยงได้อย่างปลอดภัยแล้วนั่นอาจเป็นตัวเลือกการออกแบบที่ดี
maple_shaft

1
พูดตรงไปตรงมาฉันคิดว่าทางเลือกการออกแบบที่ดีเพียงอย่างเดียวคือแบบจำลองที่ผู้เชี่ยวชาญด้านธุรกิจสามารถให้เหตุผลได้ คุณกำลังสร้างแบบจำลองของโดเมนเพื่อให้ธุรกิจใช้เพื่อแก้ปัญหาบางอย่างภายในโดเมนนั้น การแยกพฤติกรรมจากเอนทิตีของโดเมนออกเป็นบริการทำให้ยากสำหรับทุกคนที่เกี่ยวข้องเพราะคุณต้องทำแผนที่สิ่งที่ผู้เชี่ยวชาญของโดเมนบอกกับรหัสบริการที่แทบจะไม่มีความคล้ายคลึงกับการสนทนาปัจจุบัน จากประสบการณ์ของฉันคุณเสียเวลาไปกับมันมากกว่าการพิมพ์สำเร็จรูป ไม่ได้บอกว่าไม่มีวิธีแก้ไขเกี่ยวกับรหัสหลักสูตรแหล่งข้อมูล
Stefan Billiet

@StefanBilliet ในโลกที่สมบูรณ์แบบฉันเห็นด้วยกับคุณที่ผู้เชี่ยวชาญทางธุรกิจมีเวลานั่งคุยกับนักพัฒนา ความเป็นจริงของอุตสาหกรรมซอฟต์แวร์คือผู้เชี่ยวชาญทางธุรกิจไม่มีเวลาหรือความสนใจในการมีส่วนร่วมในระดับนี้หรือแย่กว่านั้น แต่นักพัฒนาคาดว่าจะคิดออกด้วยคำแนะนำที่คลุมเครือเท่านั้น
maple_shaft

จริง แต่นั่นไม่ใช่เหตุผลที่จะยอมรับความเป็นจริงนั้น เพื่อดำเนินการต่อในการแสวงหาคือการเสียเวลา (และอาจมีชื่อเสียง) ของนักพัฒนาและเงินของลูกค้า กระบวนการที่ฉันอธิบายคือความสัมพันธ์ที่ต้องสร้างขึ้นตามกาลเวลา ใช้ความพยายามอย่างมาก แต่ให้ผลลัพธ์ที่ดีกว่ามาก มีเหตุผลที่ "ภาษาแพร่หลาย" มักจะถูกมองว่าเป็นสิ่งสำคัญที่สุดของ DDD
Stefan Billiet

5

ฉันรู้ว่าคำถามนี้ค่อนข้างเก่าดังนั้นคำตอบนี้สำหรับลูกหลาน ฉันต้องการที่จะตอบด้วยตัวอย่างที่เป็นรูปธรรมแทนที่จะเป็นหนึ่งในทฤษฎี

สรุปแค็ปซูล "การเปลี่ยนแปลงสถานะของรายการงาน" ในWorkItemคลาสดังนี้:

public SomeStatusUpdateType Status { get; private set; }

public void ChangeStatus(SomeStatusUpdateType status)
{
    // Maybe we designed this badly at first ;-)
    Status = status;       
}

ตอนนี้WorkItemชั้นเรียนของคุณมีหน้าที่รับผิดชอบในการรักษาตนเองในสถานะทางกฎหมาย อย่างไรก็ตามการใช้งานนั้นค่อนข้างอ่อน WorkItemเจ้าของผลิตภัณฑ์ที่ต้องการความเป็นมาของการปรับปรุงสถานะทั้งหมดที่ทำกับที่

เราเปลี่ยนเป็นอะไรแบบนี้:

private ICollection<SomeStatusUpdateType> StatusUpdates { get; private set; }
public SomeStatusUpdateType Status => StatusUpdates.OrderByDescending(s => s.CreatedOn).FirstOrDefault();

public void ChangeStatus(SomeStatusUpdateType status)
{
    // Better...
    StatusUpdates.Add(status);       
}

การใช้งานมีการเปลี่ยนแปลงอย่างมาก แต่ผู้เรียกใช้ChangeStatusเมธอดไม่ทราบรายละเอียดการใช้งานพื้นฐานและไม่มีเหตุผลที่จะเปลี่ยนแปลงตัวเอง

นี่คือตัวอย่างของเอนทิตีโมเดลโดเมนที่สมบูรณ์แบบ IMHO

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.