Suy nghĩ triển khai Model-View-Presenter


34

Tôi đang cố gắng nắm bắt tốt cách thực hiện phân tách tốt giữa UI và mô hình, nhưng tôi gặp khó khăn trong việc tìm ra chính xác nơi để phân chia các dòng.

Tôi đã xem xét Model-View-Presenter, nhưng tôi không chắc chính xác cách thực hiện nó. Ví dụ: Chế độ xem của tôi có nhiều hộp thoại ..

  • Có nên có một lớp View với các thể hiện của mỗi hộp thoại không? Vậy thì trong trường hợp đó, các hộp thoại nên tương tác với Người thuyết trình như thế nào? I E. nếu một hộp thoại riêng lẻ cần yêu cầu dữ liệu từ Mô hình thông qua Người thuyết trình, thì hộp thoại sẽ tham chiếu đến Người thuyết trình như thế nào? Thông qua một tham chiếu đến Chế độ xem được cung cấp cho nó trong khi xây dựng?
  • Tôi đã suy nghĩ có lẽ khung nhìn nên là một lớp tĩnh? Sau đó, các hộp thoại GetView và nhận Presenter từ đó ...
  • Tôi đã suy nghĩ về việc thiết lập Người thuyết trình với quyền sở hữu Chế độ xem và Mô hình (trái ngược với Chế độ xem có Người thuyết trình và Người thuyết trình có Mô hình) và Người thuyết trình đăng ký gọi lại cho các sự kiện trong Chế độ xem, nhưng điều đó có vẻ rất nhiều kết hợp nhiều hơn (hoặc ngôn ngữ phụ thuộc, ít nhất.)

Tôi đang cố gắng:

  1. làm cho điều này tách rời càng tốt
  2. lý tưởng là có thể ghép nối Người thuyết trình / Mô hình với Chế độ xem của các ngôn ngữ khác (Tôi chưa thực hiện được rất nhiều nội dung ngôn ngữ, nhưng tôi biết điều đó là có thể, đặc biệt là void(void)tôi càng có thể gắn bó, ít nhất là ứng dụng C # với một Thư viện C ++ ...
  3. giữ mã sạch sẽ và đơn giản

Vì vậy, bất kỳ đề xuất làm thế nào các tương tác nên được xử lý?


Bạn đã xem bài viết này chưa?: En.wikipedia.org/wiki/Model-view-presenter
Bernard

1
Tôi có .. Tôi thấy nó hơi nhanh và cao cấp, tôi đang tìm hiểu rõ hơn về cách xử lý nhiều hộp thoại trong một dự án lớn với càng ít khớp nối càng tốt ..
trycatch 22/03

Câu trả lời:


37

Chào mừng bạn đến một dốc trơn trượt. Đến thời điểm này, bạn đã nhận ra rằng có một sự biến đổi vô tận của tất cả các tương tác xem mô hình. MVC, MVP (Taligent, Cá heo, Chế độ xem thụ động), MVVM chỉ để đặt tên cho một số ít.

Mẫu Trình bày Mô hình Chế độ xem, giống như hầu hết các mẫu kiến ​​trúc được mở cho nhiều thử nghiệm và đa dạng. Một điểm chung của tất cả các biến thể là vai trò của người trình bày với tư cách là "người trung gian" giữa chế độ xem và mô hình. Hai phổ biến nhất là Chế độ xem thụ độngTrình điều khiển / Trình điều khiển giám sát - [ Fowler ]. Chế độ xem thụ động coi giao diện người dùng là giao diện rất nông giữa người dùng và người trình bày. Nó chứa rất ít nếu có logic, ủy thác càng nhiều trách nhiệm cho người trình bày. Giám sát / Người điều khiểncố gắng tận dụng sự ràng buộc dữ liệu được tích hợp trong nhiều khung UI. UI xử lý đồng bộ hóa dữ liệu nhưng các bước của người trình bày / bộ điều khiển để logic phức tạp hơn. Trong cả hai trường hợp, mô hình, khung nhìn và người trình bày tạo thành một bộ ba

Có rất nhiều cách để làm điều này. Rất phổ biến để xem điều này được xử lý bằng cách coi mỗi hộp thoại / biểu mẫu là một chế độ xem khác nhau. Nhiều lần có mối quan hệ 1: 1 giữa lượt xem và người thuyết trình. Đây không phải là một quy tắc khó, nhanh. Nó khá phổ biến để có một người thuyết trình xử lý nhiều quan điểm liên quan hoặc ngược lại. Tất cả phụ thuộc vào sự phức tạp của quan điểm và sự phức tạp của logic kinh doanh.

Đối với cách các khung nhìn và người thuyết trình có được một tham chiếu với nhau, điều này đôi khi được gọi là hệ thống dây điện . Bạn có ba lựa chọn:

Chế độ xem giữ tham chiếu đến người trình bày
Một biểu mẫu hoặc hộp thoại thực hiện chế độ xem. Biểu mẫu có các trình xử lý sự kiện chỉ định cho người trình bày bằng cách sử dụng các lệnh gọi trực tiếp:

MyForm.SomeEvent(Sender)
{
  Presenter.DoSomething(Sender.Data);
}

Vì người trình bày không có tham chiếu đến chế độ xem, nên chế độ xem phải gửi dữ liệu đó dưới dạng đối số. Người thuyết trình có thể giao tiếp trở lại chế độ xem bằng cách sử dụng các chức năng sự kiện / gọi lại mà chế độ xem phải lắng nghe.

Người trình bày giữ một tham chiếu để xem
Trong kịch bản, khung nhìn hiển thị các thuộc tính cho dữ liệu mà nó hiển thị cho người dùng. Người trình bày lắng nghe các sự kiện và thao tác các thuộc tính trên khung nhìn:

Presenter.SomeEvent(Sender)
{
  DomainObject.DoSomething(View.SomeProperty);
  View.SomeOtherProperty = DomainObject.SomeData;
}

Cả hai đều có một tham chiếu với nhau tạo thành một phụ thuộc vòng tròn
Kịch bản này thực sự dễ làm việc hơn các đối tượng khác. Khung nhìn phản ứng với các sự kiện bằng cách gọi các phương thức trong người trình bày. Người trình bày đọc / sửa đổi dữ liệu từ chế độ xem thông qua các thuộc tính được hiển thị.

View.SomeEvent(Sender)
{
  Presenter.DoSomething();
}

Presenter.DoSomething()
{
  View.SomeProperty = DomainObject.Calc(View.SomeProperty);
}

Có những vấn đề khác cần được xem xét với các mẫu MVP. Thứ tự tạo, tuổi thọ đối tượng, nơi diễn ra hệ thống dây điện, liên lạc giữa các bộ ba MVP nhưng câu trả lời này đã phát triển đủ lâu rồi.


1
Điều này chắc chắn là hữu ích. Giao tiếp giữa các bộ ba và suốt đời là nơi tôi hiện đang gặp khó khăn khi tôi đang nắm bắt một số điều này.
trycatch

8

Như mọi người đã nói, có hàng tá ý kiến ​​và không một ý kiến ​​nào trong số đó là đúng hay sai. Không đi vào vô số các mẫu và chỉ tập trung vào MVP ở đây một số gợi ý về việc thực hiện.

Giữ chúng tách biệt. Khung nhìn nên thực hiện một giao diện hình thành liên kết giữa khung nhìn và người trình bày. Khung nhìn tạo ra một người thuyết trình và tiêm chính nó vào người trình bày và đưa ra các phương thức mà nó đưa ra để người trình bày tương tác với khung nhìn. Khung nhìn có trách nhiệm thực hiện các phương thức hoặc thuộc tính này theo bất kỳ cách nào nó muốn. Nói chung, bạn có một chế độ xem: một người thuyết trình nhưng trong một số trường hợp, bạn có thể có nhiều chế độ xem: một người thuyết trình (web, wpf, v.v.). Chìa khóa ở đây là người trình bày không biết gì về việc triển khai UI và chỉ tương tác với chế độ xem thông qua giao diện.

Đây là một ví dụ. Đầu tiên chúng ta có một lớp view với một phương thức đơn giản để hiển thị thông báo cho người dùng:

interface IView
{
  public void InformUser(string message);
}

Bây giờ đây là người trình bày. Lưu ý rằng người trình bày đưa IView vào hàm tạo của nó.

class Presenter
{
  private IView _view;
  public Presenter(IView view)
  {
    _view = view;
  }
}

Bây giờ đây là giao diện người dùng thực tế. Đây có thể là một cửa sổ, một hộp thoại, một trang web, vv Không quan trọng. Lưu ý hàm tạo cho khung nhìn sẽ tạo ra người trình bày bằng cách tự tiêm vào nó.

class View : IView
{
  private Presenter _presenter;

  public View()
  {
    _presenter = new Presenter(this);
  }

  public void InformUser(string message)
  {
    MessageBox.Show(message);
  }
}

Người trình bày không quan tâm đến cách thức thực hiện phương thức mà nó vừa thực hiện. Đối với tất cả những người trình bày biết, nó có thể được ghi vào một tệp nhật ký và thậm chí không hiển thị nó cho người dùng.

Trong mọi trường hợp, người trình bày thực hiện một số công việc với mô hình ở mặt sau và tại một số điểm muốn thông báo cho người dùng về những gì đang xảy ra. Vì vậy, bây giờ chúng ta có một phương thức ở đâu đó trong người trình bày gọi ra thông báo lượt xem InformUser.

class Presenter
{
  public void DoSomething()
  {
    _view.InformUser("Starting model processing...");
  }
}

Đây là nơi bạn có được sự tách rời của bạn. Người trình bày chỉ giữ một tham chiếu đến việc triển khai IView và không thực sự quan tâm đến cách thức triển khai.

Đây cũng là một triển khai của người nghèo vì bạn có một tham chiếu đến Người trình bày trong chế độ xem và các đối tượng được đặt thông qua các hàm tạo. Trong một giải pháp mạnh mẽ hơn, có lẽ bạn sẽ muốn xem xét các bộ điều khiển đảo ngược (IoC) như Windsor, Ninject, v.v. sẽ giải quyết việc triển khai IView cho bạn khi chạy theo yêu cầu và do đó làm cho nó thậm chí còn tách rời hơn.


4

Tôi nghĩ điều quan trọng cần nhớ là Người điều khiển / Người trình bày là nơi hành động thực sự diễn ra. Khớp nối trong Bộ điều khiển là không thể tránh khỏi vì cần thiết.

Điểm cốt lõi của Bộ điều khiển là nếu bạn thay đổi Chế độ xem, thì Mô hình không phải thay đổi và ngược lại (nếu Mô hình thay đổi, Chế độ xem không phải là một trong hai) bởi vì Bộ điều khiển là dịch Mô hình vào View và quay lại. Nhưng Bộ điều khiển sẽ thay đổi khi Mô hình hoặc Chế độ xem thay đổi do bạn thực sự phải dịch trong Bộ điều khiển cách Mô hình được xem cách nhận các thay đổi được thực hiện trong Chế độ xem lại vào Chế độ.

Ví dụ tốt nhất tôi có thể đưa ra là khi tôi viết một ứng dụng MVC, tôi không chỉ có dữ liệu trong chế độ xem GUI mà còn có thể viết một thói quen đẩy dữ liệu được kéo từ Mô hình vào stringtrình gỡ lỗi để hiển thị trong trình gỡ lỗi (và bằng cách mở rộng thành một tệp văn bản thuần túy). Nếu tôi có thể lấy dữ liệu Mô hình và dịch nó tự do thành văn bản mà không thay đổi Chế độ xem hoặc Mô hình và chỉ Bộ điều khiển, thì tôi đang đi đúng hướng.

Điều đó đang được nói, bạn sẽ phải có các tài liệu tham khảo giữa các thành phần khác nhau để làm cho tất cả hoạt động. Bộ điều khiển cần biết về Chế độ xem để đẩy dữ liệu, Chế độ xem cần biết về Bộ điều khiển để thông báo cho nó khi có thay đổi (như khi Người dùng nhấp vào "Lưu" hoặc "Mới ..."). Bộ điều khiển cần biết về Mô hình để lấy dữ liệu, nhưng tôi cho rằng Mô hình không nên biết về bất cứ điều gì khác.

Hãy cẩn thận: Tôi đến từ một nền tảng hoàn toàn Mac, Objective-C, Ca cao thực sự đẩy bạn vào mô hình MVC cho dù bạn có muốn hay không.


Đây chắc chắn là mục tiêu của tôi. Vấn đề chính của tôi là làm thế nào để thiết lập Chế độ xem - liệu nó có phải là một lớp với một phiên bản của mỗi hộp thoại hay không, sau đó sử dụng View.Getters gọi Dialog.Getters hoặc nếu Người trình bày có thể gọi Dialog.Getters trực tiếp ( cái này có vẻ quá chặt chẽ, nên có lẽ là không?)
trycatch 22/03

Tôi nghĩ Người trình bày / Người kiểm soát phải chịu trách nhiệm hoàn toàn cho Chế độ xem, vì vậy, sau này. Một lần nữa, một số khớp nối chắc chắn sẽ xảy ra, nhưng ít nhất nếu định hướng trách nhiệm rõ ràng, thì việc bảo trì sẽ dễ dàng hơn trong thời gian dài.
Philip Regan

2
Tôi chắc chắn đồng ý P / C phải chịu trách nhiệm cho Chế độ xem, nhưng tôi nghĩ một phần được cho là làm cho MVP trở nên mạnh mẽ là khả năng kéo toàn bộ thư viện UI ra và cắm một cái mới vào và với một số thao tác xoa bóp (dllimporting và whatnot) có thể chạy một cái khác ở vị trí của nó. Điều này có khó khăn hơn khi Bộ điều khiển / Người thuyết trình truy cập trực tiếp vào các hộp thoại không? Tôi chắc chắn không cố gắng để tranh luận, chỉ cần hiểu thêm :)
trycatch

Tôi nghĩ rằng sức mạnh thực sự đến từ hai hướng: Thứ nhất là Chế độ xem và Mô hình không liên quan gì đến nhau và thứ hai là phần lớn công việc phát triển, công cụ của ứng dụng, được thực hiện trong một ngăn chứa gọn gàng đơn vị, Người điều khiển. Nhưng một số chảy máu trách nhiệm chắc chắn sẽ xảy ra. Ít nhất phần lớn việc hoán đổi giao diện sẽ được thực hiện trong Bộ điều khiển và mọi liên kết từ Chế độ xem sẽ là tối thiểu. Như những người khác đã nói, một số chảy máu của logic được mong đợi và cho phép. MVC không phải là một viên đạn ma thuật.
Philip Regan

Điểm quan trọng để tách rời là người thuyết trình CHỈ truy cập chế độ xem thông qua các giao diện được xác định rõ (độc lập thư viện UI), vì vậy đó là cách thư viện UI có thể được thay thế cho một giao diện khác (một giao diện khác sẽ triển khai cùng giao diện cho biểu mẫu / cửa sổ / hộp thoại / trang / kiểm soát / bất cứ điều gì)
Marcel Toth

2

Nói chung, bạn muốn mô hình của mình gói gọn tất cả các tương tác với mô hình đó. Ví dụ: các hành động CRUD của bạn (Tạo, Đọc, Cập nhật, Xóa) đều là một phần của mô hình. Các tính toán đặc biệt cũng vậy. Có một vài lý do tốt cho việc này:

  • Tự động hóa thử nghiệm của bạn cho mã này dễ dàng hơn
  • Nó giữ tất cả những thứ quan trọng ở một nơi

Trong bộ điều khiển của bạn (ứng dụng MVC), tất cả những gì bạn đang làm là thu thập các mô hình bạn cần sử dụng trong chế độ xem của mình và gọi các chức năng phù hợp trên mô hình. Mọi thay đổi về trạng thái của mô hình xảy ra trong lớp này.

Chế độ xem của bạn chỉ đơn giản hiển thị các mô hình mà bạn đã chuẩn bị. Về cơ bản, khung nhìn chỉ đọc mô hình và điều chỉnh đầu ra của nó cho phù hợp.

Ánh xạ nguyên tắc chung đến các lớp thực tế

Hãy nhớ rằng các hộp thoại của bạn là lượt xem. Nếu bạn đã có một lớp hộp thoại, không có lý do gì để tạo một lớp "Xem" khác. Lớp Presenter về cơ bản liên kết mô hình với các điều khiển trong View. Logic nghiệp vụ và tất cả dữ liệu quan trọng được lưu trữ trong mô hình.

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.