Điều gì đi vào Bộ điều khiển Phần cứng trong Phần mềm MVC MVC?


186

Tôi nghĩ rằng tôi hiểu các khái niệm cơ bản của MVC - Model chứa dữ liệu và hành vi của ứng dụng, View có trách nhiệm hiển thị nó cho người dùng và Trình điều khiển xử lý đầu vào của người dùng. Điều tôi không chắc chắn là chính xác những gì diễn ra trong Bộ điều khiển.

Hãy nói ví dụ tôi có một ứng dụng khá đơn giản (tôi đặc biệt nghĩ về Java, nhưng tôi cho rằng các nguyên tắc tương tự được áp dụng ở nơi khác). Tôi tổ chức mã của tôi thành 3 gói gọi app.model, app.viewapp.controller.

Trong app.modelgói, tôi có một vài lớp phản ánh hành vi thực tế của ứng dụng. Những cái này extends Observablevà sử dụng setChanged()notifyObservers()để kích hoạt các khung nhìn để cập nhật khi thích hợp.

Các app.viewgói có một lớp (hoặc một số lớp học với nhiều loại khác nhau của màn hình) có sử dụng javax.swingcác thành phần để xử lý màn hình. Một số thành phần này cần phản hồi lại trong Mô hình. Nếu tôi hiểu chính xác, Chế độ xem không nên liên quan gì đến phản hồi - điều đó cần được Bộ điều khiển xử lý.

Vì vậy, những gì tôi thực sự đặt trong Bộ điều khiển? Tôi có đặt public void actionPerformed(ActionEvent e)trong Chế độ xem chỉ bằng một cuộc gọi đến một phương thức trong Bộ điều khiển không? Nếu vậy, có nên thực hiện bất kỳ xác nhận vv trong Bộ điều khiển? Nếu vậy, làm cách nào để tôi phản hồi các thông báo lỗi trở lại Chế độ xem - có nên chuyển qua Mô hình lại không, hay Bộ điều khiển chỉ nên gửi thẳng trở lại Chế độ xem?

Nếu xác thực được thực hiện trong Chế độ xem, tôi sẽ đặt gì vào Bộ điều khiển?

Xin lỗi vì câu hỏi dài, tôi chỉ muốn ghi lại sự hiểu biết của tôi về quy trình và hy vọng ai đó có thể làm rõ vấn đề này cho tôi!

Câu trả lời:


520

Trong ví dụ bạn đề xuất, bạn đã đúng: "người dùng đã nhấp vào nút 'xóa mục này' trong giao diện về cơ bản chỉ cần gọi chức năng" xóa "của bộ điều khiển. Tuy nhiên, bộ điều khiển không biết khung nhìn trông như thế nào và do đó, chế độ xem của bạn phải thu thập một số thông tin như "mục nào đã được nhấp?"

Trong một hình thức trò chuyện:

Xem : "Này, bộ điều khiển, người dùng chỉ nói với tôi rằng anh ta muốn xóa mục 4".
Người điều khiển : "Hmm, đã kiểm tra thông tin đăng nhập của anh ấy, anh ấy được phép làm điều đó ... Này, người mẫu, tôi muốn bạn lấy mục 4 và làm bất cứ điều gì bạn làm để xóa nó."
Mô hình : "Mục 4 ... hiểu rồi. Nó đã bị xóa. Quay lại với bạn, Người điều khiển."
Trình điều khiển : "Ở đây, tôi sẽ thu thập bộ dữ liệu mới. Quay lại với bạn, xem."
Xem : "Tuyệt, tôi sẽ hiển thị bộ mới cho người dùng ngay bây giờ."

Cuối phần đó, bạn có một tùy chọn: chế độ xem có thể đưa ra một yêu cầu riêng, "cung cấp cho tôi bộ dữ liệu gần đây nhất" và do đó, thuần túy hơn hoặc bộ điều khiển hoàn toàn trả về bộ dữ liệu mới với "xóa "Hoạt động.


90
Cuộc đối thoại đó là lời giải thích tốt nhất về MVC mà tôi đã gặp, cảm ơn!
Paul Walker

13
Tất cả các tốt, nhưng không có gì là sai với quan điểm đọc từ mô hình trực tiếp. "Bộ điều khiển không phải là cảnh sát dữ liệu". Ngoài ra còn có một học thuyết nói rằng giữ cho bộ điều khiển mỏng. Trình trợ giúp xem là một nơi hoàn hảo để thu thập dữ liệu sẵn sàng để được xem bởi chế độ xem của bạn. Người ta không cần phải gửi ngăn xếp bộ điều khiển hoàn chỉnh để sử dụng lại một số logic truy cập dữ liệu. Chi tiết hơn: rmauger.co.uk/2009/03/
Ngoại lệ vào

1
Tôi đồng ý với "Ngoại lệ e". Dữ liệu trong mô hình có thể được cập nhật bởi nhiều sự kiện, không nhất thiết phải là bộ điều khiển và do đó, trong một số thiết kế MVC, M báo hiệu cho V rằng dữ liệu bị bẩn và V có thể tự làm mới. C không có vai trò trong trường hợp đó.
Mishax

68

Vấn đề với MVClà mọi người nghĩ rằng khung nhìn, bộ điều khiển và mô hình phải độc lập nhất có thể với nhau. Chúng không - một khung nhìn và bộ điều khiển thường đan xen - nghĩ về nó như M(VC).

Bộ điều khiển là cơ chế đầu vào của giao diện người dùng, thường bị rối trong chế độ xem, đặc biệt là với GUI. Tuy nhiên, xem là đầu ra và bộ điều khiển là đầu vào. Một khung nhìn thường có thể hoạt động mà không có bộ điều khiển tương ứng, nhưng bộ điều khiển thường ít hữu ích hơn nếu không có chế độ xem. Bộ điều khiển thân thiện với người dùng sử dụng chế độ xem để diễn giải đầu vào của người dùng theo cách trực quan, có ý nghĩa hơn. Đây là những gì nó làm cho nó khó tách khái niệm bộ điều khiển khỏi chế độ xem.

Hãy nghĩ về một robot điều khiển vô tuyến trên một trường phát hiện trong một hộp kín như mô hình.

Mô hình là tất cả về chuyển đổi trạng thái và trạng thái không có khái niệm đầu ra (hiển thị) hoặc những gì đang kích hoạt chuyển đổi trạng thái. Tôi có thể có được vị trí của robot trên sân và robot biết cách chuyển vị trí (tiến một bước tiến / lùi / trái / phải. Dễ dàng hình dung mà không cần xem hoặc điều khiển, nhưng không có gì hữu ích

Hãy nghĩ về một chế độ xem mà không có bộ điều khiển, ví dụ như ai đó trong một phòng khác trên mạng trong một phòng khác đang xem vị trí robot khi tọa độ (x, y) truyền xuống bảng điều khiển cuộn. Khung nhìn này chỉ hiển thị trạng thái của mô hình, nhưng anh chàng này không có bộ điều khiển. Một lần nữa, dễ dàng hình dung quan điểm này mà không cần bộ điều khiển.

Hãy nghĩ về một bộ điều khiển mà không có tầm nhìn, ví dụ như ai đó bị nhốt trong tủ quần áo với bộ điều khiển vô tuyến được điều chỉnh theo tần số của robot. Bộ điều khiển này đang gửi đầu vào và gây ra các chuyển đổi trạng thái mà không biết họ đang làm gì với mô hình (nếu có gì). Dễ hình dung, nhưng không thực sự hữu ích nếu không có một số phản hồi từ chế độ xem.

Hầu hết các giao diện người dùng thân thiện với người dùng phối hợp chế độ xem với bộ điều khiển để cung cấp giao diện người dùng trực quan hơn. Ví dụ: hãy tưởng tượng một chế độ xem / bộ điều khiển với màn hình cảm ứng hiển thị vị trí hiện tại của robot trong 2 chiều và cho phép người dùng chạm vào điểm trên màn hình xảy ra ở phía trước robot. Bộ điều khiển cần chi tiết về chế độ xem, ví dụ: vị trí và tỷ lệ của chế độ xem và vị trí pixel của điểm được chạm tương đối với vị trí pixel của robot trên màn hình) để diễn giải điều này một cách chính xác (không giống như anh chàng bị khóa trong tủ quần áo với bộ điều khiển vô tuyến).

Tôi đã trả lời câu hỏi của bạn chưa? :-)

Bộ điều khiển là bất cứ thứ gì lấy đầu vào từ người dùng được sử dụng để làm cho mô hình chuyển sang trạng thái chuyển tiếp. Cố gắng giữ chế độ xem và bộ điều khiển tách biệt, nhưng nhận ra chúng thường phụ thuộc lẫn nhau, vì vậy không có vấn đề gì nếu ranh giới giữa chúng mờ, tức là có chế độ xem và bộ điều khiển vì các gói riêng biệt có thể không tách biệt rõ ràng như bạn thích, nhưng không sao Bạn có thể phải chấp nhận bộ điều khiển sẽ không được tách biệt rõ ràng khỏi chế độ xem vì chế độ xem là từ mô hình.

... có nên thực hiện bất kỳ xác nhận nào trong Bộ điều khiển không? Nếu vậy, làm cách nào để tôi phản hồi các thông báo lỗi trở lại Chế độ xem - có nên chuyển qua Mô hình lại không, hay Bộ điều khiển chỉ nên gửi thẳng trở lại Chế độ xem?

Nếu xác thực được thực hiện trong Chế độ xem, tôi sẽ đặt gì vào Bộ điều khiển?

Tôi nói rằng một khung nhìn và bộ điều khiển được liên kết sẽ tương tác tự do mà không cần thông qua mô hình. Bộ điều khiển lấy đầu vào của người dùng và nên thực hiện xác nhận (có thể sử dụng thông tin từ mô hình và / hoặc chế độ xem), nhưng nếu xác thực không thành công, bộ điều khiển sẽ có thể cập nhật trực tiếp chế độ xem liên quan của nó (ví dụ: thông báo lỗi).

Thử nghiệm axit cho điều này là để tự hỏi liệu một quan điểm độc lập (tức là anh chàng ở phòng khác đang xem vị trí robot qua mạng) có nên xem bất cứ điều gì hay không do lỗi xác thực của người khác (ví dụ như anh chàng trong tủ quần áo đã cố gắng nói với robot bước ra khỏi sân). Nói chung, câu trả lời là không - lỗi xác nhận đã ngăn quá trình chuyển đổi trạng thái. Nếu không có trạng thái tĩnh lặng (robot không di chuyển), thì không cần phải nói các quan điểm khác. Anh chàng trong tủ chỉ không nhận được bất kỳ phản hồi nào rằng anh ta đã cố gắng gây ra sự chuyển đổi bất hợp pháp (không có chế độ xem - giao diện người dùng xấu) và không ai khác cần phải biết điều đó.

Nếu anh chàng với màn hình cảm ứng cố gắng đưa robot ra khỏi sân, anh ta nhận được một tin nhắn thân thiện với người dùng yêu cầu anh ta không giết robot bằng cách gửi nó ra khỏi trường phát hiện, nhưng một lần nữa, không ai cần biết điều này.

Nếu quan điểm khác làm cần biết về các lỗi này, sau đó bạn có hiệu quả nói rằng các đầu vào từ người sử dụng và bất kỳ sai sót kết quả là một phần của mô hình và toàn bộ điều là một chút phức tạp hơn ...


23

Đây là một bài viết tốt về những điều cơ bản của MVC.

Nó nói ...

Bộ điều khiển - Bộ điều khiển chuyển các tương tác với khung nhìn thành các hành động được thực hiện bởi mô hình.

Nói cách khác, logic kinh doanh của bạn. Bộ điều khiển phản hồi các hành động của người dùng đã thực hiện trong chế độ xem và trả lời. Bạn đặt xác thực ở đây và chọn chế độ xem phù hợp nếu xác thực thất bại hoặc thành công (trang lỗi, hộp thông báo, bất cứ điều gì).

Có một bài viết hay tại Fowler .


MVP là một tùy chọn khác được thảo luận trong bài viết mà bạn tham khảo, xem martinfowler.com/eaaDev/ModelViewPresenter.html
Jon

Cảm ơn các liên kết, họ chắc chắn làm cho đọc thú vị.
Paul Walker

18

Mẫu MVC chỉ muốn bạn tách bản trình bày (= view) khỏi logic nghiệp vụ (= model). Phần điều khiển chỉ có để gây nhầm lẫn.


1
Chính xác, những gì tôi luôn nghĩ cho đến bây giờ nhưng không bao giờ có can đảm để nói với bất cứ ai .... hoặc có thể không thể đưa ra những từ thích hợp.
dùng1451111

1
Model-View-Confusion
Mưa

10

Thực tế mà nói, tôi chưa bao giờ thấy khái niệm bộ điều khiển là một khái niệm đặc biệt hữu ích. Tôi sử dụng tách mô hình / khung nhìn nghiêm ngặt trong mã của mình nhưng không có bộ điều khiển được xác định rõ ràng. Nó dường như là một sự trừu tượng không cần thiết.

Cá nhân, MVC toàn diện có vẻ giống như mẫu thiết kế nhà máy ở chỗ nó dễ dẫn đến thiết kế khó hiểu và quá phức tạp. Đừng là một phi hành gia kiến ​​trúc .


9

Dựa trên câu hỏi của bạn, tôi có ấn tượng rằng bạn hơi mơ hồ về vai trò của Người mẫu. Mô hình được cố định trên dữ liệu liên quan đến ứng dụng; nếu ứng dụng có cơ sở dữ liệu, công việc của Người mẫu sẽ là nói chuyện với nó. Nó cũng sẽ xử lý bất kỳ logic đơn giản nào liên quan đến dữ liệu đó; nếu bạn có một quy tắc nói rằng cho tất cả các trường hợp trong đó TABLE.foo == "Hoan hô!" và TABLE.bar == "Huzzah!" sau đó đặt TABLE.field = "W00t!", sau đó bạn muốn Model chăm sóc nó.

Bộ điều khiển là thứ nên xử lý phần lớn hành vi của ứng dụng. Vì vậy, để trả lời câu hỏi của bạn:

Tôi có đặt void void ActionPerformed (ActionEvent e) trong Chế độ xem chỉ bằng một cuộc gọi đến một phương thức trong Trình điều khiển không?

Tôi sẽ nói không. Tôi muốn nói rằng nên sống trong Bộ điều khiển; Chế độ xem chỉ đơn giản là cung cấp dữ liệu đến từ giao diện người dùng vào Bộ điều khiển và để Bộ điều khiển quyết định phương thức nào sẽ được gọi để phản hồi.

Nếu vậy, có nên thực hiện bất kỳ xác nhận vv trong Bộ điều khiển?

Phần lớn xác nhận của bạn thực sự phải được thực hiện bởi Bộ điều khiển; cần trả lời câu hỏi liệu dữ liệu có hợp lệ hay không và nếu không, hãy cung cấp các thông báo lỗi thích hợp cho Chế độ xem. Trong thực tế, bạn có thể kết hợp một số kiểm tra độ tỉnh táo đơn giản vào lớp View để cải thiện trải nghiệm người dùng. (Tôi đang suy nghĩ chủ yếu về môi trường web, nơi bạn có thể muốn có thông báo lỗi bật lên ngay khi người dùng nhấn "Gửi" thay vì chờ toàn bộ quá trình gửi -> quá trình -> tải chu kỳ trang trước khi nói với họ rằng họ đã làm hỏng .) Chỉ cần cẩn thận; bạn không muốn nhân đôi nỗ lực nhiều hơn bạn phải làm, và trong nhiều môi trường (một lần nữa, tôi đang nghĩ về web), bạn thường phải coi bất kỳ dữ liệu nào đến từ giao diện người dùng là một gói bẩn thỉu nói dối cho đến khi bạn '

Nếu vậy, làm cách nào để tôi phản hồi các thông báo lỗi trở lại Chế độ xem - có nên chuyển qua Mô hình lại không, hay Bộ điều khiển chỉ nên gửi thẳng trở lại Chế độ xem?

Bạn nên thiết lập một số giao thức trong đó Chế độ xem không nhất thiết phải biết điều gì xảy ra tiếp theo cho đến khi Bộ điều khiển nói với nó. Màn hình nào bạn hiển thị chúng sau khi người dùng bấm nút đó? Chế độ xem có thể không biết và Bộ điều khiển có thể không biết cho đến khi nó nhìn vào dữ liệu mà nó vừa nhận được. Nó có thể là "Chuyển đến màn hình khác, như mong đợi" hoặc "Ở trên màn hình này và hiển thị thông báo lỗi này".

Theo kinh nghiệm của tôi, giao tiếp trực tiếp giữa Mô hình và Chế độ xem phải rất, rất hạn chế và Chế độ xem không được thay đổi trực tiếp bất kỳ dữ liệu nào của Mô hình; đó phải là công việc của Kiểm soát viên.

Nếu xác thực được thực hiện trong Chế độ xem, tôi sẽ đặt gì vào Bộ điều khiển?

Xem ở trên; xác nhận thực sự phải có trong Bộ điều khiển. Và hy vọng bạn có một số ý tưởng về những gì nên được đưa vào Bộ điều khiển ngay bây giờ. :-)

Điều đáng chú ý là tất cả có thể bị mờ một chút xung quanh các cạnh; như với hầu hết mọi thứ phức tạp như công nghệ phần mềm, các cuộc gọi phán xét sẽ rất nhiều. Chỉ cần sử dụng phán đoán tốt nhất của bạn, cố gắng duy trì sự nhất quán trong ứng dụng này và cố gắng áp dụng các bài học bạn học được cho dự án tiếp theo.


7

Bộ điều khiển thực sự là một phần của View. Công việc của nó là tìm ra (các) dịch vụ nào cần thiết để thực hiện yêu cầu, các giá trị không theo thứ tự từ Chế độ xem thành các đối tượng mà giao diện dịch vụ yêu cầu, xác định Chế độ xem tiếp theo và sắp xếp lại phản hồi thành dạng mà Chế độ xem tiếp theo có thể sử dụng . Nó cũng xử lý bất kỳ trường hợp ngoại lệ nào được ném và đưa chúng vào Chế độ xem mà người dùng có thể hiểu.

Tầng dịch vụ là thứ biết các trường hợp sử dụng, đơn vị công việc và các đối tượng mô hình. Bộ điều khiển sẽ khác nhau cho từng loại chế độ xem - bạn sẽ không có cùng bộ điều khiển cho máy tính để bàn, dựa trên trình duyệt, Flex hoặc UI di động. Vì vậy, tôi nói rằng nó thực sự là một phần của giao diện người dùng.

Định hướng dịch vụ: đó là nơi công việc được thực hiện.


3

Bộ điều khiển chủ yếu để phối hợp giữa khung nhìn và mô hình.

Thật không may, đôi khi nó kết hợp với chế độ xem - trong các ứng dụng nhỏ mặc dù điều này không quá tệ.

Tôi đề nghị bạn đặt:

public void actionPerformed(ActionEvent e)

trong bộ điều khiển. Sau đó, người nghe hành động của bạn trong chế độ xem của bạn nên ủy quyền cho bộ điều khiển.

Về phần xác nhận, bạn có thể đặt nó trong chế độ xem hoặc bộ điều khiển, cá nhân tôi nghĩ rằng nó thuộc về bộ điều khiển.

Tôi chắc chắn sẽ khuyên bạn nên xem qua Chế độ xem thụ động và Giám sát giám sát (về cơ bản là những gì Trình bày mô hình xem được chia thành - ít nhất là bởi Fowler). Xem:

http://www.martinfowler.com/eaaDev/PassiveScreen.html

http://www.martinfowler.com/eaaDev/SupervisingPresenter.html


3

Đây là một quy luật của mà tôi sử dụng: nếu nó là một thủ tục mà tôi sẽ sử dụng đặc biệt cho một hành động trên này trang, nó thuộc về bộ điều khiển, không phải là mô hình. Mô hình chỉ nên cung cấp một sự trừu tượng nhất quán cho việc lưu trữ dữ liệu.

Tôi đã nghĩ ra điều này sau khi làm việc với một ứng dụng web lớn được viết bởi các nhà phát triển, những người nghĩ rằng họ hiểu MVC nhưng thực sự không phải vậy. Các "bộ điều khiển" của chúng được giảm xuống còn tám dòng gọi các phương thức lớp tĩnh mà chúng ta thường gọi là không có nơi nào khác: - / làm cho các mô hình của chúng ít hơn nhiều so với các cách tạo không gian tên. Tái cấu trúc điều này đúng cách thực hiện ba điều: chuyển tất cả SQL vào lớp truy cập dữ liệu (còn gọi là mô hình), làm cho mã điều khiển dài hơn một chút nhưng dễ hiểu hơn rất nhiều và giảm các tệp "mô hình" cũ thành không có gì. :-)


1

cũng lưu ý rằng mỗi tiện ích Xoay có thể được coi là có chứa ba thành phần MVC: mỗi thành phần có Mô hình (ví dụ: NútModel), Chế độ xem (BasicButtonUI) và Điều khiển (chính JButton).


1

Bạn về cơ bản là đúng về những gì bạn đặt trong bộ điều khiển. Đó là cách duy nhất mà Người mẫu nên tương tác với Chế độ xem. Hành động có thể được đặt trong Chế độ xem, nhưng chức năng thực tế có thể được đặt trong một lớp khác sẽ đóng vai trò là Trình điều khiển. Nếu bạn định làm điều này, tôi khuyên bạn nên xem xét mẫu Lệnh, đây là một cách trừu tượng hóa tất cả các lệnh có cùng một bộ thu. Xin lỗi vì sự lạc đề.

Dù sao, việc triển khai MVC phù hợp sẽ chỉ có các tương tác sau: Model -> View View -> Controller Controller -> View

Nơi duy nhất có thể có tương tác khác là nếu bạn sử dụng người quan sát để cập nhật Chế độ xem, thì Chế độ xem sẽ cần hỏi Bộ điều khiển để biết thông tin cần thiết.


0

Theo tôi hiểu, Bộ điều khiển chuyển từ các hành động giao diện người dùng sang các hành động ở cấp ứng dụng. Chẳng hạn, trong một trò chơi video, Bộ điều khiển có thể dịch "di chuyển chuột rất nhiều pixel" thành "muốn nhìn theo hướng như vậy và theo hướng đó. Trong ứng dụng CRUD, bản dịch có thể được" nhấp vào nút đó và nút như vậy "thành "In điều này", nhưng khái niệm là như nhau.


0

Do đó, chúng tôi làm điều đó, sử dụng Bộ điều khiển chủ yếu để xử lý và phản ứng với đầu vào / hành động do người dùng điều khiển (và _Logic cho mọi thứ khác, ngoại trừ chế độ xem, dữ liệu và công cụ _Model rõ ràng):

(1) (phản hồi, phản ứng - những gì webapp "làm" để đáp lại người dùng) Blog_Controll

-> chính ()

-> xử lýSubmit_AddNewCustomer ()

-> verifyUser_HasProperAuth ()

(2) (logic "kinh doanh", webapp nghĩ gì và như thế nào) Blog_Logic

-> sanityCheck_AddNewCustomer ()

-> xử lýUsernameChange ()

-> sendEmail_NotifyRequestedUpdate ()

(3) (lượt xem, cổng, cách ứng dụng web "xuất hiện") Blog_View

-> genWelcome ()

-> genForm_AddNewBlogEntry ()

-> genPage_DataEntryForm ()

(4) (chỉ đối tượng dữ liệu, có được trong _ construc () của mỗi Blog lớp *, được sử dụng để giữ tất cả dữ liệu webapp / inmemory cùng một đối tượng) Blog_Meta

(5) (lớp dữ liệu cơ bản, đọc / ghi vào DB) Blog_Model

-> saveDataToMemcache ()

-> saveDataToMongo ()

-> saveDataToSql ()

-> loadData ()

Đôi khi chúng ta có một chút bối rối về việc đặt một phương thức ở đâu, trong C hoặc L. Nhưng Mô hình rất chắc chắn, rõ ràng và vì tất cả dữ liệu trong bộ nhớ đều nằm trong _Meta, nên nó cũng không có trí tuệ . Tuy nhiên, bước tiến lớn nhất của chúng tôi là áp dụng việc sử dụng _Meta, vì điều này đã loại bỏ tất cả các mấu chốt từ các đối tượng _C, _L và _Model khác nhau, giúp mọi thứ trở nên dễ dàng về mặt tinh thần, cộng với, trong một cú đánh, nó đã cho chúng tôi biết được gọi là "Dependency Injection", hoặc một cách để vượt qua toàn bộ môi trường cùng với tất cả dữ liệu (phần thưởng có thể dễ dàng tạo ra môi trường "thử nghiệm").

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.