MVC กับ MVVM ต่างกันอย่างไร? [ปิด]


1312

มีความแตกต่างระหว่างรูปแบบ "Model View Controller" มาตรฐานและรูปแบบ Model / View / ViewModel ของ Microsoft หรือไม่


54
โปรดทราบว่าในขณะที่ MVVM ได้รับการประกาศเกียรติคุณจาก Microsoft ผู้พัฒนาและโครงการที่ไม่ใช่ Microsoft จำนวนมากได้เริ่มนำรูปแบบนี้มาใช้ ความคิดเห็นนี้มาถึงคุณโดยแผนก spite-the-MS-haters
BoltClock

1
การทำงานกับ MVVM เป็นเวลานานแปรงแรกของฉันกับ MVC น่าผิดหวังจนฉันรู้ว่าฉันสามารถส่ง ViewModels ไปมาในเบราว์เซอร์ได้โดยใช้เทคนิคการผูกที่พบใน MVVM แต่ดังที่โจเอลกล่าวไว้ข้างต้นวิธีเดียวที่จะได้รับการคืนสถานะจากเบราว์เซอร์คือการโพสต์การเปลี่ยนแปลงในแบบฟอร์ม (ซึ่งใช้ชื่อ / ค่า) คู่ หากคุณไม่เข้าใจประเด็นนี้อย่างดี คุณจะมีช่วงเวลาที่ยากลำบากใน MVC เพียงแค่ดูที่คอนโทรลเลอร์ว่าเป็นหัวฉีดพึ่งพาสำหรับมุมมองและคุณพร้อมแล้ว
John Peters

2
คำถามที่ถูกโหวตขึ้นในระดับสูง [รูปแบบการออกแบบ] ฉันอยากจะแนะนำการใช้ไดอะแกรมในคำตอบ
Ricardo

4
นี่เป็นบทความเก็บถาวรของบทความของ Joel: web.archive.org/web/20150219153055/http://joel.inpointform.net/ …
Tereza Tomcova

1
ซึ่งแตกต่างจากวิธี MVC, ViewModel ไม่ใช่ตัวควบคุม มันทำหน้าที่เป็นสารยึดเกาะที่ผูกข้อมูลระหว่างมุมมองและรูปแบบแทน ในขณะที่รูปแบบ MVC ได้รับการออกแบบมาโดยเฉพาะเพื่อสร้างการแยกข้อกังวลระหว่างรูปแบบและมุมมองรูปแบบ MVVM พร้อมการเชื่อมโยงข้อมูลได้รับการออกแบบมาโดยเฉพาะเพื่อให้มุมมองและแบบจำลองสามารถสื่อสารกันโดยตรง hackernoon.com/…
blueray

คำตอบ:


684

MVC / MVVM ไม่ใช่/ หรือตัวเลือก

รูปแบบทั้งสองครอบตัดขึ้นในวิธีที่ต่างกันทั้งในการพัฒนา ASP.Net และ Silverlight / WPF

สำหรับ ASP.Net นั้น MVVM ถูกใช้เพื่อเชื่อมโยงข้อมูลสองทิศทางภายในมุมมอง นี่คือการใช้งานฝั่งไคลเอ็นต์ (เช่นใช้ Knockout.js) MVC ในมืออื่น ๆ เป็นวิธีการของความกังวลแยกบนฝั่งเซิร์ฟเวอร์

สำหรับ Silverlight และ WPF รูปแบบ MVVM ครอบคลุมมากกว่าและสามารถดูเหมือนจะทำหน้าที่แทน MVC (หรือรูปแบบอื่น ๆ ของการจัดระเบียบซอฟต์แวร์ในความรับผิดชอบแยกต่างหาก) หนึ่งสมมติฐานที่มักออกมาในรูปแบบนี้คือการที่ViewModelเพียงแทนที่ตัวควบคุมในMVC(เช่นถ้าคุณก็สามารถใช้แทนVMสำหรับCในตัวย่อและทุกคนจะได้รับการอภัย) ...

ViewModel ไม่จำเป็นต้องแทนที่ตัวควบคุมแยกต่างหาก

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

* หมายเหตุ: ในทางปฏิบัติตัวควบคุมจะลบตรรกะส่วนใหญ่ออกจาก ViewModel ซึ่งต้องใช้การทดสอบหน่วย จากนั้น VM จะกลายเป็นคอนเทนเนอร์ที่ไม่ต้องใช้การทดสอบ สิ่งนี้เป็นสิ่งที่ดีเนื่องจาก VM เป็นเพียงแค่บริดจ์ระหว่างผู้ออกแบบและ coder ดังนั้นควรรักษาให้ง่าย

แม้แต่ใน MVVM ตัวควบคุมมักจะมีตรรกะการประมวลผลทั้งหมดและตัดสินใจว่าจะแสดงข้อมูลใดในมุมมองที่ใช้แบบจำลองมุมมองใด

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

แนวทาง MVCVM พื้นฐานที่เราติดตามคือ:

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

นอกจากนี้เรายังตั้งข้อสังเกตอีกว่ากรอบการทำงานของโค้ดเอ็นจิน Sculptureใช้ MVVM และรูปแบบคล้ายกับ Prism และยังใช้การควบคุมอย่างกว้างขวางเพื่อแยกตรรกะการใช้เคสทั้งหมด

อย่าถือว่าตัวควบคุมล้าสมัยโดย View-models

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

ประโยชน์เพิ่มเติมของการใช้แบบจำลอง MVCVM คือเฉพาะวัตถุตัวควบคุมที่จำเป็นต้องมีอยู่ในหน่วยความจำสำหรับอายุการใช้งานของแอปพลิเคชันและตัวควบคุมประกอบด้วยรหัสส่วนใหญ่และข้อมูลสถานะน้อย (เช่นค่าใช้จ่ายหน่วยความจำขนาดเล็ก) สิ่งนี้ทำให้แอพที่ใช้หน่วยความจำน้อยกว่าโซลูชั่นที่ต้องรักษารูปแบบการดูและเหมาะสำหรับการพัฒนาอุปกรณ์พกพาบางประเภท (เช่น Windows Mobile โดยใช้ Silverlight / Prism / MEF) แน่นอนว่าสิ่งนี้ขึ้นอยู่กับประเภทของแอปพลิเคชั่นเนื่องจากคุณอาจจำเป็นต้องเก็บ VMs ที่แคชเป็นครั้งคราวไว้เพื่อการตอบสนอง

หมายเหตุ: โพสต์นี้ได้รับการแก้ไขหลายครั้งและไม่ได้เจาะจงคำถามแคบ ๆ ที่ถามดังนั้นฉันได้อัปเดตส่วนแรกเพื่อครอบคลุมในตอนนี้ด้วย การอภิปรายส่วนใหญ่ในความคิดเห็นด้านล่างเกี่ยวข้องกับ ASP.Net เท่านั้นและไม่ใช่ภาพที่กว้างขึ้น โพสต์นี้มีวัตถุประสงค์เพื่อครอบคลุมการใช้ MVVM ในวงกว้างใน Silverlight, WPF และ ASP.Net และพยายามกีดกันผู้คนจากการแทนที่ตัวควบคุมด้วย ViewModels


8
@Tomasz Zielinski: จริง แต่ "ที่พวกเขาจะใช้" ไม่ใช่คำถาม (หรือจุดของคำตอบของฉัน) ประเด็นของฉันคือตัวควบคุมยังคงมีประโยชน์ใน MVVM
Gone Coding

58
ฉันเห็นด้วย. ความคิดเห็นของฉันเกิดจากการแจ้งเตือนอย่างฉับพลันและไม่ใช่เพราะฉันไม่เห็นด้วยกับคุณ
Tomasz Zieliński

นอกจากนี้เรายังใช้ตัวควบคุมเพื่อควบคุม "โฟลว์" ของมุมมองใน UI ที่คล้ายกับตัวช่วยสร้าง
riezebosch

3
@ จัสติน: ฉันเห็นข้อความของประโยคนั้นคลุมเครือเล็กน้อย ฉันหมายถึงการทดสอบหน่วยสำหรับส่วนประกอบทั้งหมดนั้นรองรับได้ง่ายกว่าไม่ใช่แค่ปรับปรุงการทดสอบของ ViewModels (ซึ่งอย่างที่คุณชี้ให้เห็นไม่ได้ทำใน MVCVM มากนัก ... ซึ่งเป็นสิ่งที่คุณต้องการ) ประโยชน์ที่แท้จริงของตัวควบคุมคือคุณจะลบข้อกำหนดส่วนใหญ่สำหรับการทดสอบออกจาก ViewModel (ที่ซึ่งผู้คนกำลังควบคุมตรรกะของตัวควบคุม) และวางไว้ในตำแหน่งที่สามารถทดสอบได้ (ส่วนใหญ่เป็นตัวควบคุมและรุ่น) ความคิดเห็นที่ใช้ซ้ำนั้นเป็นสิ่งเฉพาะสำหรับ VMs ในประโยคนั้น ฉันแก้ไขมันแล้ว
Gone Coding

7
@TomaszZielinski M (MVVM) C
Mohamed Emad

273

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

เมื่อพวกเขาเติบโตในความซับซ้อนในช่วงกลางปี ​​2000 รูปแบบการออกแบบซอฟต์แวร์ MVC - ซึ่งได้รับการอธิบายครั้งแรกในปี 1970 - เริ่มนำไปใช้กับเว็บแอปพลิเคชัน คิดว่าฐานข้อมูลหน้า HTML และรหัสอยู่ระหว่าง ลองปรับแต่งเล็กน้อยเพื่อไปที่ MVC: สำหรับ»ฐานข้อมูล«สมมติว่าฐานข้อมูลพร้อมรหัสอินเทอร์เฟซ สำหรับ»หน้า HTML «สมมติว่ามีแม่แบบ HTML พร้อมรหัสการประมวลผลแม่แบบ สำหรับ»โค้ดในระหว่าง«ลองสมมติว่าผู้ใช้รหัสคลิกเพื่อกระทำอาจส่งผลต่อฐานข้อมูลทำให้เกิดมุมมองอื่นที่จะแสดง นั่นคืออย่างน้อยสำหรับวัตถุประสงค์ของการเปรียบเทียบนี้

เราคงไว้ซึ่งคุณสมบัติหนึ่งของเนื้อหาเว็บนี้ไม่ใช่ในวันนี้ แต่มันมีอยู่เมื่อสิบปีที่แล้วเมื่อ JavaScript มีความน่ารำคาญต่ำต้อยน่ารังเกียจซึ่งโปรแกรมเมอร์ตัวจริงทำได้ดีเพื่อหลีกเลี่ยง: หน้า HTML นั้นเป็นใบ้และแฝง . เบราว์เซอร์เป็นไคลเอ็นต์แบบ thin หรือหากคุณเป็นไคลเอ็นต์ที่ไม่ดี ไม่มีความฉลาดในเบราว์เซอร์ กฎการโหลดซ้ำหน้าเต็ม "มุมมอง" ถูกสร้างขึ้นใหม่ทุกครั้ง

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

และวิธีเดสก์ท็อปที่หลากหลายน่าจะเป็นที่มาของคำย่อตัวที่สองคือ MVVM อย่าหลงกลโดยตัวอักษรโดยการละเลยของตัวควบคุม C. ยังคงมีอยู่ พวกเขาต้องเป็น ไม่มีอะไรถูกลบ เราเพิ่งเพิ่มสิ่งหนึ่ง: statefulness ข้อมูลที่แคชบนไคลเอนต์ (และพร้อมด้วยความฉลาดในการจัดการข้อมูลนั้น) ข้อมูลนั้นโดยพื้นฐานแล้วแคชบนไคลเอนต์ตอนนี้ถูกเรียกว่า» ViewModel « มันคือสิ่งที่ช่วยให้การโต้ตอบที่หลากหลาย และนั่นคือมัน

  • MVC = รูปแบบตัวควบคุมมุมมอง = การสื่อสารทางเดียวเป็นหลัก = การโต้ตอบที่ไม่ดี
  • MVVM = รูปแบบตัวควบคุมแคชมุมมอง = การสื่อสารสองทาง = การโต้ตอบที่หลากหลาย

เราสามารถเห็นได้ว่าด้วย Flash, Silverlight และที่สำคัญที่สุดคือ JavaScript เว็บได้นำ MVVM มาใช้ เบราว์เซอร์ไม่สามารถถูกเรียกว่า thin client ได้อย่างถูกกฎหมาย ดูความสามารถในการโปรแกรมของพวกเขา ดูการใช้หน่วยความจำของพวกเขา ดูการโต้ตอบแบบจาวาสคริปต์ทั้งหมดบนเว็บเพจที่ทันสมัย

โดยส่วนตัวแล้วฉันพบว่าทฤษฎีและธุรกิจตัวย่อเข้าใจง่ายขึ้นโดยดูจากสิ่งที่กล่าวถึงในความเป็นจริงที่เป็นรูปธรรม แนวคิดเชิงนามธรรมมีประโยชน์โดยเฉพาะอย่างยิ่งเมื่อแสดงให้เห็นถึงวัตถุที่เป็นรูปธรรมดังนั้นความเข้าใจอาจมาเต็มวง

 


47
MVC ไม่ได้มาจากบนเว็บ Trygve Reenskaug เปิดตัว MVC ใน Smalltalk-76 ในปี 1970
Arialdo Martini

11
แม้ว่ามันจะถูกเปลี่ยนเป็น "MVC ได้รับความนิยมผ่านการออกแบบเว็บแอปพลิเคชัน" ฉันจะยืนยันว่านี่เป็นการเก็งกำไรโดยไม่มีการอ้างอิงที่เหมาะสม
Dan Bechard

4
Arialdo: ขอบคุณฉันไม่รู้เกี่ยวกับ Smalltalk-76 (เล่นกับของเล่นอื่น ๆ ก่อนหน้านี้ :) ตลกกันมันน่าสนใจว่าแนวคิดเหล่านี้อายุเท่าไหร่ - @Dan สิ่งที่ฉันเขียนคือ: "[MVC] อาจเคยอยู่ที่นั่นมาก่อน [เว็บ] แต่เว็บก็เป็นที่นิยมในหมู่นักพัฒนาเว็บ" ฉันยังคิดว่าถูกต้อง ฉันไม่ได้กล่าวถึงเรื่องนี้ แต่ฉันไม่รู้สึกว่าต้องการเพราะ MVC เป็นที่นิยมเป็นส่วนหนึ่งของประสบการณ์ส่วนตัวของฉันเมื่อฉันเริ่มเป็นนักพัฒนาเว็บเมื่อต้นทศวรรษที่ผ่านมา Apache Struts เป็นที่นิยมในตอนนั้นพร้อมกับถั่วจำนวนมากสำหรับ MVC
Lumi

5
MVC ไม่ใช่ "การสื่อสารทางเดียวเป็นหลัก" เนื่องจากปัญหาเบราว์เซอร์ได้รับและโพสต์ตลอดเวลา ทั้งได้รับและโพสต์สามารถเปลี่ยนค่าของเขตข้อมูลที่พบในสตริงแบบสอบถาม สิ่งนี้ทำให้เบราว์เซอร์มีโอกาสเพียงพอที่จะส่งข้อมูลกลับไปยังคอนโทรลเลอร์ MVC สร้างขึ้นจาก HTTP 1.0 ซึ่งมีการสื่อสารสองทางอยู่ในใจเสมอ
John Peters

13
ขอบคุณ Lumi สิ่งนี้ทำให้ฉันรู้สึกได้มากกว่าคำตอบอื่น ๆ ถูกต้องหรือไม่ ฉันไม่รู้. แต่จากมุมมองของฉันมันเป็นอย่างน้อยที่สอดคล้องกัน
gcdev

175

MVVM Model-View ViewModelนั้นคล้ายกับ MVC, Model-View Controller

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

Russel Eastบล็อกอภิปรายรายละเอียดเพิ่มเติม เหตุใด MVVM จึงแตกต่างจาก MVC


81
ประโยค "คอนโทรลเลอร์ถูกแทนที่ด้วย View Model" ไม่ถูกต้อง ใน MVVM บทบาทของตัวควบคุมคือ databinding (หรือผูกมัดตามแบบแผนถ้าคุณใช้สิ่งนั้น)
DaniCE

9
MVVM จะเข้าท่าเมื่อใช้การผูกข้อมูลแบบสองทางของ WPF เท่านั้น มิฉะนั้น MVC / MVP ฯลฯ จะเพียงพอ
เจฟฟ์

266
@DaniCE: จอชสมิ ธ :If you put ten software architects into a room and have them discuss what the Model-View-Controller pattern is, you will end up with twelve different opinions. …
SLL

7
@OmShankar ที่ 11 ไม่ใช่ของคุณ มีทั้งหมด 10 คนและ 12 ความคิดเห็นทั้งหมด ภาษิตมีไว้เพื่อบอกเป็นนัยว่าคำจำกัดความของรูปแบบเหล่านี้เปิดกว้างต่อการตีความว่าอย่างน้อยสองคนจะสับสนมากพอที่จะมีความคิดเห็นมากกว่าหนึ่งข้อ
Dan Bechard

7
@DaniCE นี่เป็นจุดเชื่อมโยงข้อมูลของ WPF และ Microsoft ประดิษฐ์ MVVM โดยที่สามารถข้ามคอนโทรลเลอร์ได้อย่างสมบูรณ์ (อ้างว่าประโยค "คอนโทรลเลอร์ถูกแทนที่ด้วย View Model" ไม่ถูกต้องเนื่องจากมี ตัวควบคุมที่อยู่เบื้องหลังคือการอ้างคำสั่ง "ภาษาระดับสูงแทนที่การใช้รหัสเครื่องที่อ่านง่ายกว่า" จะไม่ถูกต้องเพราะเบื้องหลังภาษาเครื่องยังคงใช้อยู่ ... )
yoel halb

91

ประการหนึ่ง MVVM คือความก้าวหน้าของรูปแบบ MVC ซึ่งใช้ XAML เพื่อจัดการกับการแสดงผล บทความนี้สรุปบางส่วนของทั้งสอง

แรงผลักดันหลักของสถาปัตยกรรม Model / View / ViewModel น่าจะเป็นที่ด้านบนของข้อมูล ("the Model") มีอีกชั้นขององค์ประกอบที่ไม่ใช่ภาพ ("the ViewModel") ที่แมปแนวคิดของข้อมูลอย่างใกล้ชิดมากขึ้น ตามแนวคิดของมุมมองของข้อมูล (” มุมมอง”) เป็น ViewModel ที่ View เชื่อมโยงไม่ใช่ Model โดยตรง


20
ฉันคิดว่าย่อหน้าที่คุณยกมาจะรวมเป็น IMHO แง่มุมหนึ่งของ ViewModel คือมันเป็นรุ่นที่มีการแบน / เปลี่ยนแปลงสำหรับมุมมอง รูปแบบ MV * อื่น ๆ อีกมากมายเชื่อมโยงกับโมเดลจริง
Daniel Auger

1
"รูปแบบ MV * อื่น ๆ อีกมากมายผูกกับแบบจำลองของจริงอีกครั้ง" จริงหรือไม่ฉันคิดว่ามุมมองควรผูกกับตัวควบคุมใน MVC เสมอไม่ว่าจะเกิดอะไรขึ้น
PlagueHammer

9
น็อคเทิร์: ใน MVC แบบคลาสสิกวิวไม่ได้เกี่ยวข้องอะไรกับคอนโทรลเลอร์มากนัก แต่ส่วนใหญ่ผูกกับรุ่น ลองคิดว่ามันเป็นหุ่นยนต์ - โมเดลแสดงตำแหน่งของข้อต่อของหุ่นยนต์ View เป็นจอ LCD ที่คุณเห็นหุ่นยนต์ตัวควบคุมเป็นเช่นคีย์บอร์ด ในการตั้งค่ามุมมองนั้นขึ้นอยู่กับรุ่นเช่นตำแหน่งเชิงพื้นที่ของหุ่นยนต์ที่คุณสามารถเห็นบนจอภาพเป็นการแสดงแบบโดยตรง
Tomasz Zieliński

@Notcte สิ่งที่ดานิเอลดูเหมือนจะพูดคือในขณะที่ MV ทั้งหมดควรใช้ VM แยกต่างหาก แต่นักพัฒนาหลายคนก็เพิกเฉยและส่งแบบจำลองจริงและในความเป็นจริงไม่มีอะไรในสเปคของตัวอย่างของ MVC ไม่อนุญาต แต่ใน MVVM VM จะต้องรับผิดชอบต่อการเปลี่ยนแปลงระหว่างโมเดลและมุมมอง
yoel halb

ฉันจะบอกว่ามันเป็นแบบนี้: รูปแบบคือสิ่งที่แนบกับ DB schema เมื่อมีการเรียกใช้แบบสอบถามมันสามารถฉายข้อมูลเป็นประเภทที่รัดกุมที่เลเยอร์โมเดล viewmodel คือคอลเล็กชันของสิ่งต่าง ๆ รวมถึงโมเดลวัตถุ แต่สามารถและไม่เก็บสถานะมุมมองที่เกี่ยวกับข้อมูล คอนโทรลเลอร์เป็นเพียงตำรวจจราจรระหว่าง viewmodel และมุมมองและแน่นอนว่ามุมมองเกี่ยวข้องกับสถานะมุมมองเท่านั้น
John Peters

52

ไมโครซอฟท์มีให้คำอธิบายแบบ MVVM ๆ ในสภาพแวดล้อมของ Windows ที่นี่

นี่คือส่วนที่สำคัญ:

ในรูปแบบการออกแบบ Model-View-ViewModel แอพประกอบด้วยส่วนประกอบทั่วไปสามประการ ป้อนคำอธิบายรูปภาพที่นี่

  • รุ่น : นี่เป็นรูปแบบข้อมูลที่แอปของคุณใช้ ตัวอย่างเช่นในแอพแชร์รูปภาพเลเยอร์นี้อาจแสดงชุดของรูปภาพที่มีอยู่ในอุปกรณ์และ API ที่ใช้ในการอ่านและเขียนไปยังไลบรารีรูปภาพ

  • มุมมอง : โดยทั่วไปแอปจะประกอบด้วย UI หลายหน้า แต่ละหน้าที่แสดงต่อผู้ใช้คือมุมมองในคำศัพท์ MVVM มุมมองคือรหัส XAML ที่ใช้เพื่อกำหนดและกำหนดลักษณะที่ผู้ใช้เห็น ข้อมูลจากแบบจำลองจะแสดงต่อผู้ใช้และเป็นหน้าที่ของ ViewModel ในการป้อนข้อมูล UI นี้ตามสถานะปัจจุบันของแอป ตัวอย่างเช่นในแอปแชร์รูปภาพมุมมองนั้นจะเป็น UI ที่แสดงรายชื่ออัลบั้มในอุปกรณ์ให้กับผู้ใช้รูปภาพในอัลบั้มและอาจเป็นอีกรูปแบบหนึ่งที่แสดงรูปภาพเฉพาะของผู้ใช้

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


7
โปรดทราบว่าแม้ว่าการอ้างอิงบทความจะนำไปใช้กับการพัฒนาด้วย Microsoft Stack - โดยเฉพาะ Windows Phone - และ XAML แต่ก็ไม่จำเป็นต้องเป็น
Richard Nalezynski

คำตอบนี้เน้นปัญหาด้วยชื่อ "MVVM" - ควรเป็น "VVMM" หรือ "MVMV" - MV-VM มีความสัมพันธ์ที่ผิดทาง!
Etherman

45

ฉันคิดว่าหนึ่งในความแตกต่างที่สำคัญคือใน MVC, V ของคุณอ่าน M ของคุณโดยตรงและผ่าน C เพื่อจัดการข้อมูลในขณะที่ MVVM VM ของคุณทำหน้าที่เป็นพร็อกซี M และให้การทำงานที่มีให้คุณ โวลต์

ถ้าฉันไม่ได้เต็มไปด้วยขยะฉันประหลาดใจที่ไม่มีใครสร้างไฮบริดโดยที่ VM ของคุณเป็นเพียงพร็อกซี M และ C ก็มีฟังก์ชั่นทั้งหมด


1
+1 คำนี้เป็นคำที่ถูกต้องที่ฉันคิดว่า แต่เกี่ยวกับการสร้างไฮบริด M-MProxy-VC นั่นไม่ใช่การแยกมากเกินไปหรือ ฉันคิดว่ามันคงเพียงพอที่จะใช้ MVC ในขณะที่ M เป็นรุ่นที่มีการรองรับการเชื่อมเต็มรูปแบบ ;)
ktutnik

2
+1 ตามที่ฉันแสดงความคิดเห็นข้างต้นฉันคิดว่า MVC ใช้เพื่อออกแบบแอปพลิเคชั่นทั้งหมด (เว็บ) ในขณะที่ MVVM ใช้ภายในองค์ประกอบ View ของ MVC
Tomasz Zieliński

23
@ktutnik: รุ่นมักจะอยู่บนเซิร์ฟเวอร์ในขณะที่ ViewModel อาศัยอยู่บนไคลเอนต์ ดังนั้นจึงเป็นไปไม่ได้ที่ HTML จะผูกเข้ากับโมเดลฝั่งเซิร์ฟเวอร์โดยตรง ดังนั้นเราจึงจำเป็นต้องใช้ ModelView ซึ่งทำหน้าที่เป็นชุดการทำงานของข้อมูลที่ไม่ได้บันทึกไว้ซึ่งแยกออกมาจากตัวแบบโดยใช้ AJAX / JSON
Tomasz Zieliński

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

3
ฉันขอโทษ แต่ไม่เห็นด้วยกับการตีความ MVVM ViewModel ไม่มีความคิดเกี่ยวกับมุมมองหรือมุมมองที่จะมีลักษณะหรือวิธีการที่จะตอบสนองและรูปแบบเช่นเดียวกันไม่มีความคิดเกี่ยวกับ ViewModel ในความเป็นจริงมุมมองไม่ควรรู้รูปแบบเช่นกันเพียงแค่ ViewModel โมเดลควรแสดงข้อมูลและสถานะแอปพลิเคชัน ViewModel ควรแปลสถานะเป็นข้อมูลที่มีความสามารถใน UI (ฉันแนะนำดั้งเดิมทั้งหมด ณ จุดนี้) และมุมมองควรตอบสนองต่อการแปล ViewModels ข้อมูลมักจะเหมือนกัน แต่ควรห่อและส่งซ้ำผ่าน ViewModel และไม่มีคอนโทรลเลอร์
Michael Puckett II

24

MVC เป็นสภาพแวดล้อมที่มีการควบคุมและ MVVM เป็นสภาพแวดล้อมที่มีปฏิกิริยา

ในสภาพแวดล้อมที่มีการควบคุมคุณควรมีรหัสน้อยลงและเป็นแหล่งของตรรกะทั่วไป ซึ่งควรอยู่ภายในคอนโทรลเลอร์เสมอ อย่างไรก็ตาม; ในโลกเว็บ MVC จะแบ่งออกเป็นตรรกะการสร้างมุมมองและดูตรรกะแบบไดนามิกได้อย่างง่ายดาย การสร้างใช้งานบนเซิร์ฟเวอร์และใช้ชีวิตแบบไดนามิกกับลูกค้า คุณเห็นสิ่งนี้มากกับ ASP.NET MVC รวมกับ AngularJS ในขณะที่เซิร์ฟเวอร์จะสร้างมุมมองและส่งผ่านแบบจำลองและส่งไปยังไคลเอนต์ ไคลเอนต์จะโต้ตอบกับมุมมองซึ่งกรณี AngularJS ขั้นตอนในการเป็นตัวควบคุมภายใน เมื่อส่งรุ่นหรือรุ่นใหม่จะถูกส่งกลับไปยังเซิร์ฟเวอร์คอนโทรลเลอร์และจัดการ (ดังนั้นวัฏจักรยังคงดำเนินต่อไปและมีการแปลอื่น ๆ จำนวนมากของการจัดการนี้เมื่อทำงานกับซ็อกเก็ตหรือ AJAX ฯลฯ แต่เหนือสถาปัตยกรรมทั้งหมดเหมือนกัน)

MVVM เป็นสภาพแวดล้อมแบบรีแอคทีฟซึ่งหมายความว่าคุณมักจะเขียนโค้ด (เช่นทริกเกอร์) ซึ่งจะเปิดใช้งานตามบางเหตุการณ์ ใน XAML ที่ MVVM เจริญเติบโตสิ่งนี้ทำได้อย่างง่ายดายด้วยกรอบข้อมูลที่สร้างขึ้น แต่ดังกล่าวจะทำงานบนระบบใด ๆ ในมุมมองใด ๆ ด้วยภาษาการเขียนโปรแกรมใด ๆ มันไม่ได้เป็น MS เฉพาะ ViewModel fires (โดยปกติแล้วคุณสมบัติจะเปลี่ยนเหตุการณ์) และมุมมองจะตอบสนองต่อเหตุการณ์นั้นตามสิ่งที่ทริกเกอร์ที่คุณสร้าง สิ่งนี้สามารถรับได้ทางเทคนิค แต่บรรทัดล่างสุดคือมุมมองไร้สัญชาติและไม่มีตรรกะ มันเพียงแค่เปลี่ยนสถานะตามค่า นอกจากนี้ ViewModels ไร้สัญชาติด้วยตรรกะน้อยมากและรุ่นเป็นรัฐที่มีตรรกะเป็นศูนย์เป็นหลักเพราะพวกเขาควรจะรักษาสถานะ ฉันอธิบายสิ่งนี้เป็นสถานะแอปพลิเคชัน (รุ่น), ตัวแปลสถานะ (ViewModel) และสถานะภาพ / การโต้ตอบ (ดู)

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

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

นี่เป็นตัวอย่างเล็กน้อย: สมมติว่าคุณต้องการให้มีเมนูสไลด์เข้ามาในการกดปุ่ม ใน MVC คุณจะมีการดำเนินการ MenuPressed ในอินเทอร์เฟซของคุณ คอนโทรลเลอร์จะรู้เมื่อคุณคลิกปุ่มเมนูจากนั้นบอกให้เลื่อนดูในเมนูตามวิธีการอินเทอร์เฟซอื่นเช่น SlideMenuIn การเดินทางไปกลับด้วยเหตุผลอะไร? กรณีที่คอนโทรลเลอร์ตัดสินใจว่าคุณไม่สามารถหรือต้องการทำอย่างอื่นแทนนั่นคือเหตุผล ผู้ควบคุมควรรับผิดชอบมุมมองด้วยมุมมองโดยไม่ทำอะไรเลยเว้นแต่ผู้ควบคุมบอกว่าเป็นเช่นนั้น อย่างไรก็ตาม; ใน MVVM เมนูสไลด์ในแอนิเมชั่นควรจะสร้างขึ้นและเป็นแบบทั่วไปและแทนที่จะบอกให้เลื่อนในนั้นจะขึ้นอยู่กับค่าบางอย่าง ดังนั้นฟังจาก ViewModel และเมื่อ ViewModel กล่าวว่า IsMenuActive = true (หรืออย่างไรก็ตาม) ภาพเคลื่อนไหวสำหรับสิ่งที่เกิดขึ้น ตอนนี้ ด้วยที่กล่าวว่าฉันต้องการที่จะทำให้จุดอื่นที่ชัดเจนจริงๆและโปรดใส่ใจ IsMenuActive น่าจะเป็น BAD MVVM หรือการออกแบบ ViewModel เมื่อออกแบบ ViewModel คุณไม่ควรสมมติว่า View จะมีคุณสมบัติใด ๆ เลยและเพิ่งผ่านสถานะของโมเดลที่แปลแล้ว ด้วยวิธีนี้หากคุณตัดสินใจที่จะเปลี่ยนมุมมองเพื่อลบเมนูและเพียงแค่แสดงข้อมูล / ตัวเลือกอื่นด้วยวิธีนี้ ViewModel จะไม่สนใจ ดังนั้นคุณจะจัดการเมนูอย่างไร เมื่อข้อมูลมีเหตุผลก็เป็นเช่นนั้น ดังนั้นวิธีหนึ่งในการทำเช่นนี้คือให้เมนูรายการตัวเลือก (อาจเป็นอาร์เรย์ของ ViewModels ภายใน) หากรายการนั้นมีข้อมูลเมนูจะรู้ว่าจะเปิดผ่านทริกเกอร์หรือไม่หากไม่ใช่จะรู้ได้ว่าจะซ่อนผ่านทริกเกอร์ คุณมีข้อมูลสำหรับเมนูหรือไม่อยู่ใน ViewModel อย่าตัดสินใจที่จะแสดง / ซ่อนข้อมูลนั้นใน ViewModel .. เพียงแปลสถานะของโมเดล ด้วยวิธีนี้มุมมองนั้นมีปฏิกิริยาตอบสนองและทั่วไปอย่างสมบูรณ์และสามารถใช้ได้ในหลาย ๆ สถานการณ์

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

ดังนั้น ... สิ่งที่ต้องจำไว้เพื่อให้ถูกต้อง ตัดสินใจล่วงหน้าว่าจะออกแบบแอปพลิเคชันของคุณและติดไว้ที่ใด

หากคุณทำ MVC ซึ่งยอดเยี่ยมคุณต้องแน่ใจว่าคอนโทรลเลอร์สามารถจัดการได้และควบคุมมุมมองของคุณได้อย่างเต็มที่ หากคุณมีมุมมองขนาดใหญ่ให้พิจารณาเพิ่มการควบคุมลงในมุมมองที่มีตัวควบคุมที่แตกต่างกัน เพียงแค่ไม่แบ่งการควบคุมเหล่านั้นไปยังตัวควบคุมที่แตกต่างกัน น่าผิดหวังมากในการรักษา ใช้เวลาสักครู่และออกแบบสิ่งต่าง ๆ แยกกันในลักษณะที่จะทำงานเป็นส่วนประกอบแยกต่างหาก ... และให้ผู้ควบคุมบอกรุ่นให้ยืนยันหรือเก็บข้อมูลต่อไป การตั้งค่าการพึ่งพาในอุดมคติสำหรับ MVC ในคือView ←คอนโทรลเลอร์→รุ่น หรือด้วย ASP.NET (อย่าให้ฉันเริ่มต้น) โมเดล←ดู↔คอนโทรลเลอร์→รุ่น (โดยที่ Model สามารถเหมือนกันหรือแตกต่างกันโดยสิ้นเชิงจาก Controller ไปยังมุมมอง)... แน่นอนว่าสิ่งเดียวที่คุณควรรู้เกี่ยวกับ Controller in View ณ จุดนี้ส่วนใหญ่ใช้สำหรับการอ้างอิงจุดสิ้นสุดเพื่อให้รู้ว่าจะต้องส่งต่อโมเดลที่ไหน

หากคุณทำ MVVM ฉันขออวยพรให้จิตวิญญาณของคุณ แต่ใช้เวลาทำอย่างถูกต้อง! อย่าใช้อินเทอร์เฟซสำหรับหนึ่ง ให้มุมมองของคุณเป็นตัวกำหนดว่ามันจะเป็นอย่างไรโดยดูจากค่า เล่นด้วยข้อมูล View with Mock หากคุณมีมุมมองที่แสดงเมนู (ตามตัวอย่าง) แม้ว่าคุณจะไม่ต้องการในเวลานั้น GOOD มุมมองของคุณกำลังทำงานตามที่ควรและการตอบสนองขึ้นอยู่กับค่าตามที่ควร เพียงเพิ่มความต้องการเพิ่มเติมเล็กน้อยลงในทริกเกอร์ของคุณเพื่อให้แน่ใจว่าสิ่งนี้จะไม่เกิดขึ้นเมื่อ ViewModel อยู่ในสถานะที่ถูกแปลเฉพาะหรือสั่งให้ ViewModel ลบสถานะนี้ ใน ViewModel ของคุณอย่าลบสิ่งนี้ด้วยตรรกะภายในราวกับว่าคุณกำลังตัดสินใจจากที่นั่นไม่ว่าวิวควรเห็นหรือไม่ก็ตาม จำไว้ว่าคุณไม่สามารถคิดว่ามีเมนูหรือไม่ได้อยู่ใน ViewModel และในที่สุดก็, รุ่นควรอนุญาตให้คุณเปลี่ยนและสถานะร้านค้าน่าจะเป็นไปได้มากที่สุด นี่คือที่การตรวจสอบและจะเกิดขึ้น; ตัวอย่างเช่นหากโมเดลไม่สามารถแก้ไขสถานะได้ก็จะตั้งค่าสถานะว่าสกปรกหรือบางสิ่งบางอย่าง เมื่อ ViewModel ตระหนักถึงสิ่งนี้มันจะแปลสิ่งที่สกปรกและจากนั้น View จะรับรู้สิ่งนี้และแสดงข้อมูลบางอย่างผ่านทริกเกอร์อื่น ข้อมูลทั้งหมดในมุมมองสามารถผูกเข้ากับ ViewModel เพื่อให้ทุกสิ่งสามารถเป็นแบบไดนามิกเท่านั้น Model และ ViewModel ไม่มีความคิดเกี่ยวกับวิธีที่มุมมองจะตอบสนองต่อการเชื่อมโยง ตามความเป็นจริงแล้วตัวแบบไม่มีความคิดเกี่ยวกับ ViewModel เช่นกัน เมื่อตั้งค่าการขึ้นต่อกันพวกเขาควรชี้ให้เห็นอย่างนั้นและชอบเท่านั้น ไม่แก้ไขสถานะจากนั้นจะตั้งค่าสถานะว่าสกปรกหรือบางสิ่งบางอย่าง เมื่อ ViewModel ตระหนักถึงสิ่งนี้มันจะแปลสิ่งที่สกปรกและจากนั้น View จะรับรู้สิ่งนี้และแสดงข้อมูลบางอย่างผ่านทริกเกอร์อื่น ข้อมูลทั้งหมดในมุมมองสามารถผูกเข้ากับ ViewModel เพื่อให้ทุกสิ่งสามารถเป็นแบบไดนามิกเท่านั้น Model และ ViewModel ไม่มีความคิดเกี่ยวกับวิธีที่มุมมองจะตอบสนองต่อการเชื่อมโยง ตามความเป็นจริงแล้วตัวแบบไม่มีความคิดเกี่ยวกับ ViewModel เช่นกัน เมื่อตั้งค่าการขึ้นต่อกันพวกเขาควรชี้ให้เห็นอย่างนั้นและชอบเท่านั้น ไม่แก้ไขสถานะจากนั้นจะตั้งค่าสถานะว่าสกปรกหรือบางสิ่งบางอย่าง เมื่อ ViewModel ตระหนักถึงสิ่งนี้มันจะแปลสิ่งที่สกปรกและจากนั้น View จะรับรู้สิ่งนี้และแสดงข้อมูลบางอย่างผ่านทริกเกอร์อื่น ข้อมูลทั้งหมดในมุมมองสามารถผูกเข้ากับ ViewModel เพื่อให้ทุกสิ่งสามารถเป็นแบบไดนามิกเท่านั้น Model และ ViewModel ไม่มีความคิดเกี่ยวกับวิธีที่มุมมองจะตอบสนองต่อการเชื่อมโยง ตามความเป็นจริงแล้วตัวแบบไม่มีความคิดเกี่ยวกับ ViewModel เช่นกัน เมื่อตั้งค่าการขึ้นต่อกันพวกเขาควรชี้ให้เห็นอย่างนั้นและชอบเท่านั้น ข้อมูลทั้งหมดในมุมมองสามารถผูกเข้ากับ ViewModel เพื่อให้ทุกสิ่งสามารถเป็นแบบไดนามิกเท่านั้น Model และ ViewModel ไม่มีความคิดเกี่ยวกับวิธีที่มุมมองจะตอบสนองต่อการเชื่อมโยง ตามความเป็นจริงแล้ว Model ไม่มีความคิดเกี่ยวกับ ViewModel เช่นกัน เมื่อตั้งค่าการขึ้นต่อกันพวกเขาควรชี้ให้เห็นอย่างนั้นและชอบเท่านั้น ข้อมูลทั้งหมดในมุมมองสามารถผูกเข้ากับ ViewModel เพื่อให้ทุกอย่างสามารถเป็นแบบไดนามิกเท่านั้น Model และ ViewModel ไม่มีความคิดเกี่ยวกับวิธีที่ View จะตอบสนองต่อการเชื่อมโยง ตามความเป็นจริงแล้ว Model ไม่มีความคิดเกี่ยวกับ ViewModel เช่นกัน เมื่อตั้งค่าการขึ้นต่อกันพวกเขาควรชี้ให้เห็นอย่างนั้นและชอบเท่านั้นView → ViewModel → Model (และหมายเหตุด้านข้างที่นี่ ... และนี่อาจจะเป็นที่ถกเถียงกันเช่นกัน แต่ฉันไม่สนใจ ... อย่าส่ง MODEL ไปที่ VIEW ยกเว้น MODEL นั้นจะไม่เปลี่ยนรูปไม่เช่นนั้นจะปิดด้วย ViewModel ที่เหมาะสม The View ไม่ควรเห็นช่วงเวลาของแบบจำลองฉันให้หนูดูว่าคุณได้สาธิตอะไรหรือคุณทำมันผิดอย่างไร)

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

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

ถ้าฉันไม่ได้สับสนคุณพอลองติดต่อฉัน ... ฉันไม่รังเกียจที่จะอธิบายเรื่องนี้อย่างละเอียดพร้อมภาพประกอบและตัวอย่าง

ในตอนท้ายของวันเราทุกคนเป็นโปรแกรมเมอร์และมีอนาธิปไตยอยู่ในตัวเราเมื่อมีการเข้ารหัส ... ดังนั้นกฎจะถูกทำลายทฤษฎีจะเปลี่ยนไปและทั้งหมดนี้จะจบลงด้วยการล้างหมู ... แต่เมื่อทำงานขนาดใหญ่ โครงการและในทีมขนาดใหญ่มันช่วยให้เห็นด้วยกับรูปแบบการออกแบบและการบังคับใช้ อยู่มาวันหนึ่งมันจะทำให้ก้าวเล็ก ๆ ที่เกิดขึ้นในตอนแรกกลายเป็นก้าวกระโดดและประหยัดได้ในภายหลัง


คำตอบที่ถูกต้องและละเอียดอย่างน่าอัศจรรย์! ทำให้มันชัดเจนสำหรับฉัน :-)
ankush981

"การเรียนรู้อาจสร้างความสับสนได้มากเนื่องจากคุณจะพบข้อมูลมากมายที่ไม่ดีบนอินเทอร์เน็ต" อ๋อ ในฐานะที่เป็นคนที่ดูเหมือนจะมีประสบการณ์มากมายกับรูปแบบการออกแบบเหล่านี้คุณรู้จักบทเรียน / คำแนะนำที่ดีหรือไม่?
MarredCheese

1
ความจริงแล้วความรู้ MVVM ของฉันได้ผ่านมาหลายปีหรือลองผิดลองถูกและใช้ / ทำมันด้วยวิธีต่าง ๆ ตามความพยายามของทีม ฉันเมื่อเร็ว ๆ นี้ (2 ปีที่ผ่านมา) สามารถนำประสบการณ์ของฉันเองไปสู่แผนเกมสรุปและนำทีมเริ่มต้นให้เสร็จสิ้นและเราก็ประสบความสำเร็จอย่างมาก ที่กล่าวว่าฉันไม่สามารถชี้ให้คุณในจุดใดจุดหนึ่งและขอโทษ ฉันสามารถพูดได้ว่าคุณถูกต้องเพราะความคิดเห็นที่หลากหลายมันค่อนข้างสับสน แต่ IMO กับ MVVM มันจะเป็นเรื่องธรรมดาที่สุดเท่าที่จะทำได้ ทำให้ ViewModels มีความสามารถในการอนุญาตให้มุมมองรวมและทำงานกับข้อมูลอย่างเคร่งครัด แต่สำหรับมุมมองใด ๆ ...
Michael Puckett II

1
กล่าวอีกนัยหนึ่งไม่เคยทำให้ ViewModel ถือว่ามุมมองนั้นดูหรือกระทำในทางใดทางหนึ่ง สำหรับฉัน ViewModel นั้นใช้ดีที่สุดเช่น API แต่มีการสื่อสารที่เข้มงวด ทำตามแผนเกมสำหรับการผูกการแก้ไขคำสั่ง ฯลฯ หากมุมมองต้องการตรรกะพิเศษเพื่อทำงานในแบบเฉพาะเจาะจงซึ่งไม่มีส่วนเกี่ยวข้องกับแอพหรือข้อมูล (เช่นภาพเคลื่อนไหวหรือกล่องแบบเลื่อนลง .. ) จากนั้นตรรกะนั้น อยู่ในระดับดูอย่างใดอย่างหนึ่ง อีกครั้งมีความคิดเห็นมากมายเหลือเฟือและนี่เป็นเพียงของฉัน แต่ฉันมีพื้นฐานที่แข็งแกร่งที่นี่และประวัติที่แข็งแกร่งจนถึงตอนนี้
Michael Puckett II

ฉันมีแอพตัวอย่างที่ฉันไม่รังเกียจที่จะแบ่งปันและหรือไม่สนใจที่จะตั้งค่าการแสดงที่เรียบง่ายและบอกให้คุณหรือคนอื่น ๆ ทราบหากต้องการหรืออยากรู้อยากเห็น
Michael Puckett II

23

Simple Difference: (ได้รับแรงบันดาลใจจากหลักสูตร Coursera AngularJS ของ Yaakov)

ป้อนคำอธิบายรูปภาพที่นี่

MVC (รุ่นมุมมองคอนโทรลเลอร์)

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

MVVM (Model View View Model)

ViewModel :

  1. มันคือการแสดงสถานะของมุมมอง
  2. มันเก็บข้อมูลที่แสดงในมุมมอง
  3. ตอบสนองต่อการดูเหตุการณ์หรือตรรกะการนำเสนอ
  4. เรียกฟังก์ชันอื่น ๆ สำหรับการประมวลผลเชิงตรรกะทางธุรกิจ
  5. ไม่ต้องถามมุมมองโดยตรงเพื่อแสดงอะไร

18

MVVM เป็นการปรับแต่ง (อภิปราย) ของรูปแบบการนำเสนอ ฉันบอกว่าเป็นปัญหาเนื่องจากความแตกต่างเพียงอย่างเดียวคือวิธีที่ WPF ให้ความสามารถในการผูกข้อมูลและการจัดการคำสั่ง


1
ในปี 2009 คำตอบนี้อาจเป็นคำตอบที่ดี แต่วันนี้ไม่มีการโต้แย้งเนื่องจากแม้แต่ตัวควบคุม HTML Helper จาก MSFT ก็อนุญาตให้ใช้ตัวช่วย "สำหรับ" ที่น่าอับอายได้ สิ่งที่น่าพิศวงคือทั้งหมดที่เกี่ยวกับการผูกข้อมูลในฝั่งไคลเอ็นต์
John Peters

1
ฉันระบุสิ่งนี้ในปี 2009 เพราะมีคนจำนวนมากเกินไปในชุมชนยอมรับคำตอบนี้ ฉันบอกว่ามันเป็นที่ถกเถียงกันเพราะ MVVM และ Presentation Model เป็นรูปแบบเดียวกันโดยใช้ชื่อต่าง รถถังที่ได้รับความนิยมใน WPF มันมักเรียกว่า MVVM ในเฟรมเวิร์กอื่น ๆ ในวันนี้ แต่ชื่อใดชื่อหนึ่งนั้นถูกต้อง
wekempf

15

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

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

รูปแบบ MVVM เป็นลักษณะทั่วไปของการฝึกปฏิบัตินั้นกับองค์ประกอบ UI ทั้งหมด

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


13

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

พยายามที่จะทำให้กระจ่างบางอย่างข้างต้นฉันสร้างภาพยนตร์เรื่องนี้ที่เกี่ยวข้องกับ MVVM, MVP และ MVC เรื่องราวเริ่มต้นโดยผู้ใช้คลิกที่ปุ่ม 'ค้นหา' ในแอปค้นหาภาพยนตร์ ... :

ผู้ใช้: คลิก ...

View : นั่นใคร [ MVVM | MVP | MVC ]

ผู้ใช้: ฉันเพิ่งคลิกที่ปุ่มค้นหา ...

ดู : โอเครอสักครู่…. [ MVVM | MVP | MVC ]

( ดูการเรียกViewModel | ผู้นำเสนอ | คอนโทรลเลอร์ …) [ MVVM | MVP | MVC ]

ดู : เฮ้ViewModel | ผู้นำเสนอ | ผู้ควบคุมผู้ใช้เพิ่งคลิกที่ปุ่มค้นหาฉันต้องทำอย่างไร [ MVVM | MVP | MVC ]

ViewModel | ผู้นำเสนอ | ผู้ควบคุม : เฮ้ดูมีคำค้นหาใดในหน้านั้นบ้าง [ MVVM | MVP | MVC ]

ดู : ใช่…นี่คือ…“ เปียโน” [ MVVM | MVP | MVC ]

—— นี่คือข้อแตกต่างที่สำคัญที่สุดระหว่างMVVMและMVP | MVC ———

ผู้นำเสนอ : ขอบคุณที่ดู …ในขณะที่ฉันกำลังค้นหาข้อความค้นหาในโมเดลโปรดแสดงแถบความคืบหน้าของเขา / เธอ [ MVP | MVC ]

( ผู้นำเสนอ | คอนโทรลเลอร์กำลังเรียกใช้โมเดล ... ) [ MVP | MVC ]

ViewController : ขอบคุณฉันจะค้นหาข้อความค้นหาในโมเดลแต่จะไม่อัปเดตคุณโดยตรง ฉันจะทริกเกอร์เหตุการณ์แทน searchResultsListObservable แทนหากมีผลลัพธ์ใด ๆ ดังนั้นคุณควรสังเกตว่า [ MVVM ]

(ในขณะที่คอยสังเกตทริกเกอร์ใด ๆ ใน searchResultsListObservable มุมมองคิดว่ามันควรจะแสดงแถบความคืบหน้าให้กับผู้ใช้เนื่องจากViewModelจะไม่พูดกับมัน)

------------------------------

ViewModel | ผู้นำเสนอ | ตัวควบคุม : เฮ้โมเดลคุณมีคำที่ตรงกับคำค้นหานี้หรือไม่:“ piano” [ MVVM | MVP | MVC ]

แบบ : Hey ViewModel | ผู้นำเสนอ | คอนโทรลเลอร์ให้ฉันตรวจสอบ ... [ MVVM | MVP | MVC ]

( Modelกำลังสร้างการสืบค้นไปยังฐานข้อมูลภาพยนตร์…) [ MVVM | MVP | MVC ]

(หลังจากนั้นไม่นาน ... )

———— นี่คือจุดแยกระหว่างMVVM , MVPและMVC —————

รุ่น : ฉันพบรายการสำหรับคุณViewModel | ผู้นำเสนอที่นี่อยู่ใน JSON“ [{“ ชื่อ”:” ครูสอนเปียโน”,” ปี”: 2001}, {“ ชื่อ”:” เปียโน”,” ปี”: 1993}]” [ MVVM | MVP ]

รุ่น : มีบางผลลัพธ์พร้อมใช้งานคอนโทรลเลอร์ ฉันสร้างตัวแปรฟิลด์ในอินสแตนซ์ของฉันและเติมด้วยผลลัพธ์ ชื่อของมันคือ“ searchResultsList” [ MVC ]

( Presenter | ControllerขอบคุณModelและกลับไปที่View ) [ MVP | MVC ]

ผู้นำเสนอ : ขอบคุณที่รอดูฉันพบรายการผลลัพธ์ที่ตรงกันสำหรับคุณและจัดเรียงในรูปแบบที่ทำได้: [“ ครูสอนเปียโน 2001″,” เปียโน 1993”] นอกจากนี้โปรดซ่อนแถบความคืบหน้าในขณะนี้ [ MVP ]

ผู้ควบคุม : ขอบคุณที่รอดูฉันได้ถามรุ่นเกี่ยวกับคำค้นหาของคุณ มันบอกว่าพบรายการผลลัพธ์ที่ตรงกันและเก็บไว้ในตัวแปรชื่อ“ searchResultsList” ภายในอินสแตนซ์ของมัน คุณสามารถรับได้จากที่นั่น นอกจากนี้โปรดซ่อนแถบความคืบหน้าในขณะนี้ [ MVC ]

ViewModel : ผู้สังเกตการณ์ใด ๆ ใน searchResultsListObservable จะได้รับแจ้งว่ามีรายการใหม่นี้ในรูปแบบที่แสดงได้: [“ ครูสอนเปียโน 2001″,” เปียโน 1993”] [ MVVM ]

ดู : ขอบคุณ Presenter มาก [ MVP ]

ดู : ขอบคุณ“ ผู้ควบคุม ” [ MVC ] (ตอนนี้มุมมองตั้งคำถามตัวเอง: ฉันจะนำเสนอผลลัพธ์ที่ฉันได้รับจากตัวแบบให้ผู้ใช้ได้อย่างไรปีการผลิตของภาพยนตร์เรื่องนี้มาก่อนหรือไม่?)

ดู : โอ้มีทริกเกอร์ใหม่ใน searchResultsListObservable …ดีมีรายการที่แสดงได้แล้วตอนนี้ฉันต้องแสดงมันในรายการเท่านั้น ฉันควรซ่อนแถบความคืบหน้าในขณะที่ฉันมีผลลัพธ์ [ MVVM ]

ในกรณีที่คุณสนใจฉันได้เขียนบทความชุดหนึ่งที่นี่เปรียบเทียบ MVVM, MVP และ MVC โดยใช้แอปพลิเคชัน android ค้นหาภาพยนตร์


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

10

การฉีด ViewModels ที่พิมพ์อย่างมากลงในมุมมองโดยใช้ MVC

  1. คอนโทรลเลอร์มีหน้าที่รับผิดชอบในการสร้าง ViewModel ขึ้นมาใหม่และอัดเข้าไปใน View (สำหรับรับคำขอ)
  2. ViewModel เป็นคอนเทนเนอร์สำหรับ DataContext และสถานะการดูเช่นรายการที่เลือกล่าสุดเป็นต้น
  3. โมเดลมีเอนทิตี DB และอยู่ใกล้กับ DB Schema ซึ่งทำเคียวรีและการกรอง (ฉันชอบ EF และ LINQ สำหรับเรื่องนี้)
  4. แบบจำลองควรพิจารณาที่เก็บและหรือการคาดการณ์ผลลัพธ์เป็นประเภทที่รัดกุม (EF มีวิธีการที่ยอดเยี่ยม ... เป็นอาร์กิวเมนต์ที่ช้าEF ไม่ช้า !
  5. ViewModel รับข้อมูลและทำกฏทางธุรกิจและการตรวจสอบความถูกต้อง
  6. ตัวควบคุมที่โพสต์ด้านหลังจะทำการ Cal วิธี ViewModel Post และรอผลลัพธ์
  7. ตัวควบคุมจะฉีด Viewmodel ที่อัพเดตใหม่ไปยัง View The View ใช้ชนิดที่แข็งแกร่งเท่านั้นที่มีผลผูกพัน
  8. มุมมองเพียงแสดงข้อมูลและโพสต์เหตุการณ์กลับไปที่ตัวควบคุม (ดูตัวอย่างด้านล่าง)
  9. MVC สกัดกั้นคำขอขาเข้าและกำหนดเส้นทางไปยังตัวควบคุมที่เหมาะสมพร้อมกับชนิดข้อมูลที่แข็งแกร่ง

ในรุ่นนี้ไม่มีการติดต่อระดับ HTTPกับวัตถุคำขอหรือตอบสนองอีกต่อไปเนื่องจากเครื่อง MVC ของ MSFT ซ่อนไว้จากเรา

ในการชี้แจงรายการ 6 ข้างต้น (ตามคำขอ) ...

สมมติว่า ViewModel เป็นเช่นนี้:

public class myViewModel{
     public string SelectedValue {get;set;}
public void Post(){
    //due to MVC model binding the SelectedValue string above will be set by MVC model binding on post back.
    //this allows you to do something with it.
    DoSomeThingWith(SelectedValue);
    SelectedValue = "Thanks for update!";
 }
}

วิธีการควบคุมของการโพสต์จะมีลักษณะเช่นนี้ (ดูด้านล่าง) โปรดทราบว่าอินสแตนซ์ของ mvm จะถูกติดตั้งโดยอัตโนมัติโดยกลไกการผูก MVC คุณไม่ต้องเลื่อนไปที่เลเยอร์สตริงข้อความค้นหาเลย! นี่คือ MVC ที่สร้างอินสแตนซ์ ViewModel ให้กับคุณตามสตริงการสืบค้น!

[HTTPPOST]   
public ActionResult MyPostBackMethod (myViewModel mvm){
         if (ModelState.IsValid)
        {
               // Immediately call the only method needed in VM...
               mvm.Post()
        }
      return View(mvm);
}

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

ข้อได้เปรียบของรูปแบบนี้คือ ViewModel ทำหน้าที่ "ยุ่งเหยิง" ทั้งหมดที่เชื่อมต่อกับ Model / Buisness ตรรกะคอนโทรลเลอร์เป็นเพียงเราเตอร์ประเภทต่าง ๆ มันเป็น SOC ในการดำเนินการ


คุณช่วยอธิบายรายการ 6 ได้ไหม ฉันรู้ว่าคุณครอบคลุม ASP.Net เท่านั้น แต่ดูเหมือนว่าเป็นการเพิ่มการพึ่งพาที่ไม่พึงประสงค์ให้กับ ViewModel (เช่นความรู้เกี่ยวกับแหล่งที่มาของข้อมูล / ไปที่) ตัวอย่างโค้ด (หลอกรหัส) จะเป็นการดีที่จะชี้แจงคำตอบนี้และแสดงว่าส่วนใดเป็นฝั่งเซิร์ฟเวอร์และอันไหนเป็นฝั่งไคลเอ็นต์
Gone Coding

9

MVVM เพิ่มโมเดลมุมมองลงในส่วนผสม นี่เป็นสิ่งสำคัญเนื่องจากจะช่วยให้คุณใช้วิธีการเชื่อมโยงจำนวนมากของ WPF ได้โดยไม่ต้องใส่ส่วนเฉพาะ UI ทั้งหมดลงในโมเดลปกติของคุณ

ฉันอาจจะผิด แต่ฉันไม่แน่ใจว่า MVVM บังคับให้ผู้ควบคุมเข้าสู่ส่วนผสม ผมพบว่าแนวความคิดที่จะเป็นมากขึ้นสอดคล้องกับ: http://martinfowler.com/eaaDev/PresentationModel.html ฉันคิดว่าผู้คนเลือกที่จะรวมเข้ากับ MVC ไม่ใช่ว่ามันถูกสร้างขึ้นในรูปแบบ


3
MVVM พูดอย่างเคร่งครัดคือ Presentation Model แม้ว่า MVVM จะกลายเป็นชื่อที่ต้องการสำหรับการสร้างรูปแบบเฉพาะ WPF
wekempf

ตกลง Viewmodel ใน MVC "IS" เป็นเครื่องสถานะสำหรับมุมมอง ประกอบด้วย datacontext และติดตามข้อมูลรายการที่เลือกทั้งหมดรวมทั้งสามารถมีตรรกะการตรวจสอบทั้งหมดโดยใช้ส่วนต่อประสาน IValidatableObject อินเตอร์เฟส ViewModel พร้อม DB ที่เลเยอร์โมเดลซึ่งสามารถใช้โมเดลที่พิมพ์ได้ดี MVVM ใน WPF IS เป็นคอนโทรลเลอร์ของ MVC แต่ตัวควบคุมของ MVC นั้นสะอาดกว่ามากมันเป็นสิ่งสำคัญในการจัดการเส้นทาง
John Peters

9

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


1
IMHO ฉันจะยืนยันว่า "ทำให้ควบคุมนำมาใช้ใหม่มากขึ้น" กว้างเกินไปคำสั่งและเคาน์เตอร์ทั่วไป ASP.Net "ควบคุม" (คือไม่ได้ชั้นตรรกะทางธุรกิจ) เป็นตัวควบคุมเหล่านั้นมักจะมีส่วนของแอพลิเคชันที่มีโปรแกรมประยุกต์ โดยเฉพาะ เป็น Views, Models, ViewModels และตรรกะทางธุรกิจที่จำเป็นต้องใช้ซ้ำ ฉันคิดว่าการใช้โมดูลตรรกะทางธุรกิจในฐานะผู้ให้บริการซึ่งไม่ใช่ตัวควบคุมจะเป็นตัวเลือกที่ดีกว่า
Gone Coding

แต่คุณกำลังพูดถึง "ViewModel" ใน Asp.net ไม่ใช่เกี่ยวกับรูปแบบการออกแบบ MVVM สองสิ่งที่แตกต่าง
Luis

9

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


ว้าว ... ทั้ง MVC และ MVVM มาจาก SmallTalk? เห็นได้ชัดว่าพวกเขาอยู่ข้างหน้าเวลาของพวกเขา ...
MattE

จริงๆแล้วการบอกว่ามันมาจาก Presentation Model ของ Martin Fowler นั้นไม่ถูกต้อง มันยากมากที่จะตัดสินว่าสิ่งใดมาก่อน แต่รูปแบบทั้งคู่ (อนุญาตให้เป็นแบบเดียวกัน) มาถึงอย่างอิสระและในเวลาเดียวกัน
wekempf

6

โดยทั่วไปใช้ MVC ในการพัฒนาเว็บและ MVVM เป็นที่นิยมที่สุดในการพัฒนา WPF / Silverlight อย่างไรก็ตามบางครั้งเว็บคลังข้อมูลอาจมีการผสมผสานระหว่าง MVC และ MVVM

ตัวอย่างเช่นคุณอาจใช้knockout.jsและในกรณีนี้คุณจะมี MVVM ทางฝั่งไคลเอ็นต์ของคุณ และฝั่งเซิร์ฟเวอร์ของ MVC ของคุณยังสามารถเปลี่ยนแปลงได้ ในแอพที่ซับซ้อนไม่มีใครใช้รุ่นบริสุทธิ์ อาจมีความรู้สึกที่จะใช้ ViewModel เป็น "Model" ของ MVC และ Model จริงของคุณจะเป็นส่วนหนึ่งของ VM นี้ สิ่งนี้จะให้เลเยอร์นามธรรมที่เป็นพิเศษแก่คุณ


คำว่า 'การพัฒนาเว็บ' คืออะไร 'MVC' ไม่มีอะไรมากไปกว่าการแยกความกังวลออกจากกันและไม่ใช่ MVC ของแท้ที่นำหน้าเว็บ
Terrence Brannon

4

MVVMC หรือ MVC + อาจเป็นวิธีที่ทำงานได้สำหรับองค์กรรวมถึงการพัฒนาแอปพลิเคชันอย่างรวดเร็ว แม้ว่าจะเป็นการดีที่จะแยก UI ออกจากตรรกะทางธุรกิจและการโต้ตอบรูปแบบ MVVM ที่ 'บริสุทธิ์' และตัวอย่างที่มีอยู่ส่วนใหญ่จะทำงานได้ดีที่สุดในมุมมองเอกพจน์

ไม่แน่ใจเกี่ยวกับการออกแบบของคุณ แต่แอปพลิเคชั่นส่วนใหญ่ของฉันมีหน้าและมุมมอง (นำมาใช้ใหม่) หลายมุมมองและทำให้ ViewModels จำเป็นต้องโต้ตอบกับบางระดับ การใช้หน้าเป็นคอนโทรลเลอร์จะเอาชนะวัตถุประสงค์ของ MVVM โดยสิ้นเชิงดังนั้นอย่าใช้วิธีการ "VM-C" สำหรับตรรกะพื้นฐานอาจส่งผลให้ .. ความท้าทายในการสร้างเมื่อแอพพลิเคชั่นครบ แม้แต่ใน VB-6 พวกเราส่วนใหญ่ก็อาจหยุดเขียนโค้ดตรรกะทางธุรกิจลงในเหตุการณ์ปุ่มและเริ่มคำสั่ง 'ส่งสัญญาณ' ไปยังตัวควบคุมใช่ไหม ฉันเพิ่งดู framworks ที่เกิดขึ้นใหม่จำนวนมากในหัวข้อนั้น สิ่งที่ฉันชอบอย่างชัดเจนคือวิธีการของ Magellan (ที่ codeplex) การเข้ารหัสที่มีความสุข!

http://en.wikipedia.org/wiki/Model_View_ViewModel#References


4

คอนโทรลเลอร์ไม่ได้ถูกแทนที่ด้วย ViewModel ใน MVVM เนื่องจาก ViewModel มีฟังก์ชั่นที่แตกต่างกันโดยสิ้นเชิงแล้วเป็นคอนโทรลเลอร์ คุณยังคงต้องการคอนโทรลเลอร์เพราะไม่มีรุ่น Controller ของคุณ ViewModel และ View จะไม่ทำอะไรมากมาย ... ใน MVVM คุณมีคอนโทรลเลอร์ด้วยชื่อ MVVM ก็เป็นเพียงแค่การทำให้พลาด

MVVMC เป็นชื่อที่ถูกต้องในความเห็นของฉัน

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


4

ฉันทำบทความปานกลางสำหรับเรื่องนี้

MVVM

  1. View ➡ ViewModel ➡ Model

    • มุมมองมีการอ้างอิงถึง ViewModel แต่ไม่ใช่ในทางกลับกัน
    • ViewModel มีการอ้างอิงถึงรุ่น แต่ไม่ใช่ในทางกลับกัน
    • มุมมองไม่มีการอ้างอิงถึงโมเดลและในทางกลับกัน
  2. หากคุณกำลังใช้ควบคุมก็สามารถมีการอ้างอิงไปยังผู้ชมและViewModelsแม้ว่าตัวควบคุมไม่จำเป็นเสมอแสดงให้เห็นในSwiftUI

  3. การผูกข้อมูล : เราสร้างผู้ฟังสำหรับคุณสมบัติ ViewModel
class CustomView: UIView {
  var viewModel = MyViewModel {
    didSet {
      self.color = viewModel.color
    }
  }

  convenience init(viewModel: MyViewModel) {
    self.viewModel = viewModel
  }
}


struct MyViewModel {
   var viewColor: UIColor {
      didSet {
         colorChanged?() // This is where the binding magic happens.
      }
   }

   var colorChanged: ((UIColor) -> Void)?
}


class MyViewController: UIViewController {

   let myViewModel = MyViewModel(viewColor: .green)
   let customView: CustomView!

   override func viewDidLoad() {
      super.viewDidLoad()

      // This is where the binder is assigned.
      myViewModel.colorChanged = { [weak self] color in 
        print("wow the color changed")
      }
      customView = CustomView(viewModel: myViewModel)
      self.view = customView
   }
}

ความแตกต่างในการตั้งค่า

  1. ตรรกะทางธุรกิจจัดขึ้นในคอนโทรลเลอร์สำหรับ MVC และ ViewModels สำหรับ MVVM
  2. เหตุการณ์จะถูกส่งโดยตรงจาก View ไปยังคอนโทรลเลอร์ใน MVC ในขณะที่เหตุการณ์ถูกส่งผ่านจาก View ไปยัง ViewModel ไปยัง Controller (ถ้ามี) สำหรับ MVVM

คุณสมบัติทั่วไป

  1. ทั้ง MVVM และ MVC ไม่อนุญาตให้ View ส่งข้อความโดยตรงไปยัง Model / s
  2. ทั้งสองมีโมเดล
  3. ทั้งสองมีมุมมอง

ข้อดีของ MVVM

  1. เนื่องจาก ViewModels เก็บตรรกะทางธุรกิจพวกเขาเป็นวัตถุคอนกรีตขนาดเล็กทำให้ง่ายต่อการทดสอบหน่วย ในอีกทางหนึ่งใน MVC ตรรกะทางธุรกิจอยู่ใน ViewController คุณจะมั่นใจได้อย่างไรว่าการทดสอบหน่วยของตัวควบคุมมุมมองนั้นปลอดภัยโดยไม่ต้องทดสอบวิธีการและผู้ฟังทั้งหมดพร้อมกัน? คุณไม่สามารถเชื่อถือผลการทดสอบหน่วยทั้งหมดได้
  2. ใน MVVM เนื่องจากตรรกะทางธุรกิจถูกแยกออกจากคอนโทรลเลอร์เป็นหน่วย ViewModel ของอะตอมขนาดของ ViewController จะลดขนาดลงและนี่ทำให้โค้ด ViewController ชัดเจนมากขึ้น

ข้อดีของ MVC

  1. การให้ตรรกะทางธุรกิจภายในตัวควบคุมจะช่วยลดความจำเป็นในการแยกย่อยดังนั้นข้อความสั่งจึงมีแนวโน้มที่จะทำงานบนแคชซึ่งมีประสิทธิภาพมากกว่าการห่อหุ้มตรรกะทางธุรกิจลงใน ViewModels
  2. การให้ตรรกะทางธุรกิจในที่เดียวสามารถเร่งกระบวนการพัฒนาสำหรับแอปพลิเคชันแบบง่ายโดยไม่จำเป็นต้องทำการทดสอบ ฉันไม่รู้ว่าไม่จำเป็นต้องทำการทดสอบเมื่อใด
  3. การให้ตรรกะทางธุรกิจใน ViewController นั้นง่ายกว่าที่คิดสำหรับนักพัฒนาใหม่

1
คำอธิบายที่ดีที่สุด
p32094

2

จากมุมมองที่ใช้งานได้จริง MVC (Model-View-Controller) เป็นรูปแบบ อย่างไรก็ตาม MVC เมื่อใช้เป็น ASP.net MVC เมื่อรวมกับ Entity Framework (EF) และ "เครื่องมือไฟฟ้า" เป็นวิธีการที่มีประสิทธิภาพมากโดยอัตโนมัติบางส่วนสำหรับการนำฐานข้อมูลตารางและคอลัมน์ไปยังหน้าเว็บสำหรับเต็ม การดำเนินการ CRUD หรือการดำเนินการ R (เรียกคืนหรืออ่าน) เท่านั้น อย่างน้อยตอนที่ฉันใช้ MVVM รูปแบบการดูมีปฏิสัมพันธ์กับแบบจำลองที่ขึ้นอยู่กับวัตถุทางธุรกิจซึ่งในทางกลับกัน "ทำด้วยมือ" และหลังจากใช้ความพยายามอย่างมากคนหนึ่งก็โชคดีที่ได้รับแบบจำลอง -of-the-box" จากมุมมองการเขียนโปรแกรมที่ใช้งานได้จริง MVC ดูเหมือนจะเป็นตัวเลือกที่ดีเพราะมันมีประโยชน์มากมายนอกกรอบ แต่ก็ยังมีศักยภาพที่จะเพิ่มเสียงระฆังและเสียงนกหวีด


2

ประกอบกับการตอบสนองที่ได้รับจำนวนมากฉันต้องการเพิ่มมุมมองเพิ่มเติมจากเว็บไคลเอ็นต์ฝั่งโมเดิร์น - หรือมุมมองRich Web Application

แท้จริงแล้วทุกวันนี้เว็บไซต์ง่าย ๆ และเว็บแอปพลิเคชั่นที่ใหญ่กว่านั้นถูกสร้างขึ้นด้วยห้องสมุดยอดนิยมมากมายเช่น Bootstrap สิ่งที่น่าพิศวงสร้างโดยสตีฟแซนเดอร์สันสนับสนุนรูปแบบ MVVM ซึ่งเลียนแบบหนึ่งในพฤติกรรมที่สำคัญที่สุดในรูปแบบ: การผูกข้อมูลผ่านรูปแบบการดู มีน้อย JavaScript, ข้อมูลและตรรกะสามารถดำเนินการนั้นจะสามารถเพิ่มเข้าไปในองค์ประกอบของหน้าด้วยง่ายdata-bindแอตทริบิวต์ HTML, คล้ายกับการใช้จำนวนมากของคุณสมบัติของเงินทุน ห้องสมุดทั้งสองแห่งนี้เสนอเนื้อหาเชิงโต้ตอบเท่านั้น และเมื่อรวมกับการกำหนดเส้นทางวิธีการนี้จะส่งผลให้วิธีการง่ายๆที่ยังมีประสิทธิภาพในการสร้างแอพลิเคชันหน้าเดี่ยว

ในทำนองเดียวกันเฟรมเวิร์กฝั่งไคลเอ็นต์สมัยใหม่เช่นAngularเป็นไปตามรูปแบบ MVC ตามการประชุม แต่ยังเพิ่มบริการ ที่น่าสนใจก็คือมันถูกขนานนามว่า Model-View-Anything (MVW) (ดูโพสต์นี้ใน Stack Overflow )

นอกจากนี้ด้วยเฟรมเวิร์กเว็บแบบProgressive ที่เพิ่มขึ้นเช่น Angular 2 เราจะเห็นการเปลี่ยนแปลงในคำศัพท์และอาจเป็นรูปแบบสถาปัตยกรรมใหม่ที่ Components ประกอบด้วยมุมมองหรือเทมเพลตและโต้ตอบกับบริการซึ่งทั้งหมดนี้สามารถอยู่ใน โมดูล; และชุดของโมดูลที่ประกอบขึ้นเป็นแอพพลิเคชั่น


2

ฉันเคยคิดว่า MVC และ MVVM เหมือนกัน ตอนนี้เพราะการดำรงอยู่ของฟลักซ์ฉันสามารถบอกความแตกต่าง:

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

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

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


2

mvc เป็นฝั่งเซิร์ฟเวอร์และ mvvm เป็นฝั่งไคลเอ็นต์ (เบราว์เซอร์) ในการพัฒนาเว็บ

จาวาสคริปต์ส่วนใหญ่ใช้สำหรับ mvvm ในเบราว์เซอร์ มีเทคโนโลยีด้านเซิร์ฟเวอร์จำนวนมากสำหรับ mvc


1

ในระยะสั้นมาก - ใน MVC Controler ตระหนักถึงมุมมอง (การควบคุม) ในขณะที่ใน MVVM ViewModel จะไม่รู้ว่าใครใช้มัน ViewModel จะเปิดเผยคุณสมบัติและการดำเนินการที่สังเกตได้ให้กับผู้ที่อาจสนใจใช้งาน ข้อเท็จจริงนั้นทำให้การทดสอบง่ายขึ้นเนื่องจากไม่มีการอ้างอิงถึง UI ภายใน ViewModel


1

Model – View – Controller (รู้จักกันในชื่อMVC ) เป็นรูปแบบการออกแบบซอฟต์แวร์ที่ใช้กันทั่วไปสำหรับการพัฒนาส่วนต่อประสานผู้ใช้ที่แบ่งตรรกะของโปรแกรมที่เกี่ยวข้องออกเป็นสามองค์ประกอบที่เชื่อมต่อกัน สิ่งนี้ทำเพื่อแยกการแสดงข้อมูลภายในจากวิธีการนำเสนอข้อมูลและยอมรับโดยผู้ใช้ การทำตามรูปแบบสถาปัตยกรรม MVC จะทำการแยกส่วนประกอบที่สำคัญเหล่านี้ทำให้สามารถนำโค้ดกลับมาใช้ใหม่และพัฒนาแบบขนานได้

รูปแบบนี้ได้รับความนิยมในการออกแบบเว็บแอพพลิเคชั่น ภาษาโปรแกรมที่ได้รับความนิยมเช่น JavaScript, Python, Ruby, PHP, Java และ C # มีเฟรมเวิร์ก MVC ที่ใช้ในการพัฒนาเว็บแอปพลิเคชั่นตรงๆ

แบบ

องค์ประกอบกลางของลวดลาย มันเป็นโครงสร้างข้อมูลแบบไดนามิกของแอปพลิเคชันซึ่งเป็นอิสระจากส่วนติดต่อผู้ใช้ มันจัดการข้อมูลตรรกะและกฎของแอปพลิเคชันโดยตรง

ดู

การแสดงข้อมูลใด ๆ เช่นแผนภูมิไดอะแกรมหรือตาราง สามารถดูได้หลายมุมมองของข้อมูลเดียวกันเช่นแผนภูมิแท่งสำหรับการจัดการและมุมมองแบบตารางสำหรับนักบัญชี

ตัวควบคุม

ยอมรับอินพุตและแปลงเป็นคำสั่งสำหรับโมเดลหรือมุมมอง

นอกเหนือจากการแบ่งแอปพลิเคชันออกเป็นส่วนประกอบเหล่านี้การออกแบบโมเดล - มุมมอง - คอนโทรลเลอร์จะกำหนดปฏิสัมพันธ์ระหว่างกัน

ตัวแบบมีหน้าที่ในการจัดการข้อมูลของแอพพลิเคชั่น ได้รับการป้อนข้อมูลของผู้ใช้จากคอนโทรลเลอร์

มุมมองหมายถึงการนำเสนอของโมเดลในรูปแบบเฉพาะ

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

Model – View – ViewModel (MVVM) เป็นรูปแบบสถาปัตยกรรมซอฟต์แวร์

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

MVVM เป็นรูปแบบการออกแบบรูปแบบการนำเสนอของมาร์ตินฟาวเลอร์ MVVM จะสรุปสถานะและพฤติกรรมของมุมมองในลักษณะเดียวกัน แต่โมเดลการนำเสนอจะสรุปมุมมอง (สร้างโมเดลมุมมอง) ในลักษณะที่ไม่ขึ้นอยู่กับแพลตฟอร์มส่วนต่อประสานผู้ใช้ที่เฉพาะเจาะจง

MVVM ได้รับการคิดค้นโดยสถาปนิก Ken Microsoft และ Ted Peters โดยเฉพาะเพื่อลดความซับซ้อนของการโปรแกรมมิงอินเทอร์เฟซผู้ใช้ รูปแบบถูกรวมเข้าไว้ใน Windows Presentation Foundation (WPF) (ระบบกราฟิก Microsoft .NET) และ Silverlight (อนุพันธ์ของแอปพลิเคชันอินเทอร์เน็ตของ WPF) John Gossman หนึ่งในสถาปนิก WPF และ Silverlight ของ Microsoft ประกาศ MVVM บนบล็อกของเขาในปี 2005

Model – View – ViewModel เรียกอีกอย่างว่า model – view – binder โดยเฉพาะอย่างยิ่งในการใช้งานที่ไม่เกี่ยวข้องกับแพลตฟอร์ม. NET ZK (เว็บแอ็พพลิเคชันเฟรมเวิร์กที่เขียนด้วย Java) และ KnockoutJS (ไลบรารี JavaScript) ใช้ model – view – binder ป้อนคำอธิบายรูปภาพที่นี่

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