Theo cách tiếp cận truyền thống hoặc lý thuyết khôn ngoan, ViewModel phải là một phần của lớp giao diện người dùng. Ít nhất là cái tên nói như vậy.
Nhưng khi bạn bắt đầu tự thực hiện nó với Khung thực thể, MVC, Kho lưu trữ, v.v, thì bạn sẽ nhận ra điều gì đó khác.
Ai đó phải lập bản đồ Mô hình thực thể/DB với Chế độ xem (DTO được đề cập ở cuối). Điều này có nên được thực hiện trong [A] lớp giao diện người dùng (bởi Bộ điều khiển) hay trong [B] lớp Dịch vụ?
Tôi đi với Tùy chọn B.Tùy chọn A là không không vì thực tế đơn giản là một số mô hình thực thể kết hợp với nhau để tạo thành một ViewModel. Chúng ta không thể truyền dữ liệu không cần thiết cho lớp UI, trong khi trong tùy chọn B, dịch vụ có thể chơi với dữ liệu và chỉ truyền yêu cầu/tối thiểu đến lớp UI sau khi ánh xạ (tới ViewModel).
Một lần nữa, chúng ta hãy đi với tùy chọn A, đặt ViewModel trong lớp giao diện người dùng (và mô hình thực thể trong lớp dịch vụ).
Nếu lớp dịch vụ cần ánh xạ tới ViewModel, thì lớp Dịch vụ cần truy cập ViewModel trong lớp giao diện người dùng. Thư viện/dự án nào? ViewModel phải nằm trong một dự án riêng biệt trong lớp giao diện người dùng và dự án này cần được tham chiếu bởi Lớp dịch vụ. Nếu ViewModel không nằm trong một dự án riêng biệt, thì có tham chiếu vòng tròn, vì vậy không đi. Có vẻ khó xử khi có lớp UI truy cập lớp dịch vụ nhưng chúng tôi vẫn có thể đối phó với nó.
Nhưng điều gì xảy ra nếu có một ứng dụng giao diện người dùng khác sử dụng dịch vụ này? Điều gì sẽ xảy ra nếu có ứng dụng dành cho thiết bị di động? ViewModel có thể khác nhau như thế nào? Dịch vụ có nên truy cập vào cùng một dự án mô hình xem không? Tất cả các dự án giao diện người dùng có truy cập vào cùng một dự án ViewModel hay không?
Sau những cân nhắc này, câu trả lời của tôi là đặt dự án ViewModel trong Lớp dịch vụ. Mỗi lớp giao diện người dùng phải truy cập vào lớp Dịch vụ. Và có thể có rất nhiều ViewModels tương tự mà tất cả chúng có thể sử dụng (do đó ánh xạ trở nên dễ dàng hơn cho lớp dịch vụ). Ánh xạ được thực hiện thông qua LINQ những ngày này, đó là một cộng thêm.
Cuối cùng, có cuộc thảo luận này về DTO. Và cũng về chú thích dữ liệu trong ViewModels. ViewModels với chú thích dữ liệu (Microsoft.Web.Mvc.DataAnnotations.dll) không thể cư trú trong lớp dịch vụ thay vì chúng cư trú trong lớp giao diện người dùng (nhưng ComponentModel.DataAnnotations.dll có thể nằm trong lớp dịch vụ). Vì vậy, DTO thực sự là một ViewModel bởi vì chủ yếu sẽ có một trên một bản đồ giữa hai (nói với AutoMapper). Một lần nữa DTO vẫn có logic cần thiết cho UI (hoặc nhiều ứng dụng) và nằm trong Service Layer. Và lớp UI ViewModel (nếu chúng ta sử dụng Microsoft.Web.Mvc.DataAnnotations.dll) chỉ để sao chép dữ liệu từ DTO, với một số 'hành vi'/thuộc tính được thêm vào nó.
[Bây giờ cuộc thảo luận này là về để có một lượt thú vị hãy đọc tiếp ...: I]
Và đừng nghĩ thuộc tính dữ liệu chú thích là chỉ dành riêng cho giao diện người dùng. Nếu bạn giới hạn xác thực bằng cách sử dụng System.ComponentModel.DataAnnotations.dll thì cùng một viewmodel cũng có thể được sử dụng cho front232 end & xác nhận hợp lệ phụ trợ (do đó loại bỏ UI-residing-viewmodel-copy-of-DTO). Nhiều hơn các thuộc tính cũng có thể được sử dụng trong các mô hình thực thể. Ví dụ: sử dụng .tt, các khung dữ liệu của Entity Framework có thể được tạo tự động với các thuộc tính xác thực để thực hiện một số xác nhận hợp lệ db như độ dài tối đa trước khi gửi đến phần cuối. Một ưu điểm nữa là nếu các thay đổi hợp lệ của backend trong DB thì .tt (đọc db specifics và tạo thuộc tính cho lớp thực thể) sẽ tự động chọn nó. Điều này có thể buộc thử nghiệm đơn vị xác thực UI thất bại, đó là một dấu cộng lớn (vì vậy chúng tôi có thể sửa và thông báo cho tất cả UI/người tiêu dùng thay vì vô tình quên và thất bại). Vâng, cuộc thảo luận đang hướng tới một thiết kế khung tốt. Như bạn có thể thấy, tất cả đều liên quan: xác thực cấp độ khôn ngoan, chiến lược kiểm tra đơn vị, chiến lược bộ nhớ đệm, v.v.
Mặc dù không liên quan trực tiếp đến câu hỏi. 'ViewModel Façade' được đề cập trong này phải xem channel 9 link cũng đáng để khám phá. Nó bắt đầu chính xác ở 11 phút 49 giây trong video. Bởi vì đây sẽ là bước tiếp theo/suy nghĩ khi câu hỏi hiện tại của bạn ở trên được sắp xếp: 'Cách tổ chức chế độ xem?'
Cũng trong ví dụ "_repository.ListContacts()" của bạn đang trả về chế độ xem từ kho lưu trữ. Đây không phải là cách trưởng thành. Các kho lưu trữ nên cung cấp các mô hình thực thể hoặc các mô hình db. Điều này được chuyển đổi thành các mô hình xem và đó là mô hình khung nhìn này được lớp dịch vụ trả về.
Bạn cũng có thể muốn xem http://weblogs.asp.net/scottgu/archive/2009/04/28/free-asp-net-mvc-nerddinner-tutorial-now-in-html. aspx –
Hướng dẫn NerdDinner là nơi tồi tệ nhất để tìm kiếm thông tin này. Thật tuyệt vời khi trình diễn các tính năng MVC nhưng kiến trúc mà nó ngụ ý là khủng khiếp. – Aaronaught
@Aaronaught vì bạn rõ ràng là một chuyên gia, đó là hướng dẫn chuyên sâu của bạn về kiến trúc MVC chính xác ở đâu? –