ฉันควรใส่คำขอ API ไว้ที่ MVC ที่ไหน


25

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

แต่จะเกิดอะไรขึ้นถ้าฉันต้องเรียกบริการที่ผู้อื่นเปิดเผยบนเว็บ ตัวอย่างเช่นฉันต้องการเข้าถึง Facebook API เพื่อรับผู้ติดตามทั้งหมดในหน้าของฉันดังนั้นฉันจะวางวิธีการเหล่านี้ไว้ที่ไหน

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

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


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

2
ฐานข้อมูล? แหล่งข้อมูล? มันเป็นเพียงข้อมูล

2
มีความคิดเห็นมากมายเกี่ยวกับสิ่งที่ "MVC" ควรจะเป็นว่าคำถามนี้เป็นนามธรรมเกินไปที่จะตอบ
RemcoGerlich

2
ลองพิจารณาการเรียก API จากโค้ด Javascript ส่วนหน้าของคุณและอย่าให้มันแตะส่วน "MVC" แบ็กเอนด์เลย
RemcoGerlich

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

คำตอบ:


37

โมเดลไม่ จำกัด เฉพาะการโต้ตอบกับฐานข้อมูลโมเดลมีหน้าที่รับผิดชอบในการรับและจัดการข้อมูล

ดังนั้นสำหรับมุมมองและตัวควบคุมของคุณมันไม่ควรสร้างความแตกต่างหากข้อมูลมาจากฐานข้อมูลหรือจากเว็บเซอร์หรือสุ่มทั้งหมดดังนั้นคุณควรทำในรูปแบบ

MVC เป็นรูปแบบการนำเสนอที่แยกเลเยอร์การแสดงต่างกันออกไปเท่านั้น

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

วิธีสาธารณะในแบบจำลองของคุณสามารถมีโครงสร้างแบบนี้ (Pseudo-code) ซึ่งสามารถเรียกใช้โดยคอนโทรลเลอร์ของคุณ:

public MyDataClass getData(int id) {
    WebServiceData wsData = WebService->getData(id);
    DatabaseData dbData = ORM->getData(id);
    return new MyDataClass(wsData, dbData);
}

WebServiceและORMอาจจำเป็นต้องเป็นอินสแตนซ์ของอินเทอร์เฟซที่สามารถแทนที่ด้วย mocks ผ่านการฉีดขึ้น แต่ตัวควบคุมและมุมมองของคุณไม่จำเป็นต้องเปลี่ยนเพื่อการทดสอบ


8
ตัวแบบไม่ควรมีเหตุผลใด ๆ ดังนั้นจึงไม่ต้องโต้ตอบกับสิ่งใดโดยตรง รูปแบบ MVC เรียกร้องให้วางตรรกะทั้งหมดลงในคอนโทรลเลอร์อย่างชัดเจน ตัวควบคุมเหล่านี้ควรติดต่อ DB, API, ฯลฯ ... และปรับปรุงโมเดลตามความจำเป็น สิ่งนี้ทำให้เทคโนโลยีโมเดลของคุณไม่เชื่อเรื่องพระเจ้าและทำให้มั่นใจได้ว่าไม่มีอะไรมากไปกว่ากลไกการจัดเก็บที่สามารถส่งผ่านไปยังมุมมองต่างๆสำหรับการนำเสนอและตัวควบคุมสำหรับการจัดการเพิ่มเติม
CLW

3
@CLW: Model! = ตัวแบบข้อมูล รายละเอียดเพิ่มเติมสามารถพบได้ที่อื่นเช่นstackoverflow.com/a/14045514/124983
Residuum

2
@CLW: ตรรกะทางธุรกิจไม่ควรอยู่ใน M, V หรือ C Models เป็นนามธรรมของแหล่งข้อมูลมุมมองและตัวควบคุมเป็นส่วนต่อประสานผู้ใช้ของคุณ พวกเขาเป็นส่วนต่อพ่วงของแอปพลิเคชันจริงที่คุณกำลังสร้างซึ่งควรเป็น "รหัสเพียง" ซึ่งไม่จำเป็นต้องรู้เกี่ยวกับสิ่งต่าง ๆ เช่นฐานข้อมูลและเว็บ
RemcoGerlich

2
ส่วน "โมเดล" ตีความหลายร้อยวิธีที่แตกต่างกัน ฉันได้รับการสอนเสมอว่าแบบจำลองเป็นตัวแทน รถไฟจำลองเป็นตัวแทนของรถไฟจริงที่มีชิ้นส่วนเคลื่อนไหวเล็ก ๆ ที่เคลื่อนไหวเหมือนกับของจริง โมเดลในแอปของคุณเป็นตัวแทนของระบบและกระบวนการที่คุณกำลังสร้างซอฟต์แวร์เพื่อทดแทน เช่นรุ่นที่มีพฤติกรรม พฤติกรรมนั้นรวม "ตรรกะทางธุรกิจ" ของคุณ ดังนั้นเมื่อคุณไม่สนใจการเข้าถึงข้อมูล CRUD บริสุทธิ์ UI และการทำงานร่วมกันสิ่งที่เหลืออยู่น่าจะเป็น "แบบจำลอง" ของคุณ - คลาสโดเมนกฎเกณฑ์ทางธุรกิจและอื่น ๆ
anaximander

1
@RemcoGerlich ฉันไม่ได้พูดอะไรเกี่ยวกับตรรกะทางธุรกิจ ฉันเพียง แต่กล่าวว่าเนื่องจากการตีความส่วนใหญ่ของ MVC เรียกร้องให้แบบจำลองนั้นไม่มีอะไรมากไปกว่าโครงสร้างอย่างง่ายที่แสดงสถานะแอปพลิเคชันของคุณว่าความรับผิดชอบในการติดต่อ DB, API และอื่น ๆ ... ไม่ควรอยู่ภายในแบบจำลอง ตรรกะฟรี หน้าที่ในการสื่อสารกับฐานข้อมูลควรอยู่บนคอนโทรลเลอร์หรือวัตถุอื่นที่จัดการโดยคอนโทรลเลอร์
CLW

12

มีความเข้าใจผิดทั่วไปเกี่ยวกับ M, V และ C ไม่เกี่ยวกับบทบาทที่พวกเขาทำ แต่พวกเขาคืออะไร

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

ในเว็บเฟรมเวิร์ก OTOH พวกมันมักจะถูกมองว่าเป็นเลเยอร์โดยที่พวกมันเป็นเพียงหนึ่งในนั้นและข้อตกลงส่วนใหญ่เกี่ยวกับการครอบคลุมระดับนามธรรมย่อยบางส่วน: "เลเยอร์โมเดลย่อบทคัดย่อฐานข้อมูล", "เลเยอร์มุมมอง กระบวนการเลเยอร์ที่ผู้ใช้ป้อน "

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


1
ตกลง: โมเดลควรจะเป็นโดเมนปัญหาทั้งหมดเสมอ ในแอพที่ซับซ้อนมันควรจะเป็นรหัสจำนวนมากเสมอ พวกเขาประกอบด้วยรหัสทั้งหมดที่จะไม่เปลี่ยนแปลงหากคุณเปลี่ยนส่วนติดต่อผู้ใช้ (พูดจากเว็บไซต์เพื่อ GUI หรือแม้กระทั่งการประยุกต์ใช้บรรทัดคำสั่ง) คิดว่าคอมไพเลอร์ มีเพียงส่วนน้อยมากของรหัสที่จะเปลี่ยนหากคุณเปลี่ยนจาก UI บรรทัดคำสั่งเป็น GUI หรือแม้กระทั่งเว็บ UI ความกล้าทั้งหมดของแอปพลิเคชั่นดังกล่าวเป็นแบบจำลอง
Kevin Cathcart

1
ในการใช้คำศัพท์ Smalltalk ดั้งเดิมทุกการควบคุม UI ในส่วนต่อประสานมีรูปแบบมุมมองและตัวควบคุมของตัวเอง
RemcoGerlich

5

ส่วนหนึ่งของความยากลำบากในการพูดคุยกับ MVC ก็คือกลุ่มต่าง ๆ ได้เลือกที่จะให้มีความหมายต่างกัน การใช้งาน MVC ที่ใช้ในการพูดแอพ Rails นั้นแทบจะไม่เป็นที่รู้จักสำหรับคนที่กำลังเขียนแอพ Swing อยู่ เท่าที่ MVC ยังคงเป็นสิ่งที่กำหนดไว้มันเป็นชุดของหลักการชี้นำ (แยกแอปพลิเคชันหลักออกจากการแสดงด้วยภาพจัดเตรียมกลไกที่ยืดหยุ่นเพื่อให้ทั้งสองถูกดิ่งเข้าด้วยกัน) ซึ่งสามารถนำมาใช้ในหลากหลาย วิธี

แท้จริงแล้วมีแนวโน้มที่จะให้ชื่อต่าง ๆ ที่ได้มาจากการออกแบบ MVC แตกต่างกัน (ดูบทความนี้โดย Martin Fowlerสำหรับการอภิปรายในเรื่องนี้) หรือแม้กระทั่งยอมแพ้ในการตั้งชื่อที่แม่นยำ - ตัวอย่าง AngularJS อธิบายตัวเองว่าเป็น กรอบ.

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


2

ที่นี่แบบจำลองมีการอธิบายดังนี้:

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

ฉันว่าตัวควบคุมอาจรวมถึงตรรกะของการเรียกใช้บริการหรือเรียกServiceวัตถุแยกต่างหาก หากบริการแยกจากกันคุณสามารถสร้างการทดสอบได้ง่ายขึ้นเช่นถ้าไม่มีการเชื่อมต่อกับบริการผ่านเครือข่ายเป็นไปได้บางคนTestServiceสามารถให้คำตอบจากServiceภายในเครื่อง

นอกจากนี้ให้ตรวจสอบคำตอบนี้เพื่อแนะนำว่าคอนโทรลเลอร์เรียกบริการ


2

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

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

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

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


4
ฉันคิดว่าเมื่อคุณพูดว่า "model" ที่นี่คุณหมายถึง "viewmodel" ซึ่ง IMO เป็นสิ่งที่แยกจากกัน viewmodel ได้รับข้อมูลจากตัวควบคุมไปยังมุมมองและเช่นนี้เป็นรายละเอียดการใช้งานของมุมมองหรือมุมมองของการสื่อสารระหว่างมุมมองและตัวควบคุมที่ไม่พอดีกับจริง ๆ (ขึ้นอยู่กับว่าคุณเห็น) "Model" ใน MVC หมายถึงโมเดลระบบ - การแสดงระบบที่รวมข้อมูลโครงสร้างและพฤติกรรมของมัน ตัวแบบคือสถานะและตรรกะ ตัวควบคุมเป็นสิ่งที่ทำให้ตรรกะในการทำงานและสถานะการเปลี่ยนแปลงเมื่อมีการจัดการมุมมอง
anaximander

@anaximander ไม่ฉันหมายถึงแบบจำลองในการตีความอย่างเข้มงวดของ MVC (ดู Wikipedia, Microsoft MVC, รูปแบบการออกแบบ Head First, ฯลฯ ... ) ในกรณีเหล่านั้นแบบจำลองไม่มีอะไรมากไปกว่าโครงสร้างที่ง่ายสำหรับการส่งผ่านข้อมูล รอบ ๆ และไม่มีสิ่งนั้นเป็นโมเดลวิว ในขณะที่การนำ Microsoft MVC ไปใช้จะเพิ่มคุณลักษณะที่หลากหลายให้กับแบบจำลองสิ่งนี้ก็เพื่อความสะดวกมากกว่าสิ่งอื่นใด ในตอนท้ายวัตถุประสงค์ของรูปแบบ MVC ก็เพื่ออำนวยความสะดวกในการฝึกฝนการแยกโค้ดและผลข้างเคียงที่ จำกัด
CLW

1

อาจเป็นวิธีที่นี่ แต่นี่คือความรู้สึกของฉันเกี่ยวกับ WebApps และทำงานกับ [ซับซ้อน] API ระยะไกลในหลายกรณี:

ฉันจะทำให้มันเป็นคลาส (เช่นห้องสมุดของวิธีการลดข้อมูล) แทนรูปแบบ (เช่นฟังก์ชั่นสแต็คของฟังก์ชั่นการลดข้อมูล) ดูเหมือนว่ามันจะมีความโปร่งใสมากขึ้นไม่เชื่อเรื่องตรรกะ / schema มากขึ้นและคุณสามารถใช้มันได้ทุกที่โดยไม่ต้องโหลด -> เรียกรุ่น / คอนโทรลเลอร์เองทุกครั้งที่คุณต้องการใช้ ตรรกะยังคงถูกแยกออกดาต้าพอยน์ยังคงยืดหยุ่นและดูเหมือนว่าจะเปิดกว้างสำหรับการทำงานร่วมกันในกรณีแปลก ๆ เช่นการซ้อน clientAJAX-> appJSON-> appLIB-> remoteAPI-> remoteAPI-> remoteJSON ฯลฯ เพื่อสำรวจจุดปลายทางทางอ้อม

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