MVP - Model View Presenter

Giới thiệu

- Trong bài viết giới thiệu về mô hình MVC, chúng ta đã đề cập đến các nhược điểm của ngôn ngữ ASP. Có thể thấy hiện giờ ít trang web nào sử dụng công nghệ ASP cũ để phát triển nữa mà thay vào đó là các ngôn ngữ mới hơn, tiện ích hơn như PHP, ASP.NET, Java, v.v. Microsoft giới thiệu ngôn ngữ ASP.NET với điểm nhấn tách riêng các thành phần giao diện và xử lý dữ liệu bussiness logic bằng mô hình code-behind. ASP.NET có vẽ như là một lựa chọn tốt cho các ứng dụng web đơn giản, nhưng chính mô hình code-behind sẽ gây ra một số khó khăn cho các ứng dụng web vừa và lớn:

- Code-behind dường như được thiết kế để làm quá nhiều việc, nó vừa là một nơi để xử lý các event, kiểm soát các workflow trong chương trình và nó còn là một layer trung gian giữa dữ liệu bên dưới và giao diện phía trên. Người lập trình có thể viết mọi thứ trong code-behind và làm cho nó trở nên vô cùng rối rắm. Để cho code-behind làm quá nhiều thứ sẽ làm cho code của bạn khó kiểm soát và khó test (Unit Test). Trong những ứng dụng web lớn, người ta xem một design tốt khi nó giảm thiểu sự phụ thuộc lẫn nhau giữa các tầng (layer) và làm sao để cho code-behind càng đơn giản càng tốt. Với mô hình Model-View-Presenter, chúng ta sẽ thấy rằng code-behind được giữ cho vô cùng đơn giản và không hề dính dáng gì đến những xử lý trên giao diện Web.

- Một nhược điểm khác của code-behind là nó hầu như rất khó để sử dụng lại những xử lý giao diện (presentation logic) giữa những trang code-behind khác nhau nếu không đưa các xử lý đó ra các lớp Utility hay Helpers để tránh trùng lặp code. Tất nhiên để làm được điều đó cần một thời gian để tổ chức các lớp cho thich hợp. Tuy nhiên, nó thường dẫn chúng ta đến việc thiết kế các lớp một cách rời rạc và giống như khi sử dụng ASP. Trong một design tốt, mỗi class trong hệ thống nên có duy nhất một nhiệm vụ và mục đích rõ ràng, nếu chúng ta cần tạo ra một class chỉ để tránh trùng lặp code giữa 2 hoặc nhiều nơi khác thì đó là một dấu hiệu xấu, một thiết kế tồi.

- Và một nhược điểm cố hữu mà tôi thường nhắc đến là khả năng sử dụng Unit Test để test các lớp code-behind này. Các lớp code-behind đều kế thừa từ System.Web.UI.Page nên khó có thể viết các Unit Test một cách tự nhiên và thuận lợi được.

- Đã có nhiều kĩ thuật được tìm ra để giải quyết vấn đề của code-behind. Chẳng hạn như Castle Monorail project đã kế thừa những lợi điểm của Ruby-On-Rails và không sử dụng mô hình ASP.NET event. Thực ra cũng giống như ASP.NET MVC Framework, Castle Monorail hướng người lập trình đến cách phát triển ứng dụng Web theo MVC hơn là MVP, và khi áp dụng những framework này, chúng ta sẽ làm web ASP.NET theo một cách hoàn toàn khác, không có postback, không có server controls,... Khác với các framework hỗ trợ MVC, các framework hỗ trợ MVP là những giải pháp trong đó vẫn giữ mô hình event của ASP.NET nhưng hướng đến mục tiêu làm cho code-behind càng đơn giản càng tốt. Model-View Presenter sẽ giúp bạn làm được chuyện đó mà không cần dựa trên một framework nào cả. Đó cũng chính là lý do rất nhiều lập trình viên Web đã chọn MVP thay vì MVC trước khi có những framework hỗ trợ MVC như hiện nay.

- Bên cạnh các ASP.NET MVC Framework, Castle Monorail, hiện nay đã có những framework hỗ trợ MVP cho .NET như MVC# FrameworkNMVP Framework. Hi vọng tôi có thời gian tìm hiểu và chia sẽ với các bạn muốn quan tâm. Trong bài viết này, tôi sẽ trình bay khái quát lý thuyết suông về MVP; một sample code sẽ được giới thiệu trong bài tiếp theo.

Các bạn đang xem bài viết về Model View Presenter từ blog của Nguyễn Thoại (http://nthoai.blogspot.com)
Model-View-Presenter

- Nhiều người cho rằng MVP là một design biến đổi của MVC. Điểm khác nhau dễ thấy nhất là Presenter và Controller :bbpraroi: hehe đùa thôi... Trong mô hình MVP, các lớp View sẽ được sử dụng thông qua một Interface được định nghĩa trong .NET. Các lớp Presenter tương ứng sẽ sử dụng Interface này để đọc và ghi dữ liệu lên trên các View. Trong đa số các cách implement, một View sẽ có một Presenter tương ứng của nó. View sẽ khởi tạo Presenter cho nó và truyền cho Presenter này tham chiếu đến chính nó. Khi một event nào trên view được kích hoạt chẳng hạn như button_clicked, text_changed,.. bản thân lớp View sẽ không làm gì cả mà sẽ để cho lớp Presenter xử lý những sự kiện đó. Presenter sẽ đọc dữ liệu từ View (vì nó giữ một instance của View như là một member trong class) thông qua View Interface, thực hiện những xử lý ứng với Event được kích hoạt và set những thay đổi từ dữ liệu Model lên trên View thông qua View Interface.

- Trong môi trường .NET, cùng một Presenter có thể được sử dụng cho View trên web như các trang ASP.NET hoặc được sử dụng cho các Form trong Windows Form Application. Các Presenter đọc và ghi dữ liệu thông qua một Interface của .NET nên nó hoàn toàn độc lập với layer View. Chính nhờ cách làm này mà ta có thể áp dụng Unit Test cho các lớp xử lý Presenter rất dễ dàng và nó cũng chính là một trong những lợi ích lớn nhất của MVP cho khả năng tái sử dụng.



Model View Presenter Solution Structure


Cập nhật View

- Khi thành phần dữ liệu Model được cập nhật, View cũng sẽ phải được cập nhật để hiển thị những thay đổi. Quá trình cập nhật View có thể được thực hiện bằng nhiều cách khác nhau. Có lẽ cũng từ những cách này mà Model-View-Presenter được chia thành hai loại là Passive View và Supervising Controller.

- Trong mô hình Passive View, Presenter sẽ cập nhật view tương ứng bằng cách đọc dữ liệu trực tiếp từ Model rồi set lên View, do đó các lớp View sẽ không biết gì về thay đổi dữ liệu bên dưới. Hay nói cách khác chúng hoàn toàn bị động theo như trên gọi.

- Còn trong mô hình Supervising Controller, các lớp View sẽ tương tác trực tiếp với Model bên dưới để đọc dữ liệu mà không cần thông qua các lớp Presenter. Presenter sẽ cập nhật Model; nó chỉ thay đổi những control trên View trong trường hợp có những xử lý giao diện phức tạp mà không thể khai báo trước chẳng hạn như ẩn hiện control, đổi màu text,…

Passive View and Supervising Controller


- Quyết định dùng Passive View hay Supervising Controller thường dựa trên nhu cầu test tự động của ứng dụng. Nếu bạn muốn làm một ứng dụng có thể test tự động dể dàng và cover hầu hết các xử lý bên trong thì Passive View là một lựa chọn thích hợp, mọi UI logic đều được test bằng cách viết lớp test cho các Presenter. Mặt khác, nếu bạn thích code đơn giản hơn thì Supervising Controller có vẻ là một lựa chọn thích hợp hơn. Đối với những thay đổi đơn giản trên giao diện, bạn cũng không cần đưa những xử lý cho các thay đổi đó vào lớp Presenter. Khi chọn lựa giữa Passive View và Supervising Controller, bạn nên cân nhắc các điều sau đây:

  • Cả hai cách đều cho phép bạn tăng khả năng test tự động cho các xử lý giao diện (presentation logic)
  • Passive View thường cung cấp khả năng test cao hơn Supervising Controller bởi vì tất cả các xử lý giao diện được đặt trong các lớp Presenter.
  • Supervising Controller sẽ đỡ phải code nhiều như Passive View bởi vì Passive View không cần thực hiện những cập nhật đơn giản cho View.

Tương tác với dữ liệu

- Bạn cần phân biệt rõ Model với Domain, hai khái niệm này hoàn toàn khác nhau. Chúng ta có thể implement các lớp tương tác với dữ liệu bằng nhiều cách khác nhau. Trong một số trường hợp, có thể bạn sẽ phải sử dụng Observer Pattern cho các Presenter và Model. Nó sẽ giúp cho Presenter nhận những events từ Model khi có sự thay đổi và từ đó cập nhật thay đổi đó lên trên View. Thông thường, người ta sẽ làm ra các lớp Service/Manager, các lớp này sẽ đóng vai trò như các lớp Bussiness Logic trong layer Model để giúp Presenter tương tác với database bên dưới:

MVP Tiers


Các nhược điểm của MVP

  • Có nhiều lớp, nhiều layer phải implement; có nghĩa độ phức tạp của ứng dụng sẽ tăng.
  • Bạn phải nghĩ ra một cách để kết hợp giữa các Views và các Presenters. Trong ASP.NET thì các lớp Code-Behind sẽ implement một interface IView nào đó và sử dụng một member Presenter.
  • Mô hình Model không biết gì về Presenter. Vì thế nếu dữ liệu Model bị thay đổi từ một chương trình khác thay vì bởi Presenter thì phải nghĩ ra một cách để Presenter biết. Các bạn có thể implement chức năng này nếu cần bằng cách sử dụng các events, hoặc tham khảo thiết kế Observer Pattern.



Trong bài sau tôi sẽ trình bày một sample cho Supervisinng Controller.:bbpxtay:

4 comments:

  1. foronereason Says:

    Bài này chưa nói kĩ về "Supervising Controller" và "Passive View" nên em cũng chưa hiểu nhiều, nhưng chắc phần em thắc mắc liên quan tới "Supervising Controller" phải ko anh Thoại :D

    Mô hình MVP nếu ko có nhiều ví dụ cụ thể thì cũng khó hình dung :D. À, em cũng chưa hiểu rõ Model và Domain khác nhau thế nào ? :D

    Chờ xem bài viết kế tiếp về sample của "Supervising Controller" của anh Thoại :D

  2. PapyrusRose Says:

    Model trừu tượng hóa problems trong Domain

  3. Nguyễn Quốc Tuấn Says:

    em củng đang tìm hiểu về mô hình MVP. trong quá trình tìm hiểu những cài gi em không hiểu anh có thể giúp em không.anh có thể liên lạc với em qua mail :quoctuan143@gmail.com. e rất vui được sự giúp đỡ của anh

  4. Y Trịnh Says:

    Rất dễ hiểu, dễ đọc. Thank bạn.

rss
 

About Me

Place I've live
Near Bossley Park, Sydney, NSW, Australia
Place I've work
  • Freelancer (from 06/2010 to present)
  • Harvey Nash (from 05/2008 to 06/2010)
  • DataDesign Vietnam (10/2005 to 04/2008)
Place I've studied
  • University of Natural Science (Bachelor of Science HoChiMinh City Vietnam From 2001 to 2005)
  • Le Hong Phong High School (HoChiMinh City Vietnam From 1997 to 2000)