บังเอิญฉันกำลังทำงานในโครงการ WinForms ที่มีลวดลายหลัง MVC ฉันจะไม่เรียกสิ่งนี้ว่าคำตอบที่สมบูรณ์แบบ แต่ฉันจะอธิบายการออกแบบโดยรวมของฉันและหวังว่าสิ่งนี้จะช่วยให้คุณได้มาด้วยตัวคุณเอง
จากการอ่านที่ฉันทำก่อนเริ่มโครงการนี้ดูเหมือนจะไม่มีวิธีที่ "ถูกต้อง" ในการดำเนินการนี้ ฉันทำตามหลักการออกแบบที่เรียบง่ายของ OOP และ MVC ส่วนที่เหลือคือการลองผิดลองถูกเมื่อฉันพัฒนาเวิร์กโฟลว์
MVC เป็นเพียงสถาปัตยกรรมที่ไม่เหมาะสมสำหรับกรณีการใช้งานนี้หรือไม่?
ไม่ .. คำถามของคุณมีบริบทไม่เพียงพอที่จะให้คำตอบโดยตรงกับสิ่งนั้น ทำไมคุณใช้ MVC ตั้งแต่แรก ข้อกำหนดด้านการใช้งานของโครงการของคุณมีอะไรบ้าง? โปรเจคของคุณจะหนักหนาสาหัสขนาดนี้หรือไม่? คุณสนใจเกี่ยวกับความปลอดภัยมากกว่าและต้องการสถาปัตยกรรมแบบเลเยอร์หรือไม่ องค์ประกอบหลักของโครงการของคุณคืออะไร? บางทีแต่ละองค์ประกอบต้องการรูปแบบการออกแบบที่แตกต่างกัน ค้นหาสาเหตุที่คุณต้องการใช้รูปแบบการออกแบบนี้ตั้งแต่แรกและคุณอาจตอบคำถามของคุณเอง;)
เหตุผลของฉันสำหรับการใช้ MVC: มันเป็นรูปแบบการออกแบบที่ค่อนข้างง่ายที่จะเข้าใจในความคิดเห็นของฉันและการออกแบบของฉันนั้นขึ้นอยู่กับการโต้ตอบของผู้ใช้เป็นอย่างมาก วิธีที่ MVC อนุญาตให้นักพัฒนาแยกความกังวลก็เพียงพอสำหรับแอปพลิเคชันของฉันเช่นกัน นี่ทำให้รหัสของฉันมากขึ้นและสามารถบำรุงรักษาได้มากขึ้น
ฉันก็คิดว่าฉันใช้การออกแบบไฮบริดมากขึ้น โดยปกติแล้วแนวคิดในอุดมคติที่นำเสนอในวิศวกรรมซอฟต์แวร์นั้นไม่ได้มีประโยชน์ในทางปฏิบัติ คุณสามารถปรับเปลี่ยนการออกแบบเพื่อให้เหมาะกับความต้องการของโครงการของคุณ ไม่จำเป็นต้องจมอยู่กับสิ่งที่ถูกหรือผิด มีการปฏิบัติทั่วไป แต่กฎสามารถโค้งงอหรือแตกหักได้เสมอตราบใดที่คุณไม่ยิงตัวเองด้วยการเดินเท้า
การนำไปใช้ของฉันเริ่มต้นด้วยการออกแบบระดับสูงซึ่งทำให้ฉันมีความคิดเกี่ยวกับองค์ประกอบที่ฉันต้องการ วิธีที่ดีที่สุดในการเริ่มต้นด้วยวิธีนี้และลงมือทำในสถาปัตยกรรม นี่คือแผนภาพแพคเกจสำหรับโครงการ (สร้างใน StarUML):
สังเกตเห็นทุกชั้นเดียวยกเว้นชั้นนำเสนอขึ้นอยู่กับระบบการส่งข้อความ นี่เป็น "ภาษา" ทั่วไปที่ชั้นล่างและระบบย่อยของชั้นเหล่านั้นใช้เพื่อสื่อสารซึ่งกันและกัน ในกรณีของฉันมันเป็นการแจงนับอย่างง่ายตามการดำเนินการที่สามารถทำได้ ซึ่งนำฉันไปยังจุดต่อไป ...
คิดว่าการดำเนินงานหรือคำสั่งเป็นพื้นฐานสำหรับการใช้งาน คุณต้องการให้ใบสมัครของคุณทำอะไร ทำลายมันลงไปในปฏิบัติการขั้นพื้นฐานที่สุด ตัวอย่างเช่น: CreateProject, WriteNotes, SaveProject, LoadProject เป็นต้น GUI (หรือคลาสฟอร์ม) จะเกิดเหตุการณ์บางอย่าง (เช่นกดปุ่ม) ทุกการดำเนินการมีวิธีการควบคุมที่เกี่ยวข้อง ในกรณีนี้สิ่งที่ต้องการออกง่ายเกินไป แอปพลิเคชันสามารถปิดได้จากคลาสฟอร์ม แต่สมมติว่าฉันต้องการเก็บข้อมูลแอปพลิเคชั่นบางไฟล์ไว้ก่อน? ฉันจะเรียกวิธีการ "บันทึก" จากคลาสคอนโทรลเลอร์ที่เกี่ยวข้องภายในวิธีการกดปุ่มของฉัน
จากนั้นตัวควบคุมจะเรียกชุดปฏิบัติการที่ถูกต้องจากคลาสบริการ คลาสบริการในแอปพลิเคชันของฉันทำหน้าที่เป็นส่วนต่อประสานกับเลเยอร์โดเมน พวกเขาจะตรวจสอบอินพุตที่ได้รับจากการเรียกใช้เมธอดคอนโทรลเลอร์ (และจาก GUI) และจัดการโมเดลข้อมูล
เมื่อการตรวจสอบและการจัดการวัตถุที่เกี่ยวข้องเสร็จสมบูรณ์แล้ววิธีการบริการจะส่งคืนรหัสข้อความไปยังตัวควบคุม ตัวอย่างเช่นMessageCodes.SaveSuccess
. ทั้งตัวควบคุมและคลาสบริการขึ้นอยู่กับวัตถุโดเมนและ / หรือชุดการดำเนินงานทั่วไปที่สามารถจัดกลุ่มเข้าด้วยกัน
ตัวอย่างเช่น: FileMenuController
(การดำเนินการ: NewProject, SaveProject, LoadProject) -> ProjectServices
(CreateProject, PersistProjectToFile, LoadProjectFromFile) ที่Project
จะเป็นชั้นโดเมนในรูปแบบข้อมูลของคุณ คลาส Controller และ Service ในกรณีของฉันเป็นคลาสที่ไม่สามารถใช้งานได้ทันทีด้วยวิธีการคงที่
จากนั้นคอนโทรลเลอร์จะจดจำการดำเนินการเมื่อเสร็จสิ้นการยกเลิก / สำเร็จ ตอนนี้คอนโทรลเลอร์มีระบบการส่งข้อความของตัวเองซึ่งใช้ในการโต้ตอบกับเลเยอร์การนำเสนอดังนั้นการพึ่งพาสองครั้งระหว่างชั้นบริการและการนำเสนอ ในกรณีนี้คลาสเรียกว่าViewState
ในViewModels
แพ็คเกจจะถูกส่งกลับไปยัง GUI โดยผู้ควบคุมเสมอ รัฐนี้มีข้อมูลเช่น: " ? เป็นรัฐที่คุณพยายามที่จะนำการประยุกต์ใช้ในที่ถูกต้อง ", " ข้อความอ่านของมนุษย์เกี่ยวกับการดำเนินการที่คุณพยายามที่จะดำเนินการและเหตุผลที่มันเป็นหรือไม่ประสบความสำเร็จ (ข้อผิดพลาด) " และViewModel
ระดับ
ViewModel
ชั้นมีข้อมูลที่เกี่ยวข้องจากชั้นโดเมนที่ GUI จะใช้ในการปรับปรุงมุมมอง มุมมองแบบจำลองเหล่านี้ดูเหมือนคลาสโดเมน แต่ในกรณีของฉันฉันใช้มากวัตถุที่ผอมโดยทั่วไปแล้วพวกเขาไม่มีพฤติกรรมที่ค่อนข้างสวยเพียงแค่ถ่ายทอดข้อมูลเกี่ยวกับสถานะระดับล่างของแอปพลิเคชัน กล่าวอีกนัยหนึ่งฉันจะไม่ให้คลาสโดเมนของฉันกับเลเยอร์การนำเสนอ นี่คือสาเหตุที่Controllers
และServices
แพ็กเกจแบ่งชั้นบริการเป็นสองส่วน ตัวควบคุมจะไม่จัดการกับคลาสโดเมนหรือตรวจสอบสถานะของพวกเขา พวกเขาเพียงแค่ทำหน้าที่เป็นขอบเขตในการแปลงข้อมูลที่เกี่ยวข้องกับ GUI เป็นข้อมูลที่เกี่ยวข้องกับโดเมนที่บริการสามารถใช้และรองได้ การรวมตรรกะบริการในตัวควบคุมจะทำให้อ้วนมาก ตัวควบคุมซึ่งยากที่จะรักษา
ฉันหวังว่านี่จะช่วยให้คุณเป็นจุดเริ่มต้น