Mô hình béo / bộ điều khiển mỏng so với lớp dịch vụ [đã đóng]


83

Tôi đã phát triển các ứng dụng doanh nghiệp trong nhiều năm bằng cách sử dụng .Net Các ứng dụng của tôi thường có mô hình miền chứa các thực thể ánh xạ tới bảng SQL DB. Tôi sử dụng mẫu Kho lưu trữ, chèn Phụ thuộc và lớp dịch vụ.

Gần đây, chúng tôi đã bắt đầu thực hiện các dự án MVC 3 và chúng tôi đã có một cuộc tranh luận nên đặt logic nào. Tôi đã xem qua kiến ​​trúc Mô hình điều khiển / FAT mỏng và đang tự hỏi làm thế nào để lớp dịch vụ phù hợp với

Tùy chọn 1 - Mô hình nói chuyện với các dịch vụ

Bộ điều khiển mỏng, gọi các phương thức trên các mô hình. Các mô hình "biết" cách tải bản thân từ DB và nói chuyện với các kho lưu trữ hoặc dịch vụ. Ví dụ: customerModel có phương thức Load (id) và tải khách hàng và một số đối tượng con như GetContracts ().

Tùy chọn 2 - Người điều khiển nói chuyện với các dịch vụ

Bộ điều khiển yêu cầu Dịch vụ truy xuất các đối tượng mô hình. Logic của việc tải / lưu trữ, v.v. Nằm trong lớp dịch vụ. Mô hình là một mô hình thực thể thuần túy chỉ có dữ liệu.

Tại sao tùy chọn 1 lại là lựa chọn tốt hơn đặc biệt là khi chúng tôi nói về các ứng dụng doanh nghiệp, kinh nghiệm của tôi cho tôi biết hãy tách biệt các mối quan tâm, giữ cho các mô hình VÀ Bộ điều khiển càng mỏng càng tốt và có các dịch vụ chuyên biệt thực hiện Logic kinh doanh (imcl. Tương tác DB)

Cảm ơn tất cả lời khuyên và tài liệu tham khảo đến các nguồn tốt.

Câu trả lời:


94

Tất cả những điều này phụ thuộc vào ý định và yêu cầu của ứng dụng của bạn.

Điều đó nói rằng, đây là gợi ý của tôi cho các ứng dụng web "quy mô trung bình" (không phải nhà hàng địa phương và không phải Twitter / Facebook).

  1. Mô hình miền Lean

    Các đối tượng kiểu POCO khô khan, tốt hơn là không biết đến kiến ​​trúc MVC của ứng dụng web của bạn để được kết hợp chặt chẽ với nhau từ việc triển khai cụ thể của bạn càng tốt. ).

    "Mô hình" trong MVC chính xác nhất có nghĩa là mô hình mà Bộ điều khiển biết và do đó là mô hình dành cho Chế độ xem .

    Trong các ứng dụng nhỏ hơn (thường là Hướng dẫn), các mô hình thực thể của "Lớp mô hình ứng dụng / miền" của bạn thường giống các đối tượng được khởi tạo mà bộ điều khiển chuyển đến Chế độ xem.

    Trong các ứng dụng lớn hơn, các nhà phát triển thường sử dụng các nguyên lý của kiến ​​trúc MVVM và bắt đầu sử dụng các đối tượng View Model riêng biệt. Bộ điều khiển thường gọi các dịch vụ bậc trung hoạt động với các thực thể không nhìn thấy bên dưới. Trong trường hợp này, M trong MVC chính xác nhất có nghĩa là Mô hình Chế độ xem.

  2. Lớp dịch vụ mạnh mẽ

    Điều này không có nghĩa là logic béo phì , mà là các dịch vụ đơn lẻ được viết tốt. Mặc dù mã hóa logic nghiệp vụ của bạn trong các dịch vụ bên ngoài mô hình có "thủ tục" hơn một chút so với "OOP" thuần túy, nhưng nó giúp ích rất nhiều cho việc ghép nối lỏng lẻo, kiểm tra và triển khai linh hoạt (ví dụ: triển khai n-tier).

    Trong thực tế cá nhân của tôi, tôi viết mã các dịch vụ ở cả lớp dữ liệu, mà tôi coi là mô hình hành vi của tôi đối với các đối tượng POCO (cơ chế bền bỉ, xác thực mức thấp, v.v.) và các dịch vụ cấp cao hơn (chức năng kinh doanh / quy trình làm việc) gần hơn cơ học MVC.

  3. Bộ điều khiển tinh gọn

    Tôi đảm bảo rằng người điều khiển của tôi chỉ đơn thuần là huấn luyện viên , trong đó nó không phải là người chơi (dịch vụ) hay người chơi (mô hình thực thể hoặc mô hình chế độ xem), mà chỉ đơn giản là quyết định ai chơi ở vị trí nào và chơi gì. Bộ điều khiển của tôi thực hiện hai việc:

    1. Gọi các dịch vụ tương tác với Mô hình thực thể / miền

    2. Chuẩn bị Mô hình Chế độ xem cho Chế độ xem thích hợp.

    Ngay cả các hành động của bộ điều khiển được xác thực / ủy quyền cũng được thực hiện thông qua các dịch vụ / thuộc tính được đưa vào.


CHỈNH SỬA 1:

Hãy nhớ rằng điều này không có nghĩa là Mô hình thực thể / miền của bạn đang hoặc phải thiếu máu. ORM, kho lưu trữ và nhà máy, xác nhận hoặc cơ khí trạng thái đều được hoan nghênh. Nó chỉ có nghĩa là đối với các ứng dụng có quy mô vừa phải, Mô hình trong MVC đại diện cho mô hình dành cho bộ điều khiển, giao cho Chế độ xem của bạn .

Hy vọng rằng điểm này sẽ làm dịu các tông đồ của Fowler, những người tin rằng mô hình dữ liệu thiếu máu là một mô hình phản đối . Đồng thời, nó cũng phản ánh một góc hơi thủ tục hơn OOP nơi mà nó là tinh khiết hơn để bao gồm hành vi trong các lớp mô hình.

Không có "sự thật cuối cùng", nhưng sử dụng mẫu này, bạn sẽ thấy dễ dàng xây dựng, thử nghiệm và triển khai các ứng dụng của mình - trong khi vẫn duy trì nhiều khả năng tái sử dụng và khả năng mở rộng.


CHỈNH SỬA 2:

Điều đó nói lên rằng, ngay cả đối với các ứng dụng có kích thước khiêm tốn, việc kiểm tra kiến ​​trúc quá mức (một hệ thống từ mọt sách được tạo thành?) Là quá phổ biến. Ví dụ: bao bọc một ORM với một mẫu kho lưu trữ, và sau đó viết các dịch vụ để sử dụng kho lưu trữ ... tất cả điều này là tốt để tách mối quan tâm và tương tự, nhưng nếu dự án của bạn không yêu cầu (và không có khả năng sớm yêu cầu ) những thứ như vậy, đừng xây dựng nó. Không có gì sai khi bỏ qua kho lưu trữ cùng nhau, viết các dịch vụ doanh nghiệp mỏng (ví dụ: các lớp truy vấn) chống lại ORM hoặc thậm chí để bộ điều khiển của bạn nói chuyện trực tiếp với nó. Tất cả phụ thuộc vào quy mô.


CHỈNH SỬA 3:

Tôi muốn lưu ý rằng lời giải thích và lời khuyên này dành cho ngữ cảnh của kiến ​​trúc MVC phía máy chủ như ASP.Net, không phải cho các khung phía clent như Knockout hoặc Backbone.


11
Đây gần như giống hệt mẫu thiết kế mà tôi sử dụng ngoại trừ bộ điều khiển không có kiến ​​thức về kho lưu trữ. Bộ điều khiển chỉ tương tác với các dịch vụ tương tác với các kho lưu trữ.
Lester

2
@Lester Tôi đã chỉnh sửa để xóa điều đó. 95% thời gian của tôi cũng không, ý tưởng là các dịch vụ làm được. Trên các ứng dụng nhỏ nó có thể là quá mức cần thiết nhưng bất cứ ai một thói quen tốt và dễ dàng hơn để duy trì với một container IoC
one.beat.consumer

1
+1 @ one.beat.consumer: đây cũng là cách tiếp cận mà tôi thực hiện trong các dự án của mình ... đôi khi quá thuần túy về các quy tắc dẫn đến các giải pháp quá phức tạp và bạn có thể trải nghiệm để có nhiều lợi ích hơn từ một giải pháp đã được chứng minh trong thế giới thực. không hoàn toàn làm theo mẫu GOF
themarcuz

7
@ivowiblo Mô hình trong MVC là bất kỳ mô hình dữ liệu nào mà bộ điều khiển của bạn chuẩn bị và chuyển đến Chế độ xem. Đây là lý do tại sao 'mô hình ứng dụng' của bạn (mô hình miền, lớp mô hình, bất cứ thứ gì-bạn-nhãn-nó) có thể hoàn toàn không biết về các thư viện MVC, thậm chí tồn tại bên ngoài giải pháp của bạn trên một hệ thống phân tán riêng biệt. Trong MVC, một yêu cầu chỉ được chuyển đến bộ điều khiển. Bộ điều khiển lắp ráp một mô hình khung nhìn (dữ liệu cho lớp trình bày). Nếu mô hình đó là cùng một đối tượng khởi tạo mà bạn đã sử dụng trong cơ chế bền bỉ của mình, có thể thực hành kém, nhưng nó được phép, nghĩa là không có định nghĩa độc quyền.
one.beat.consumer

2
+1 cho Lưu ý "Mô hình" trong MVC chính xác nhất có nghĩa là mô hình mà Bộ điều khiển biết và do đó là mô hình dành cho Chế độ xem.
Luiz Damim

16

Bạn cần biết thêm một số về MVC trước khi chúng ta tiếp tục và thảo luận về nơi đặt mọi thứ. Vâng, nếu bạn muốn làm theo mẫu. Nếu không, bạn có thể ngừng đọc ngay bây giờ.

Mô hình được xác định rất lỏng lẻo. Không có gì cho biết bộ điều khiển, khung nhìn hoặc mô hình sẽ trông như thế nào hoặc chúng nên được cấu trúc như thế nào. Mô hình chỉ đơn giản nói rằng bạn nên tách các phần và cách chúng tương tác với nhau. Vì vậy, chúng ta hãy xem xét thêm một chút về chúng là gì (diễn giải của tôi).

MVC

Mô hình Mô hình có thể là bất cứ thứ gì. Nó có thể là một dịch vụ web, kho lưu trữ của bạn, các lớp dịch vụ của bạn hoặc đơn giản là các mô hình miền của bạn. Mô hình là mọi thứ được sử dụng để lấy thông tin bạn cần. Hãy coi "Model" như một lớp thay vì chỉ một đối tượng duy nhất.

Bộ điều khiển Bộ điều khiển là một chất keo. Nó lấy thông tin từ Model và điều chỉnh nó vào khung nhìn và ngược lại.

Chế độ xem Chế độ xem chỉ nên hiển thị những gì người dùng nhìn thấy.

Lưu ý rằng bạn không nên nhầm lẫn Model với View Models. Microsoft thực sự nên đặt tên cho thư mục "Model" là "ViewModels" vì chúng là như vậy. Tôi sẽ không sử dụng thông tin từ "Model" trực tiếp trong các khung nhìn. Không làm như vậy có nghĩa là bạn phải thay đổi Mô hình nếu Chế độ xem bị thay đổi và ngược lại.

Câu trả lời

Mô hình không phải là một mô hình khung nhìn mà là một lớp. Mọi thứ trong mô hình được sử dụng để lấy thông tin cần thiết cho chế độ xem. Bộ điều khiển lấy thông tin đó và đưa nó vào một mô hình xem duy nhất.

Một hành động bộ điều khiển đơn lẻ có thể sử dụng một hoặc một số lệnh gọi tới "Model" để có thể thu thập thông tin cần thiết cho chế độ xem.

Điều đó có nghĩa là tùy chọn thứ hai của bạn là đúng nhất khi bạn muốn nhận được một ứng dụng dễ bảo trì và mở rộng.

Lưu ý rằng một lớp dịch vụ có thể không cần thiết. Bạn có thể gọi OR / M trực tiếp từ bộ điều khiển. Nhưng nếu bạn thấy mình trùng lặp mã hoặc nhận được bộ điều khiển béo, chỉ cần di chuyển logic sang lớp dịch vụ. Không có gì ngoại trừ bộ điều khiển sẽ bị ảnh hưởng bởi thay đổi đó vì bạn đang sử dụng các mô hình chế độ xem thích hợp.


3
Thay vào đó, tôi ước ASP.NET MVC được đặt tên là ASP.NET ModelView View Controller. Nó sẽ là một tên khủng khiếp nhưng ít nhất nó sẽ truyền đạt ý nghĩa thực sự của nó :)
Hector Correa

Tôi đã mất một lúc ngay cả sau khi sử dụng ASP.NET MVC để nhận ra rằng mô hình đó không có nghĩa là mô hình lượt xem.
Lester

@ one.beat.consumer: Quan điểm của tôi về Mô hình là nó có thể là bất cứ thứ gì. Nó chỉ là một lớp ngoài đó. Tạo nó khi nó phù hợp với ứng dụng. Tôi đặt nó như vậy vì rất nhiều người nghĩ rằng Model trong ASP.NET MVC là View Model hoặc VM và Model là giống nhau.
jgauffin

Tôi nghĩ rằng tôi giải quyết câu hỏi. Cách hiểu của tôi về những customerModelgì anh ấy nói trong câu hỏi là một mô hình khung nhìn. Nếu anh ấy hiểu rằng không phải vậy thì câu trả lời rõ ràng hơn.
jgauffin

2
@jgauffin ngữ nghĩa rất quan trọng ở đây - trong MVC "mô hình" không ngụ ý "lớp mô hình"; nó chỉ ngụ ý một đối tượng mô hình phù hợp để Bộ điều khiển chuyển tới Chế độ xem . Trong các ứng dụng lớn, kiến ​​trúc MVC thường thậm chí không biết về mô hình / lớp dữ liệu hoặc bất cứ thứ gì bạn chọn để gọi nó. Câu trả lời đã chỉnh sửa của tôi cố gắng giải thích sự nhầm lẫn này ... chủ yếu là khi các ứng dụng nhỏ, thường không cần thêm sự tách biệt giữa Mô hình và Mô hình xem, vì vậy mọi người có xu hướng đánh dấu mô hình của họ và để bộ điều khiển sử dụng kho lưu trữ, v.v. Trong ứng dụng kích thước đầy đủ, điều này hiếm khi xảy ra.
one.beat.consumer

0

Tùy chọn 1: Bạn có thể nghĩ rằng mô hình == dịch vụ. Mô hình cũng là lớp nghiệp vụ.

Tùy chọn 2 là mô hình chống mô hình miền Anemic. http://en.wikipedia.org/wiki/Anemic_domain_model


Hãy nhớ rằng việc gọi một cái gì đó là một khuôn mẫu chống đối cần thêm một số ngữ cảnh! Rất nhiều ứng dụng không cần mô hình miền, bởi vì những thứ chúng làm hầu hết là hoạt động CRUD.
Rookian

Mô hình miền chỉ là một dữ liệu có "siêu dữ liệu", nếu bạn không có siêu dữ liệu, thì tốt thôi. Tôi đã loại bỏ từ "chống khuôn mẫu" bởi vì bạn đã đúng về phần đó. Tôi thực sự thích câu trả lời được chấp nhận và thay vào đó tôi nên nhận xét.
Imre L

0

Tùy chọn 2 là những gì được mô tả là kiến ​​trúc Bộ điều khiển Xấu xí béo ( Tham khảo tác giả của biểu thức này ). Giải pháp này nói chung là chống lại tinh thần MVC vì nó phá vỡ mối quan tâm.


1
public ActionResult FetchApple() { return View(_groceryService.GetApple("Granny Smith")); }là khá gầy nếu bạn hỏi tôi.
one.beat.consumer

4
Việc tôi đọc bài báo FSUC đó không phù hợp với Lựa chọn 2 ở trên. Ví dụ mà tác giả FSUC cung cấp không cho thấy việc sử dụng lớp dịch vụ nơi tất cả logic sắp xếp đó được đóng gói. Thay vào đó, nó cho thấy rằng bộ điều khiển đã được tải xuống với logic nghiệp vụ. Và khả năng tái sử dụng của logic nghiệp vụ, do nằm trong bộ điều khiển, giờ đã mất.
Marvo
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.