เมื่อใดควรรูทรวมโดยรวมมี AR อื่น (และเมื่อใดควรจะรวม)


15

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

ฉันกำลังออกแบบแอพพลิเคชั่นตามแนวทาง DDD และสงสัยว่าฉันสามารถทำตามแนวทางใดได้บ้างเพื่อพิจารณาว่ารูทการรวมควรมี AR อื่นหรือไม่ถ้าพวกมันควรจะแยกจากกัน

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

แอปพลิเคชันเป็นเว็บไคลเอ็นต์ที่เรียกใช้เซิร์ฟเวอร์แบ็คเอนด์ที่เปิดเผยผ่านส่วนต่อประสานบริการ RESTful การผ่านครั้งแรกของฉันในการสร้าง URL ที่ใช้งานง่ายและอ่านได้ทำให้เกิดจุดปลายสองจุดต่อไปนี้:

http://myhost/employees/{id}/clockin
http://myhost/employees/{id}/clockout

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

บนเซิร์ฟเวอร์ฉันมี ApplicationService ที่ให้บริการ API แนวคิดแรกของฉันสำหรับวิธี ClockIn เป็นดังนี้:

public void ClockIn(String id)
{
    var employee = EmployeeRepository.FindById(id);

    if (employee == null) throw SomeException();

    employee.ClockIn();

    EmployeeRepository.Save();
}

สิ่งนี้จะดูตรงไปตรงมาจนกว่าเราจะทราบว่าข้อมูลบัตรลงเวลาของพนักงานนั้นได้รับการปรับปรุงเป็นรายการธุรกรรม ซึ่งหมายความว่าทุกครั้งที่ฉันเรียก ClockIn หรือ ClockOut ฉันไม่ได้เปลี่ยนสถานะของพนักงานโดยตรง แต่ฉันจะเพิ่มรายการใหม่ลงใน TimeSheet ของพนักงานแทน สถานะปัจจุบันของพนักงาน (สัญญาณนาฬิกาในหรือไม่) มาจากรายการล่าสุดใน TimeSheet

ดังนั้นถ้าฉันไปด้วยรหัสที่แสดงด้านบนที่เก็บของฉันต้องยอมรับว่าคุณสมบัติที่คงอยู่ของพนักงานไม่เปลี่ยนแปลง แต่มีการเพิ่มรายการใหม่ลงใน TimeSheet ของพนักงานและทำการแทรกลงในแหล่งข้อมูล

ในทางกลับกัน (และนี่คือคำถามสุดท้ายของการโพสต์), TimeSheet ดูเหมือนว่าเป็น Aggregate Root และมีตัวตน (ID พนักงานและระยะเวลา) และฉันสามารถใช้ตรรกะเดียวกันกับ TimeSheet ได้อย่างง่ายดาย (employeeId)

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


ฉันได้แก้ไข / อัพเดทโพสต์เพื่อให้คำถามชัดเจนขึ้นและใช้สถานการณ์ที่ดีขึ้น (หวังว่า)
SonOfPirate

คำตอบ:


4

ฉันอยากจะใช้บริการติดตามเวลา:

public interface ITimeSheetTrackingService
{
   void TrackClockIn(Employee employee, Timesheet timesheet);

   void TrackClockOut(Employee employee, Timesheet timesheet);

}

ฉันไม่คิดว่ามันเป็นความรับผิดชอบของใบบันทึกเวลาในการตอกบัตรหรือหมดเวลาไม่เป็นความรับผิดชอบของพนักงาน


3

รากรวมไม่ควรมีซึ่งกันและกัน (แม้ว่าพวกเขาอาจมี ID ให้ผู้อื่น)

ก่อนอื่น TimeSheet เป็นรูทรวมหรือไม่ ความจริงที่ว่ามันมีเอกลักษณ์ทำให้เป็นนิติบุคคลไม่จำเป็นต้องเป็น AR ลองดูกฎข้อใดข้อหนึ่ง:

Root Entities have global identity.  Entities inside the boundary have local 
identity, unique only within the Aggregate.

คุณกำหนดตัวตนของ TimeSheet เป็น ID พนักงานและช่วงเวลาซึ่งแสดงให้เห็นว่า TimeSheet เป็นส่วนหนึ่งของพนักงานที่มีช่วงเวลาเป็นตัวตนในท้องถิ่น เนื่องจากนี่เป็นแอปพลิเคชั่นนาฬิกาเวลาวัตถุประสงค์หลักของพนักงานที่จะเป็นที่เก็บภาชนะสำหรับ TimeSheets หรือไม่

สมมติว่าคุณต้อง ARS, ClockIn และ ClockOut ดูเหมือนการดำเนินการ TimeSheet มากกว่าพนักงาน เมธอดเลเยอร์บริการของคุณอาจมีลักษณะดังนี้:

public void ClockIn(String employeeId)
{
    var timeSheet = TimeSheetRepository.FindByEmployeeAndTime(employeeId, DateTime.Now);    
    timeSheet.ClockIn();    
    TimeSheetRepository.Save();
}

หากคุณต้องการติดตามสถานะการโอเวอร์คล็อกในทั้งพนักงานและ TimeSheet ให้ดูที่กิจกรรมของโดเมน (ฉันไม่เชื่อว่าพวกเขาอยู่ในหนังสือของอีแวนส์ แต่มีบทความออนไลน์มากมาย) มันจะมีลักษณะดังนี้: Employee.ClockIn () เพิ่มเหตุการณ์ EmployeeClockedIn ซึ่งตัวจัดการเหตุการณ์หยิบขึ้นมาและในทางกลับกันจะเรียก TimeSheet.LogEmployeeClockIn ()


ฉันเห็นคะแนนของคุณ อย่างไรก็ตามมีกฎบางอย่างที่ จำกัด ว่าเมื่อใดและเมื่อใดที่พนักงานสามารถตอกบัตรเข้าได้กฎเหล่านี้ส่วนใหญ่ขับเคลื่อนโดยสถานะปัจจุบันของพนักงานเช่นว่าจะถูกยกเลิกยกเลิกการตอกบัตรแล้วกำหนดให้ทำงานในวันนั้นหรือแม้กระทั่ง กะปัจจุบัน ฯลฯ TimeSheet ควรมีความรู้นี้หรือไม่?
SonOfPirate

3

ฉันกำลังออกแบบแอพพลิเคชั่นตามแนวทาง DDD และสงสัยว่าฉันสามารถทำตามแนวทางใดได้บ้างเพื่อพิจารณาว่ารูทการรวมควรมี AR อื่นหรือไม่ถ้าพวกมันควรจะแยกจากกัน

รากรวมไม่ควรมีรากรวมอื่น

ในคำอธิบายของคุณคุณมีนิติบุคคลพนักงานและนิติบุคคล Timesheet เช่นเดียวกัน เอนทิตีทั้งสองนี้แตกต่างกัน แต่อาจรวมถึงการอ้างอิงถึงกัน (เช่น: นี่คือแผ่นเวลาของบ๊อบ)

นั่นคือการสร้างแบบจำลองพื้นฐาน

คำถามรากรวมแตกต่างกันเล็กน้อย หากเอนทิตีทั้งสองเหล่านี้มีความแตกต่างทางธุรกรรมจากกันพวกเขาก็สามารถสร้างแบบจำลองได้อย่างถูกต้องเป็นผลรวมที่แตกต่างกันสองแบบ โดยการทำธุรกรรมที่แตกต่างกันฉันหมายความว่าไม่มีธุรกิจคงที่ที่ต้องรู้สถานะปัจจุบันของพนักงานและสถานะปัจจุบันของ TimeSheet พร้อมกัน

ตามสิ่งที่คุณอธิบาย Timesheet.clockIn และ Timesheet.clockOut ไม่จำเป็นต้องตรวจสอบข้อมูลใด ๆ ในพนักงานเพื่อพิจารณาว่าคำสั่งนั้นได้รับอนุญาตหรือไม่ ดังนั้นสำหรับปัญหาที่เกิดขึ้นนี้ AR ที่แตกต่างกันสองตัวดูสมเหตุสมผล

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

ในทางกลับกัน (และนี่คือคำถามสุดท้ายของการโพสต์) TimeSheet ดูเหมือนว่าเป็น Aggregate Root และมีตัวตน (ID พนักงานและระยะเวลา)

ตัวตนเท่านั้นหมายความว่ามันเป็นเอนทิตี้ของ - มันเป็นค่าคงที่ของธุรกิจที่ขับเคลื่อนว่าควรพิจารณาว่าเป็นรากรวมที่แยกจากกันหรือไม่

อย่างไรก็ตามมีกฎบางอย่างที่ จำกัด ว่าเมื่อใดและเมื่อใดที่พนักงานสามารถตอกบัตรได้กฎเหล่านี้ส่วนใหญ่ขับเคลื่อนโดยสถานะปัจจุบันของพนักงานเช่นว่าจะถูกยกเลิกยกเลิกการตอกบัตรแล้วกำหนดให้ทำงานในวันนั้นหรือแม้กระทั่ง กะปัจจุบัน ฯลฯ TimeSheet ควรมีความรู้นี้หรือไม่?

บางที - ควรรวม ไม่ได้แปลว่า Timesheet ควรหมายความ

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

การรวมมีหนึ่งเอนทิตีรูท ระบุว่ามันเป็นส่วนหนึ่งของปริศนา หากพนักงานมี Timesheet มากกว่าหนึ่งและพวกเขาทั้งคู่เป็นส่วนรวมเดียวกัน Timesheet นั้นไม่ใช่รากแน่นอน ซึ่งหมายความว่าแอปพลิเคชันไม่สามารถแก้ไขหรือส่งคำสั่งโดยตรงไปที่แผ่นเวลา - พวกเขาจำเป็นต้องส่งไปยังวัตถุราก (สันนิษฐานว่าพนักงาน) ซึ่งสามารถมอบหมายความรับผิดชอบบางอย่าง

การตรวจสอบอีกอย่างคือการพิจารณาว่า Timesheets สร้างขึ้นอย่างไร หากพวกเขาถูกสร้างขึ้นโดยปริยายเมื่อพนักงานเข้ามาก็เป็นอีกคำใบ้ว่าพวกเขาเป็นหน่วยงานย่อยในการรวม

นอกเหนือไปจากนี้มันไม่น่าเป็นไปได้ที่มวลรวมของคุณควรมีเวลาของตัวเอง ควรส่งเวลาให้พวกเขาแทน

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