ลองดูตัวเลือกที่เราสามารถวางรหัสการตรวจสอบ:
- ภายใน setters ในผู้สร้าง
- ภายใน
build()
วิธีการ
- ภายในเอนทิตีที่สร้างขึ้น: มันจะถูกเรียกใช้ใน
build()
วิธีการเมื่อมีการสร้างเอนทิตี
ตัวเลือกที่ 1ช่วยให้เราสามารถตรวจสอบปัญหาก่อนหน้านี้ได้ แต่อาจมีกรณีที่ซับซ้อนเมื่อเราสามารถตรวจสอบความถูกต้องของอินพุตว่ามีบริบทแบบเต็มbuild()
เท่านั้น ดังนั้นการเลือกตัวเลือกที่ 1 จะนำไปสู่รหัสที่ไม่สอดคล้องกับส่วนหนึ่งของการตรวจสอบความถูกต้องในที่เดียวและอีกส่วนที่ทำในที่อื่น
ตัวเลือกที่ 2นั้นไม่ได้เลวร้ายยิ่งไปกว่าตัวเลือก 1 เนื่องจากโดยทั่วไป setters ในตัวสร้างจะถูกเรียกใช้ก่อนหน้าbuild()
นี้โดยเฉพาะอย่างยิ่งในส่วนต่อประสานที่คล่องแคล่ว ดังนั้นจึงยังคงเป็นไปได้ที่จะตรวจสอบปัญหาก่อนเวลาในกรณีส่วนใหญ่ อย่างไรก็ตามหากผู้สร้างไม่ได้เป็นวิธีเดียวในการสร้างวัตถุมันจะนำไปสู่การทำสำเนาของรหัสตรวจสอบเพราะคุณจะต้องมีทุกที่ที่คุณสร้างวัตถุ วิธีแก้ปัญหาเชิงตรรกะที่สุดในกรณีนี้คือการทำให้การตรวจสอบใกล้เคียงกับวัตถุที่สร้างขึ้นมากที่สุดเท่าที่จะทำได้ และนี่คือตัวเลือกที่ 3
จากมุมมองของ SOLID การวางการตรวจสอบความถูกต้องในตัวสร้างยังเป็นการละเมิด SRP: คลาสตัวสร้างมีความรับผิดชอบในการรวบรวมข้อมูลเพื่อสร้างวัตถุ การตรวจสอบกำลังสร้างสัญญาในสถานะภายในของตัวเองมันเป็นความรับผิดชอบใหม่ในการตรวจสอบสถานะของวัตถุอื่น
ดังนั้นจากมุมมองของฉันไม่เพียง แต่จะดีกว่าที่จะล้มเหลวจากมุมมองการออกแบบ แต่ยังดีกว่าที่จะล้มเหลวในเอนทิตีที่สร้างขึ้นแทนที่จะสร้างตัวมันเอง
UPD: ความคิดเห็นนี้ทำให้ฉันนึกถึงความเป็นไปได้อีกหนึ่งเมื่อการตรวจสอบภายในตัวสร้าง (ตัวเลือก 1 หรือ 2) สมเหตุสมผล มันสมเหตุสมผลถ้าผู้สร้างมีสัญญาของตัวเองในวัตถุที่กำลังสร้าง ตัวอย่างเช่นสมมติว่าเรามีการสร้างที่สร้างสตริงที่มีเนื้อหาเฉพาะการพูด, 1-2,3-4,5-6
รายการของช่วงตัวเลข addRange(int min, int max)
สร้างนี้อาจมีวิธีการเช่น สตริงผลลัพธ์ไม่ทราบอะไรเกี่ยวกับตัวเลขเหล่านี้ไม่ควรรู้ ผู้สร้างเองกำหนดรูปแบบของสตริงและข้อ จำกัด เกี่ยวกับตัวเลข ดังนั้นวิธีการaddRange(int,int)
จะต้องตรวจสอบหมายเลขอินพุตและส่งข้อยกเว้นถ้าค่าสูงสุดน้อยกว่าขั้นต่ำ
ที่กล่าวว่ากฎทั่วไปจะตรวจสอบเฉพาะสัญญาที่กำหนดโดยผู้สร้างเอง