สถาปัตยกรรม MVC - ฉันต้องการคอนโทรลเลอร์จำนวนเท่าใด


54

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

ฉันหวังว่าคำถามนี้จะไม่คล้ายกับ " แนวทางปฏิบัติที่ดีที่สุดสำหรับสถาปัตยกรรม MVC " แต่เมื่อฉันทำแบบฝึกหัดที่แตกต่างกันสองสามครั้งฉันสังเกตเห็นว่าบางคนมีตัวควบคุมหลายตัวสำหรับสิ่งที่แตกต่างกัน

แอปพลิเคชันเว็บเดียวต้องมีคอนโทรลเลอร์จำนวนเท่าใด

ฉันรู้ว่ามันคงยากที่จะตอบโดยไม่มีตัวอย่างดังนั้นฉันจะให้:

การประยุกต์ใช้:

  1. ผู้ใช้เข้าสู่ระบบ
  2. ผู้ใช้สามารถทำหนึ่งในสามสิ่งต่อไปนี้:
    ก) อัปโหลดไฟล์ (เก็บไว้ในฐานข้อมูล mongodb พร้อมข้อมูลเมตา)
    b) ค้นหาไฟล์
    c) ออกจากระบบ

คำถามของฉันเป็นคำถามทั่วไป แต่ฉันยกตัวอย่างเพื่อช่วยใครก็ตามที่พยายามจะตอบ


8
คำถามที่ถามกันจริงๆ
Daniel Hollinrake

คำตอบ:


34

สำหรับตัวอย่างของคุณฉันจะสร้างตัวควบคุมสองตัว:

  • ตัวควบคุมเซสชันสำหรับลงชื่อเข้าใช้และออกจากระบบ (สร้างและทำลายเซสชันสำหรับ REST เช่นเลย์เอาต์)
  • ตัวควบคุมไฟล์สำหรับทุกอย่างในไฟล์ (ดัชนี = ค้นหาและสร้าง = อัปโหลด)

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

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

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


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

4
มันขึ้นอยู่กับฟังก์ชั่นการใช้งานจริง ๆ แต่โดยทั่วไปฉันเขียนตัวควบคุมที่สองโดยไม่ต้องสืบทอดเลย ตามหลักการ 'thin controller' ไม่ควรมีโค้ดมากในคอนโทรลเลอร์ และตัวควบคุมผู้ดูแลระบบสามารถทำได้ง่ายโดยเฉพาะอย่างยิ่ง ฟังก์ชั่นที่สำคัญทั้งหมดเข้าสู่โมเดล (เช่นหากการลบผู้ใช้หมายความว่าไฟล์ทั้งหมดของเขาควรจะถูกลบออกไปจากนั้นตัวแบบจะจัดการกับสิ่งนี้ไม่มีบรรทัดเดียวสำหรับสิ่งนี้ในคอนโทรลเลอร์)
thorsten müller

6

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

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


5

จริงๆมันขึ้นอยู่กับความต้องการของแอพลิเคชันและสถาปัตยกรรมของโมดูลธุรกิจของคุณ

กฎทั่วไปของหัวแม่มือจำนวนของตัวควบคุมที่จำเป็นขึ้นอยู่กับจำนวนของโมดูลและโมดูลย่อยในเว็บแอป

ในฐานะที่เป็นที่สมบูรณ์ก็จะเป็นประโยชน์ในการจัดระเบียบควบคุมลงไปในพื้นที่ แนวคิดของพื้นที่คือโครงสร้างในกรอบ ASP.NET MVC และช่วยให้องค์กรของตัวควบคุมที่ให้บริการหนึ่งโมดูลง่ายขึ้น

มีการสนทนาที่เกี่ยวข้องจำนวนหนึ่ง:


1
การอ้างอิงที่ยอดเยี่ยม! ฉันจะแน่ใจว่าได้ตรวจสอบพวกเขาออก!
Jeff

แน่นอนไม่มีปัญหา.
EL Yusubov

4

ฉันชอบวิธีของ Apple ในการทำเช่นนั้น

ทุกมุมมองถูกควบคุมโดยคอนโทรลเลอร์มุมมองเดียวเท่านั้น ~ ดูคู่มือการเขียนโปรแกรมควบคุมสำหรับ iOS

แนวคิดคือคุณควรจะสามารถสลับมุมมองได้อย่างง่ายดาย IMO โดยมีเพียง 1 Controllerต่อViewก็จะทำให้มันง่ายต่อการบรรลุเป้าหมายนี้ แต่ฉันแน่ใจว่าคุณสามารถมีตัวควบคุมที่มีหลายมุมมองและยังคงออกแบบไว้เพื่อให้คุณสามารถสลับมุมมองโดยไม่ต้องเปลี่ยนตรรกะโปรแกรม


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

แบบจำลองควรติดตามผู้ใช้ ดังนั้นคอนโทรลเลอร์หลายตัวสามารถใช้วัตถุโมเดลเดียวกันได้หากจำเป็น
Korey Hinton

2
ดังนั้นคอนโทรลเลอร์จึงมีวัตถุโมเดลและวัตถุมุมมอง คอนโทรลเลอร์ขอให้โมเดลวัตถุหาข้อมูล (เช่นข้อมูลผู้ใช้) จากนั้นตั้งค่ามุมมองให้สอดคล้องกัน ตัวแบบควรมีตรรกะของโปรแกรมส่วนใหญ่ในขณะที่ตัวควบคุมมีตรรกะเพื่อให้สามารถสื่อสารไปมาระหว่างมุมมองและตัวแบบ
Korey Hinton

2
คอนโทรลเลอร์หนึ่งตัวต่อการดูนั้นมีการออกแบบที่ จำกัด มากเนื่องจากคอนโทรลเลอร์ของคุณจะไม่สามารถแสดงมุมมองที่แตกต่างกันสำหรับสถานะที่แตกต่างของโมเดล
EL Yusubov

1
@ElYusubov ฉันสามารถดูว่ามันอาจทำให้เกิดความสับสน ใน iOS ทุกมุมมองมีตัวควบคุมมุมมองเดียวเท่านั้นและทุกตัวควบคุมมุมมองมีมุมมองที่ใช้งานอยู่เพียง 1 มุมมอง (และมุมมองนั้นสามารถมีมุมมองย่อย) แต่ตัวควบคุมมุมมองนั้นยังสามารถมีการอ้างอิงถึงจำนวนมุมมองต่างๆ
Korey Hinton

2

ตัวอย่างหนึ่งที่ฉันชอบคือคิดถึงเทอร์โมสตัท เทอร์โมเป็นภาพที่ดีสำหรับการดูรูปแบบ MVC


ในเทอร์โมอะนาล็อกที่เก่ากว่าคุณสามารถนึกภาพสิ่งต่าง ๆ ดังนี้:

มุมมอง - ตัวอ่านอุณหภูมิซึ่งแสดงอุณหภูมิปัจจุบัน

คอนโทรลเลอร์ - ปุ่มหมุนซึ่งคุณเปลี่ยนอุณหภูมิ

รุ่น - ชิ้นส่วนภายในที่ถูกเรียกใช้โดยตัวควบคุมที่ทำให้อุณหภูมิเปลี่ยนแปลง


คุณควรปฏิบัติตามการออกแบบที่ช่วยให้การมีเพศสัมพันธ์และ จำกัด หลวมรูปแบบและตัวควบคุมที่เกี่ยวข้องกับงานเดียวและคุณควรใช้หน่วยเป็นจำนวนมาก / ควบคุมตามที่คุณต้องการ ขึ้นอยู่กับขนาดของแอปพลิเคชันของคุณคุณอาจมีมุมมองน้อยกว่าแบบจำลองและคอนโทรลเลอร์ สิ่งนี้คาดว่าจะเกิดขึ้นกับแอปพลิเคชันขนาดใหญ่ การเขียนโปรแกรมเชิงวัตถุที่ดีนั้นมีเอกลักษณ์เฉพาะด้วยการมีเพศสัมพันธ์แบบหลวมการห่อหุ้มการถ่ายทอดและการเกิดความหลากหลาย ไม่ใช่ทุกภาษาที่รองรับ polymorphism ในระดับเดียวกัน (ฟังก์ชั่นวิธีการโอเปอเรเตอร์การบรรทุกเกินพิกัด / การแทนที่)

หากคุณต้องการมีความเข้าใจที่ดีขึ้นเกี่ยวกับการใช้งานสถาปัตยกรรม MVC อย่างถูกต้องให้ศึกษา GoF "รูปแบบการออกแบบ: องค์ประกอบของซอฟต์แวร์ที่ใช้ซ้ำได้ ... " ซึ่งใช้ C ++ และ SmallTalk สำหรับโค้ดตัวอย่าง หนังสือเล่มนี้ไม่ใช่อัลฟ่าและโอเมก้า แต่มันเป็นจุดเริ่มต้นอย่างแน่นอน!

โชคดี!


1

ฉันสมมติว่าตัวอย่างของคุณจะพัฒนาเป็นระบบที่ซับซ้อน

การประยุกต์ใช้:

ผู้ใช้เข้าสู่ระบบ:

  • LoginController

ความรับผิดชอบ แต่เพียงผู้เดียวคือการจัดการการเข้าสู่ระบบใหม่อีกครั้งหรือแจ้งให้ผู้ใช้ทราบผล

อัปโหลดไฟล์

  • UploadController

ฉันถือว่าที่นี่คุณต้องการอัปโหลดไฟล์ประเภทใดก็ได้ หากในภายหลังคุณตัดสินใจที่จะอัปโหลด MP3 และ PDF แล้วฉันจะมีฐานการอัพโหลดไฟล์

ค้นหาไฟล์

  • SearchFileController

สิ่งนี้จะเพียงพอสำหรับความต้องการขั้นพื้นฐาน คุณสามารถมีตัวควบคุมการค้นหาหลายตัวในภายหลังขึ้นอยู่กับความซับซ้อนของตรรกะการค้นหา สิ่งสุดท้ายที่คุณต้องการคือ SearchController เพียงหนึ่งเดียวที่มีวิธีการดำเนินการ 20 วิธีในการค้นหาที่แตกต่างกัน

ออกจากระบบ.

LogoutController-

บางคนอาจคิดว่านี่เป็นยาเกินขนาด แต่ฉันไม่คิดว่ามันจะเป็น ฉันคิดว่ามันสะอาดและแยกจากกันอย่างดี

ถ้าฉันดูโครงสร้างของโครงการนี้ฉันจะรู้ทันทีว่ามันทำอะไรและมีโครงสร้างอย่างไร เพื่อก้าวไปอีกขั้นฉันจะใส่LoginControllerและLogoutControllerแยกพื้นที่

ฉันพัฒนาบางอย่างเช่นนี้มาก่อนและใช้งานได้ดีจริงๆ


ขอบคุณสำหรับการป้อนข้อมูล! มีรหัสการทำงานหรือไม่ ติดอยู่กับบางสิ่ง
Jeff

คุณกำลังประสบปัญหาอะไร
CodeART

ฉันสามารถอัปโหลดหัวเรื่องและวันที่ (ในรูปแบบสตริง) แต่ไม่สามารถอัปโหลดไฟล์ได้เอง (ดูstackoverflow.com/questions/18344614/… )
Jeff

ฉันเป็นนักพัฒนา. NET ขอโทษฉันไม่สามารถช่วยคุณได้
CodeART

1

รหัสส่วนใหญ่ของคุณจะเกิดขึ้นในชั้นธุรกิจใช่ไหม หากเป็นเช่นนั้นสิ่งที่คุณทำจริง ๆ ในคอนโทรลเลอร์ของคุณคือการส่งคืนข้อมูลไปยังมุมมอง

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

จะดีกว่าถ้ามีคอนโทรลเลอร์ต่อหน่วยตรรกะตัวอย่างเช่น AccountController (เข้าสู่ระบบลงทะเบียนออกจากระบบ) FileController (ค้นหาอัปโหลด) และอื่น ๆ


0

โดยทั่วไปคุณอาจกล่าวได้ว่าทุก MODEL มีตัวควบคุมและมุมมองเฉพาะ โดยทั่วไปแล้วฉันหมายความว่านี่เป็นวิธีปฏิบัติที่ดีที่สุด

ด้านแอปพลิเคชัน (เช่นการจัดการผู้ใช้) ควรแปลเป็นบริการแอปพลิเคชันและต้องมีการเรียกใช้โดยคอนโทรลเลอร์ที่ควบคุมด้วยตนเองหรือใช้ตัวควบคุมของคุณ (โดยใช้แอตทริบิวต์ที่ทำให้ฟังก์ชันการทำงาน

โปรดจำไว้ว่าคอนโทรลเลอร์ทั้งหมดควรจัดการกับการทำงานของ CRUD ผ่านโมเดลและใช้มุมมองที่แตกต่างกันสำหรับตัวกรองที่แตกต่างกัน

ในความเห็นของฉันหนึ่งในข้อดีที่สำคัญของ MVC เนื่องจากรูปแบบคือมันมอบวิธีที่ดีที่สุดในการผูกโมเดลและมุมมอง

เกี่ยวกับตัวอย่างที่คุณเพิ่ม: ฉันจะสร้างตัวควบคุม 2 ตัว: ตัวหนึ่งสำหรับการดำเนินการเข้าสู่ระบบของผู้ใช้ทั้งหมด (ลงทะเบียนเข้าสู่ระบบออกจากระบบ ฯลฯ ) และตัวที่สองสำหรับการทำงานของไฟล์ (อัปโหลดและค้นหา) โปรดทราบว่าสิ่งแรกที่ควรสำรองไว้ด้วย Aspect บางอย่างที่เกี่ยวข้องกับฟังก์ชั่นเข้าสู่ระบบและตัวที่สองเป็นตัวควบคุมธรรมดา


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

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