Trong một kiến ​​trúc MVC, Model và View đối với Bộ điều khiển được kết hợp chặt chẽ như thế nào?


16

Tôi đã có một ứng dụng sử dụng MVC, nhưng tôi gặp khó khăn một chút về cách trình điều khiển nên được kiến ​​trúc. Ví dụ: Chế độ xem chỉ xem một số tập hợp con dữ liệu của mô hình cùng một lúc. Tuy nhiên, tôi không chắc chính xác cách sắp xếp này. Chẳng hạn, Chế độ xem hoặc Mô hình gọi trực tiếp các chức năng trên Bộ điều khiển chẳng hạn? Thông qua một số loại giao diện? Hay họ hoàn toàn gói gọn và không bao giờ biết về Bộ điều khiển hay nhau?

Chỉ là một chỉnh sửa; đây là một ứng dụng tùy chỉnh không được viết trong bất kỳ khung web nào, vì vậy tôi không tìm kiếm các chi tiết cụ thể về khung ở đây và có quyền tự do lựa chọn.


1
Tôi sẽ không trả lời vì kinh nghiệm của tôi bị hạn chế trong kiến ​​trúc MVC, nhưng từ tất cả những gì tôi đã nghe và nói với người khác, M & V được liên kết chặt chẽ với nhau nhưng không phải là C. Nói chung, M gọi các chức năng trên C và V thường chỉ lưu trữ dữ liệu cho một số tập hợp con của M.
Steven Evers

8
@SnOrfus: Điều đó hoàn toàn trái ngược với những gì tôi nghĩ - M & V được ghép nối với C nhưng không khớp với nhau.
DeadMG

1
Làm thế nào nhiều câu trả lời có thể sai như vậy. Dưới đây đọc phiên bản MS của msdn.microsoft.com/en-us/library/ff649643.aspx
Reactgular

Câu trả lời:


15

Bộ điều khiển kiểm soát dòng hoạt động. Người dùng thực hiện hành động này, bộ điều khiển chuyển dữ liệu xem sang miền mà làm bất cứ điều gì cần làm sau đó, dựa trên (các) phản hồi, bộ điều khiển cho khung nhìn hiển thị tiếp theo (và cung cấp cho nó đủ dữ liệu để làm vì thế).

Do đó, bộ điều khiển phải được ghép nối với mô hình miền, ở một mức độ nào đó. I E. Bạn có thể đặt một lớp dịch vụ ở giữa nhưng, theo định nghĩa nghiêm ngặt, nó sẽ trở thành một phần của miền.

Nó cũng được kết hợp với dữ liệu xem nhưng không phải là chính nó. I E. nó chỉ đơn giản nói "hiển thị chế độ xem của khách hàng bằng cách sử dụng chi tiết khách hàng này." Khung sau đó quyết định nơi cần tìm quan điểm đó.

Bây giờ, điều này sẽ cho phép bạn tách mô hình miền khỏi chế độ xem, bằng cách sử dụng mô hình chế độ xem của cùng một dữ liệu. Một số nhà phát triển làm điều này, một số thì không, và tôi nghĩ đó phần lớn là vấn đề sở thích cá nhân.

Trong Rails, bạn được khuyến khích rất nhiều để đẩy các đối tượng miền (ActiveRecord) đến chế độ xem và tin rằng chế độ xem không tận dụng quyền truy cập đó (ví dụ: bạn không nên gọi khách hàng từ chế độ xem, mặc dù vậy sẽ có sẵn).

Trong thế giới .NET, chúng ta có xu hướng giảm rủi ro bằng cách không cho phép những điều không nên xảy ra và có thể vì lý do đó, đối với tôi, mô hình khung nhìn tách rời là phổ biến hơn.


1
Xem mô hình là một thực tiễn rất phổ biến khi nói đến thử nghiệm đơn vị. Thông thường bạn sẽ tự động ánh xạ mô hình miền hoặc đối tượng DTO sang mô hình xem. Sau đó, bạn sẽ sử dụng mô hình xem của bạn trong một khung nhìn. Xem mô hình có thể dễ dàng kiểm tra và nó không bị ràng buộc với một lớp bên dưới.
CodeART

7

Lưu ý: Robert C. Martin (còn gọi là chú Bob) giải thích điều này theo cách hài hước và hay hơn nhiều trong bài phát biểu của mình, Architecture the Lost Years . Một chút dài nhưng dạy rất nhiều khái niệm tốt.

tl; dr: Đừng suy nghĩ và lập kế hoạch cho ứng dụng của bạn theo MVC. Khung MVC chỉ là một chi tiết triển khai.

Điều khó hiểu nhất về MVC là, các nhà phát triển cố gắng sử dụng tất cả các thành phần được dán lại với nhau.

Hãy thử suy nghĩ trong các điều khoản của một chương trình, không phải trong các điều khoản của khung.

Chương trình của bạn có một mục đích. Nó lấy một số dữ liệu, thực hiện mọi thứ với dữ liệu và trả về một số dữ liệu.

Bằng cách đó, controllercơ chế phân phối của chương trình của bạn.

  1. Một người dùng gửi yêu cầu đến chương trình của bạn (giả sử, thêm một sản phẩm vào giỏ hàng).
  2. Bộ điều khiển nhận yêu cầu đó (thông tin sản phẩm và thông tin người dùng), nó gọi phần cần thiết trong chương trình của bạn sẽ xử lý yêu cầu này $user->addToCart($product)
  3. Chương trình của bạn ( addToCartchức năng của userđối tượng trong trường hợp này) thực hiện công việc mà nó dự định thực hiện và trả về phản hồi (giả sử success)
  4. Bộ điều khiển chuẩn bị phản hồi bằng cách sử dụng có liên quan view: vd. trong đối tượng điều khiển$this->render($cartView('success')

Bằng cách này, các bộ điều khiển được tách rời khỏi chương trình và được sử dụng làm cơ chế phân phối. Họ không biết chương trình của bạn hoạt động như thế nào, họ chỉ biết phần nào của chương trình cần được gọi cho các yêu cầu.

Nếu bạn muốn sử dụng một khung công tác khác, ứng dụng của bạn sẽ không cần thay đổi, bạn sẽ chỉ cần viết các bộ điều khiển có liên quan để gọi chương trình của bạn cho các yêu cầu.

Hoặc nếu bạn muốn tạo một phiên bản máy tính để bàn, ứng dụng của bạn sẽ giữ nguyên, bạn chỉ cần chuẩn bị một cơ chế phân phối.

Model. Hãy nghĩ về nó như một cơ chế bền bỉ.

Theo cách OO, có các đối tượng trong chương trình của bạn chứa dữ liệu.

class User {
    //...
    private $id;
    private $shoppingCart;
    //...
}

class Product {
    //...
    private $id;
    //...
}

Khi bạn thêm một sản phẩm vào giỏ hàng, bạn có thể thêm sản phẩm product::idvào user::shoppingCart.

Và khi bạn muốn duy trì dữ liệu, bạn có thể sử dụng modelmột phần của khung, thường bao gồm sử dụng ORM, để ánh xạ các lớp vào các bảng cơ sở dữ liệu.

Nếu bạn muốn thay đổi ORM bạn sử dụng, chương trình của bạn sẽ giữ nguyên, chỉ có thông tin ánh xạ sẽ thay đổi. Hoặc nếu bạn muốn tránh tất cả các cơ sở dữ liệu cùng nhau, bạn chỉ cần ghi dữ liệu vào các tệp văn bản thuần túy và ứng dụng của bạn sẽ giữ nguyên.


Vì vậy, viết chương trình của bạn đầu tiên. Nếu bạn lập trình theo cách 'OO', hãy sử dụng các đối tượng cũ đơn giản của ngôn ngữ. Đừng nghĩ về mặt MVC lúc đầu.


Video tuyệt vời. Cảm ơn. Tôi sẽ không đồng ý với cách giải thích của bạn về nó mặc dù. MVC không phải là một chi tiết theo nghĩa mà chú Bob có. Bạn sẽ lưu ý rằng MVC là một mẫu kiến ​​trúc giống như mẫu "Interactor / Entity / Boundary" mà anh ta đang thiết lập. Mặt khác, bất kỳ hệ thống MVC cụ thể nào, chẳng hạn như Spring hoặc bất cứ điều gì, thực sự là thứ mà anh ấy khuyên bạn nên trì hoãn. Như ông giải thích, các khung công tác được gọi là "MVC" này là một dạng khốn của thuật ngữ này.
Edward Strange

Phải, tôi đã viết rằng theo cách mà mọi người nghĩ là gì MVC. Đó là lý do tại sao tôi viết MVC Framework.
Hakan Deryal

2

Martin Fowler làm tốt công việc mô tả mô hình MVC. Đây là một liên kết đến bài viết của mình về nó http://martinfowler.com/eaaDev/uiArchs.html

Lưu ý trích dẫn của ông về Bản trình bày tách biệt "Ý tưởng đằng sau Bản trình bày tách biệt là phân chia rõ ràng giữa các đối tượng miền mô hình hóa nhận thức của chúng ta về thế giới thực và các đối tượng trình bày là các yếu tố GUI mà chúng ta thấy trên màn hình."


1

Đây là một ví dụ đơn giản về cách sử dụng MVC trong ứng dụng Java Swing điển hình ...

Giả sử bạn có Bảng điều khiển chứa Nút và TextField. Khi nhấn nút, một sự kiện sẽ được kích hoạt, dẫn đến một số thay đổi trạng thái trong ứng dụng. Khi thay đổi trạng thái được đăng ký, TextField sẽ bị tắt.

Sau đó, đây sẽ là cách tiếp cận điển hình được thực hiện bởi một ứng dụng MVC đơn giản ...

Bộ điều khiển đăng ký chính nó như là người nghe các sự kiện của View. Khi nhấn vào nút, Chế độ xem không xử lý sự kiện; Bộ điều khiển nào. Bộ điều khiển là đặc trưng của Swing vì nó phải xử lý các sự kiện liên quan đến Swing.

Kiểm soát viên nhận được thông báo này và phải quyết định ai phải xử lý thông báo đó (Chế độ xem hoặc Mô hình). Vì sự kiện này sẽ thay đổi trạng thái của ứng dụng, nó quyết định chuyển tiếp thông tin đến Mô hình chịu trách nhiệm về dữ liệu và logic chương trình. Một số mắc lỗi khi đặt logic chương trình trong Bộ điều khiển nhưng trong OOP, Mô hình đại diện cho cả dữ liệu VÀ hành vi. Đọc Martin Fowler về việc này.

Thông điệp được nhận bởi Người mẫu trong bối cảnh thích hợp. Đó là, nó hoàn toàn không có bất kỳ tham chiếu nào đến Swing hoặc bất kỳ tài liệu tham khảo cụ thể về GUI nào khác. Thông báo này nói với Mô hình và CHỈ mô hình. Nếu bạn thấy mình đang nhập các câu lệnh javax.swing trong Mô hình, bạn không mã hóa Mô hình chính xác.

Mô hình sau đó đặt trạng thái của nó thành 'bị vô hiệu hóa' và tiến hành thông báo cho bất kỳ bên nào quan tâm về sự thay đổi mô hình này. Chế độ xem, quan tâm đến sự kiện này đã tự đăng ký làm Người quan sát về mọi thay đổi mô hình. Khi sự kiện thay đổi trạng thái Mô hình được chọn bởi Chế độ xem, nó sẽ tiến hành vô hiệu hóa TextField của nó. Việc Chế độ xem để lấy thông tin Chỉ đọc trực tiếp từ Mô hình của nó cũng là hợp pháp mà không phải thông qua Bộ điều khiển (thường thông qua một giao diện cụ thể được Mô hình đưa ra cho hoạt động đó)

Bằng cách thúc đẩy sự kết hợp lỏng lẻo như vậy giữa Trình bày và Logic nghiệp vụ và Lớp dữ liệu, bạn sẽ thấy mã của mình dễ bảo trì hơn nhiều. Khi các hệ thống phát triển, cách tiếp cận của bạn với MVC cũng vậy. Ví dụ, MVC phân cấp là một phần mở rộng thường được sử dụng để liên kết các bộ ba MVC với nhau để tạo thành các hệ thống rộng cho doanh nghiệp lớn mà không cần ghép các hệ thống con lại với nhau


0

Khớp nối (loại bạn muốn tránh) liên quan đến sự phụ thuộc lẫn nhau giữa hai lớp. Nghĩa là, một Foo phụ thuộc vào một Thanh và một Thanh phụ thuộc vào một Foo để bạn thực sự không thể sửa đổi cái này mà không sửa đổi cái khác. Đó là một điều xấu.

Tuy nhiên, bạn thực sự không thể tránh có MỘT SỐ phụ thuộc. Các lớp phải biết một chút về nhau, nếu không họ sẽ không bao giờ giao tiếp.

Trong mẫu MVC, Bộ điều khiển kiểm soát giao tiếp giữa Mô hình miền và Chế độ xem bản trình bày. Như vậy, Bộ điều khiển phải biết đủ về Mô hình để yêu cầu nó thực hiện những gì nó phải làm. Bộ điều khiển cũng phải biết đủ về Chế độ xem để có thể trình bày cho khách hàng hoặc người dùng. Vì vậy, Bộ điều khiển mô hình có sự phụ thuộc vào cả hai. Tuy nhiên, Chế độ xem có thể tồn tại hoàn toàn tốt mà không cần Bộ điều khiển - không có sự phụ thuộc ở đó. Tương tự như vậy, Model không có phụ thuộc vào bộ điều khiển - nó chỉ đơn giản là những gì nó là. Cuối cùng, Model và View hoàn toàn tách biệt với nhau.

Về cơ bản, Bộ điều khiển là mức độ gián tiếp tách rời Chế độ xem khỏi Mô hình, để chúng không phải biết về nhau.


À - đó là lý do tại sao các downvote - tôi viết sai. Tôi có nghĩa là Bộ điều khiển có phụ thuộc vào cả hai. Ôi!
Matthew Flynn

-5

Theo kinh nghiệm của tôi, nhìn chung mô hình chỉ phụ thuộc vào một khung nhìn, không phải là một góc nhìn cụ thể, thường là một người quan sát ... nếu nó có bất kỳ khớp nối nào như vậy.

Quan điểm nói chung kết hợp với bất cứ điều gì nó đang nhìn, có ý nghĩa. Khó có thể đưa ra một chế độ xem có thể tách rời khỏi chế độ xem ... nhưng đôi khi bạn có thể có khớp nối một phần hoặc một cái gì đó.

Bộ điều khiển thường có xu hướng kết hợp cả hai. Điều này cũng có ý nghĩa vì công việc của nó là biến các sự kiện xem thành các thay đổi mô hình.

Tất nhiên, đây chỉ là một xu hướng tôi đã quan sát và không thực sự nói bất cứ điều gì về bất kỳ ví dụ cụ thể nào.

Để hiểu MVC là gì và mối quan hệ khớp nối có xu hướng là gì, bạn nên tìm hiểu xem MVC xuất hiện như thế nào. Môi trường trong đó MVC được tạo là một trong đó "widget" là các thành phần biểu mẫu mà bạn có thể xây dựng các hộp thoại không tồn tại. Một "khung nhìn" là một cái hộp và nó đã thu hút mọi thứ. Một khung nhìn văn bản sẽ là một hộp sẽ vẽ văn bản. Một khung nhìn danh sách là một hộp sẽ vẽ một danh sách. "Bộ điều khiển" đã nhận tất cả các sự kiện chuột và bàn phím từ hệ thống UI diễn ra trong chế độ xem đó; không có sự kiện "textChanged" hoặc "selectChanged". Bộ điều khiển sẽ nhận tất cả các sự kiện mức thấp này và tạo ra sự tương tác với mô hình. Mô hình, khi được thay đổi sẽ thông báo quan điểm của nó; kể từ đó chúng tôi đã xem mối quan hệ này là "người quan sát" và nó '

THAT là bản chất của mẫu MVC. Do loại lập trình UI cấp thấp này thường không được thực hiện nữa, nên MVC đã phát triển theo nhiều hướng khác nhau. Một số thứ đi theo cái tên đó ngày nay hầu như không có gì giống như MVC và thực sự nên được gọi là thứ khác. Nó vẫn có thể được sử dụng mặc dù theo nghĩa của một hộp thoại khi toàn bộ tương tác với một đối tượng lớn hơn. Có nhiều lựa chọn thay thế tốt hơn mặc dù.

Về cơ bản, mọi thứ mà MVC có nghĩa là để giải quyết đều xảy ra bên trong các widget và là thứ chúng ta không còn phải sử dụng nữa.


Đối với những người nghĩ rằng họ biết rõ hơn:

http://www.codeproject.com/Articles/42830/Model-View-Controll-Model-View-Presenter-and-Mod

http://msdn.microsoft.com/en-us/l Library / ff649643.aspx

Tôi chắc chắn có nhiều hơn nhưng những thứ đó chỉ là đầu danh sách trong google. Như bạn có thể thấy, mô hình phụ thuộc rất nhiều vào giao diện xem trong triển khai NHIỀU. Nói chung một mô hình là có thể quan sát và quan điểm là một người quan sát.

Nhưng tại sao lại để sự thật cản trở ...

Một bài viết đã được đăng trong một câu trả lời khác cũng hỗ trợ cho tuyên bố của tôi:

http://martinfowler.com/eaaDev/uiArchs.html

Nếu mọi người muốn tiếp tục nói rằng MỌI NGƯỜI trong ngành thiết kế là sai thì không sao.


4
Điều này hoàn toàn sai. Một mô hình không được phụ thuộc vào một cái nhìn bao giờ! Ngay cả khi quan điểm đó là trừu tượng hoặc một giao diện. Một mô hình nên được tách rời hoàn toàn khỏi bài thuyết trình!
Falcon

3
Trả lời là sai. Mô hình không phụ thuộc vào một khung nhìn hoặc bộ điều khiển.
CodeART

2
@Crazy Eddie Bạn nói: "Theo kinh nghiệm của tôi, nói chung mô hình chỉ phụ thuộc vào một chế độ xem, không phải là một quan sát cụ thể, thường là một người quan sát" Tham chiếu được trích dẫn của bạn nói: "Tuy nhiên, mô hình phụ thuộc vào cả chế độ xem và bộ điều khiển." Bạn thậm chí đã đọc các bài báo được trích dẫn? Không giống như nó.
CodeART

2
@Crazy Eddie: Tôi không quan tâm những gì ai đó trên bảng mã ngu ngốc viết. Đây là một thiết kế khủng khiếp. Sử dụng một người quan sát để lắng nghe các thay đổi là được, nhưng đặt giao diện trình bày trong một mô hình miền thì thật quá sai lầm. Mã được trích dẫn từ bài viết bị thiếu sót trong một số cách cơ bản liên quan đến MVC. Nó thậm chí còn cho phép mô hình hoàn toàn phụ thuộc vào bộ điều khiển. Thật là tào lao.
Falcon

3
@Crazy Eddie: lol @ downvote hung hăng. Tôi đã ghen tị với bạn?
Falcon

-7
  • Bộ điều khiển gửi mô hình đến một khung nhìn và nó xử lý mô hình được gửi từ các khung nhìn, tuy nhiên nó không được kết hợp chặt chẽ với một khung nhìn hoặc một mô hình.

Nếu bộ điều khiển được kết hợp chặt chẽ với một khung nhìn, thì chúng ta sẽ ở trong một thế giới của các hình thức web. Bạn sẽ có một mã phía sau sẽ được gắn vào một tệp mẫu (Áp dụng cho các biểu mẫu web ASP.NET)

Do đó, bộ điều khiển không được ghép với mô hình hoặc khung nhìn. Nó chỉ là một cơ chế để xử lý các yêu cầu và gửi phản hồi.

  • View được gắn chặt với một mô hình. Thay đổi mô hình của bạn (ví dụ: thay đổi thuộc tính của nó) và bạn sẽ phải thay đổi quan điểm của mình.

  • Mô hình không được gắn chặt với một khung nhìn. Thay đổi chế độ xem và nó sẽ không ảnh hưởng đến mô hình.

  • Mô hình không biết gì về bộ điều khiển hoặc các khung nhìn nơi nó có thể được sử dụng. Do đó, mô hình không được kết hợp chặt chẽ với một khung nhìn hoặc bộ điều khiển.

Một cách khác để suy nghĩ về điều này:

  • Thay đổi bộ điều khiển - chế độ xem và mô hình sẽ không bị ảnh hưởng

  • Thay đổi mô hình - chế độ xem sẽ bị hỏng vì nó phụ thuộc vào mô hình

  • Thay đổi chế độ xem - mô hình và bộ điều khiển sẽ không bị ảnh hưởng

Sự kết hợp lỏng lẻo này trong các dự án MVC là điều giúp chúng dễ dàng kiểm tra đơn vị.


1
Điều này là sai, nó không buồn cười. Thậm chí không đáng để giải thích. Chỉ cần bỏ qua câu trả lời này hoàn toàn.
Phản ứng

1
@MathewFoscarini Ngừng khóc và để lại "câu trả lời đúng"
CodeART

2
lol, toàn bộ lý thuyết thiết kế đằng sau MVC là chúng không phụ thuộc vào nhau.
Phản ứng

Tôi đã để lại nhiều thông tin cho bạn, hy vọng nó sẽ có ý nghĩa
CodeART
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.