นี่เป็นการถอดความความคิดเห็นเริ่มต้นของฉันภายใต้คำถามของคุณ คำตอบของคำถามที่กล่าวถึงโดย OP จะอยู่ที่ด้านล่างของคำตอบนี้ โปรดตรวจสอบหมายเหตุสำคัญที่อยู่ในสถานที่เดียวกัน
สิ่งที่คุณกำลังอธิบาย Sipo เป็นรูปแบบการออกแบบที่เรียกว่าบันทึกการใช้งาน เช่นเดียวกับทุกสิ่งทุกอย่างแม้แต่สิ่งนี้ก็พบว่าอยู่ในตำแหน่งของโปรแกรมเมอร์ แต่ถูกทิ้งให้อยู่ในรูปแบบของพื้นที่เก็บข้อมูลและรูปแบบตัวแม็ปข้อมูลด้วยเหตุผลง่ายๆ
กล่าวโดยย่อบันทึกที่ใช้งานอยู่คือวัตถุซึ่ง:
- แสดงถึงวัตถุในโดเมนของคุณ (รวมถึงกฎทางธุรกิจรู้วิธีจัดการการดำเนินการบางอย่างกับวัตถุเช่นถ้าคุณสามารถหรือไม่สามารถเปลี่ยนชื่อผู้ใช้เป็นต้น)
- รู้วิธีเรียกค้นอัปเดตบันทึกและลบเอนทิตี
คุณกล่าวถึงปัญหาหลายประการเกี่ยวกับการออกแบบปัจจุบันของคุณและปัญหาหลักของการออกแบบของคุณได้รับการแก้ไขในครั้งที่ 6, จุด (สุดท้าย แต่ไม่ท้ายสุดฉันเดา) เมื่อคุณมีคลาสที่คุณออกแบบคอนสตรัคเตอร์และคุณไม่รู้ด้วยซ้ำว่าคอนสตรัคเตอร์ควรทำอย่างไรคลาสอาจทำสิ่งผิดปกติ ที่เกิดขึ้นในกรณีของคุณ
แต่การแก้ไขการออกแบบนั้นง่ายมากโดยการแยกการแสดงเอนทิตีและตรรกะ CRUD ออกเป็นสองคลาส (หรือมากกว่า)
นี่คือการออกแบบของคุณในตอนนี้:
Employee
- มีข้อมูลเกี่ยวกับโครงสร้างพนักงาน (คุณลักษณะของมัน) และวิธีการแก้ไขเอนทิตี (ถ้าคุณตัดสินใจที่จะเปลี่ยนวิธี), มีตรรกะ CRUD สำหรับEmployee
เอนทิตีสามารถส่งกลับรายการของEmployee
วัตถุยอมรับEmployee
วัตถุเมื่อคุณต้องการ อัปเดตพนักงานสามารถส่งคืนเดียวEmployee
ผ่านวิธีการเช่นgetSingleById(id : string) : Employee
ว้าวชั้นเรียนดูใหญ่มาก
นี่จะเป็นวิธีแก้ปัญหาที่เสนอ:
Employee
- มีข้อมูลเกี่ยวกับโครงสร้างพนักงาน (คุณลักษณะของมัน) และวิธีการแก้ไขเอนทิตี (ถ้าคุณตัดสินใจที่จะใช้วิธีที่ไม่แน่นอน)
EmployeeRepository
- มีตรรกะ CRUD สำหรับEmployee
เอนทิตีสามารถส่งกลับรายการของEmployee
วัตถุยอมรับEmployee
วัตถุเมื่อคุณต้องการอัพเดตพนักงานสามารถส่งคืนเดียวEmployee
ผ่านวิธีเช่นgetSingleById(id : string) : Employee
คุณเคยได้ยินเรื่องการแยกความกังวลหรือไม่? ไม่ตอนนี้คุณจะ มันเป็นรุ่นที่เข้มงวดน้อยกว่าของหลักการความรับผิดชอบเดี่ยวซึ่งกล่าวว่าชั้นเรียนควรมีความรับผิดชอบเพียงอย่างเดียวเท่านั้นหรือตามที่ลุงบ๊อบกล่าวว่า:
โมดูลควรมีเหตุผลเดียวเท่านั้นที่จะเปลี่ยน
เป็นที่ชัดเจนว่าถ้าฉันสามารถแยกชั้นเรียนเริ่มต้นของคุณเป็นสองอย่างชัดเจนซึ่งยังคงมีอินเทอร์เฟซที่โค้งมนชั้นเรียนเริ่มต้นอาจทำมากเกินไปและเป็น
สิ่งที่ยอดเยี่ยมเกี่ยวกับรูปแบบพื้นที่เก็บข้อมูลมันไม่เพียงทำหน้าที่เป็นนามธรรมเพื่อให้ชั้นกลางระหว่างฐานข้อมูล (ซึ่งสามารถเป็นอะไรไฟล์ noSQL, SQL, วัตถุเชิงหนึ่ง) แต่ไม่จำเป็นต้องเป็นรูปธรรม ชั้น ในหลายภาษา OO คุณสามารถกำหนดอินเทอร์เฟซเป็นจริงinterface
(หรือคลาสด้วยวิธีเสมือนจริงถ้าคุณอยู่ใน C ++) แล้วมีการนำไปใช้หลายอย่าง
สิ่งนี้เป็นการยกระดับการตัดสินใจอย่างสมบูรณ์ว่าที่เก็บข้อมูลเป็นการใช้งานจริงของคุณหรือไม่โดยอาศัยอินเทอร์เฟซโดยอาศัยโครงสร้างกับinterface
คำสำคัญ และพื้นที่เก็บข้อมูลนั้นเป็นคำศัพท์ที่เป็นนามธรรมสำหรับ data layer abstraction นั่นคือการจับคู่ข้อมูลกับโดเมนของคุณและในทางกลับกัน
อีกสิ่งที่ยอดเยี่ยมเกี่ยวกับการแยกมันออกเป็นสองคลาส (อย่างน้อย) คือตอนนี้Employee
ชั้นเรียนสามารถจัดการข้อมูลของตัวเองได้อย่างชัดเจนและทำได้ดีมากเพราะไม่จำเป็นต้องดูแลสิ่งที่ยากอื่น ๆ
คำถามที่ 6:ผู้สร้างควรทำอะไรในEmployee
ชั้นเรียนที่สร้างขึ้นใหม่ มันง่าย ควรใช้อาร์กิวเมนต์ตรวจสอบว่าถูกต้อง (เช่นอายุไม่น่าจะเป็นลบหรือชื่อไม่ควรว่างเปล่า) เพิ่มข้อผิดพลาดเมื่อข้อมูลไม่ถูกต้องและหากการตรวจสอบผ่านการมอบหมายอาร์กิวเมนต์ให้ตัวแปรส่วนตัว ของกิจการ ตอนนี้มันไม่สามารถสื่อสารกับฐานข้อมูลได้เพราะมันไม่รู้ว่าจะทำอย่างไร
คำถามที่ 4:ไม่สามารถตอบได้เลยไม่ใช่โดยทั่วไปเพราะคำตอบนั้นขึ้นอยู่กับว่าคุณต้องการอะไร
คำถามที่ 5:ตอนนี้คุณได้แยกชั้นป่องออกเป็นสองคุณสามารถมีวิธีการอัปเดตหลายโดยตรงบนEmployee
ชั้นเช่นchangeUsername
, markAsDeceased
ซึ่งจะจัดการกับข้อมูลของEmployee
ชั้นเท่านั้นในแรมและจากนั้นคุณสามารถแนะนำวิธีเช่นregisterDirty
จากรูปแบบหน่วยการทำงานเป็นคลาสที่เก็บข้อมูลซึ่งคุณจะให้ที่เก็บทราบว่าวัตถุนี้มีการเปลี่ยนแปลงคุณสมบัติและจะต้องมีการปรับปรุงหลังจากที่คุณเรียกใช้commit
เมธอด
เห็นได้ชัดว่าสำหรับการปรับปรุงวัตถุจะต้องมี ID และถูกบันทึกไว้แล้วและมันเป็นความรับผิดชอบของพื้นที่เก็บข้อมูลในการตรวจสอบและเพิ่มข้อผิดพลาดเมื่อไม่ตรงตามเกณฑ์
คำถามที่ 3:หากคุณตัดสินใจที่จะไปกับหน่วยของรูปแบบการทำงานที่วิธีการในขณะนี้จะcreate
registerNew
ถ้าคุณทำไม่ได้ฉันอาจจะเรียกมันว่าsave
แทน เป้าหมายของพื้นที่เก็บข้อมูลคือการให้สิ่งที่เป็นนามธรรมระหว่างโดเมนและชั้นข้อมูลเพราะสิ่งนี้ฉันขอแนะนำให้คุณทราบว่าวิธีการนี้ (ไม่ว่าจะเป็นregisterNew
หรือsave
) ยอมรับEmployee
วัตถุและขึ้นอยู่กับคลาสที่ใช้อินเทอร์เฟซพื้นที่เก็บข้อมูล พวกเขาตัดสินใจที่จะนำกิจการออกไป ผ่านวัตถุทั้งหมดจะดีกว่าดังนั้นคุณไม่จำเป็นต้องมีพารามิเตอร์เพิ่มเติมมากมาย
คำถามที่ 2:ทั้งสองวิธีนี้จะเป็นส่วนหนึ่งของส่วนต่อประสานที่เก็บข้อมูลและพวกเขาไม่ได้ละเมิดหลักการความรับผิดชอบเดียว ความรับผิดชอบของพื้นที่เก็บข้อมูลคือการจัดเตรียมการดำเนินการ CRUD สำหรับEmployee
วัตถุนั่นคือสิ่งที่มันทำ (นอกเหนือจากการอ่านและลบ CRUD แปลเป็นทั้งสร้างและปรับปรุง) เห็นได้ชัดว่าคุณสามารถแยกพื้นที่เก็บข้อมูลได้มากขึ้นโดยมีEmployeeUpdateRepository
และอื่น ๆ แต่ที่ไม่ค่อยจำเป็นและการใช้งานเพียงครั้งเดียวสามารถมีการดำเนินงาน CRUD ทั้งหมด
คำถามที่ 1:คุณจบด้วยEmployee
คลาสแบบง่าย ๆซึ่งตอนนี้ (ท่ามกลางคุณสมบัติอื่น ๆ ) จะมีรหัส ระบุว่า ID เต็มหรือว่างเปล่า (หรือnull
) ขึ้นอยู่กับว่าวัตถุได้รับการบันทึกแล้ว อย่างไรก็ตามรหัสยังคงเป็นคุณลักษณะที่กิจการเป็นเจ้าของและความรับผิดชอบของEmployee
กิจการคือการดูแลคุณลักษณะของกิจการดังนั้นการดูแล ID
ไม่ว่าเอนทิตีจะทำหรือไม่มี id มักจะไม่สำคัญจนกว่าคุณจะพยายามทำสิ่งต่อไปนี้ ตามที่กล่าวไว้ในคำตอบของคำถามที่ 5 มันเป็นความรับผิดชอบของที่เก็บในการตรวจสอบว่าคุณไม่ได้พยายามที่จะบันทึกเอนทิตีที่ถูกบันทึกไว้แล้วหรือพยายามที่จะอัพเดตเอนทิตีโดยไม่มี ID
โน๊ตสำคัญ
โปรดระวังว่าแม้ว่าการแยกข้อกังวลออกมานั้นยอดเยี่ยมจริง ๆ แล้วการออกแบบเลเยอร์พื้นที่เก็บข้อมูลที่ใช้งานได้นั้นเป็นงานที่ค่อนข้างน่าเบื่อและจากประสบการณ์ของฉันค่อนข้างยากที่จะได้รับมากกว่าวิธีบันทึกที่ใช้งานอยู่ แต่คุณจะจบลงด้วยการออกแบบที่ยืดหยุ่นและปรับขนาดได้ซึ่งอาจเป็นสิ่งที่ดี
Employee
วัตถุเพื่อให้เป็นนามธรรมคำถาม4และ5โดยทั่วไปไม่สามารถตอบได้ขึ้นอยู่กับความต้องการของคุณและถ้าคุณแยกโครงสร้างและการดำเนินการ CRUD ออกเป็นสองคลาสแล้วมันค่อนข้างชัดเจนตัวสร้างของEmployee
ข้อมูลที่ไม่สามารถดึงข้อมูลได้ จาก db อีกต่อไปดังนั้นคำตอบที่6