“Lớp logic nghiệp vụ” phù hợp với ứng dụng MVC ở đâu?


86

Đầu tiên, trước khi có ai đó la hét dupe, tôi đã gặp khó khăn khi tóm tắt nó trong một tiêu đề đơn giản. Một tiêu đề khác có thể là "Sự khác biệt giữa mô hình miền và mô hình MVC là gì?" hoặc "Mô hình là gì?"

Về mặt khái niệm, tôi hiểu Mô hình là dữ liệu được sử dụng bởi các khung nhìn và bộ điều khiển. Ngoài ra, dường như có rất nhiều ý kiến ​​khác nhau về những gì tạo nên mô hình. Mô hình miền là gì so với mô hình ứng dụng, so với mô hình chế độ xem, so với mô hình dịch vụ, v.v.

Ví dụ, trong một câu hỏi gần đây tôi đã hỏi về mô hình kho lưu trữ, tôi đã được trả lời trống rằng kho lưu trữ là một phần của mô hình. Tuy nhiên, tôi đã đọc các ý kiến ​​khác rằng mô hình nên được tách biệt khỏi mô hình bền vững và lớp logic nghiệp vụ. Rốt cuộc, không phải mẫu Kho lưu trữ được cho là tách phương pháp duy trì cụ thể khỏi mô hình sao? Những người khác nói rằng có sự khác biệt giữa mô hình Miền và mô hình MVC.

Hãy lấy một ví dụ đơn giản. AccountController được bao gồm trong dự án mặc định MVC. Tôi đã đọc một số ý kiến ​​cho rằng Mã tài khoản được bao gồm có thiết kế kém, vi phạm SRP, v.v ... vv .. Nếu một người thiết kế mô hình Thành viên "phù hợp" cho ứng dụng MVC, đó sẽ là gì?

Bạn sẽ tách các dịch vụ ASP.NET (nhà cung cấp thành viên, nhà cung cấp vai trò, v.v.) ra khỏi mô hình như thế nào? Hay bạn sẽ không?

Theo cách tôi thấy, mô hình nên "thuần túy", có lẽ với logic xác thực .. nhưng nên tách biệt khỏi các quy tắc nghiệp vụ (ngoài xác thực). Ví dụ: giả sử bạn có một quy tắc kinh doanh nói rằng ai đó phải được gửi email khi tạo tài khoản mới. Theo quan điểm của tôi, điều đó không thực sự thuộc về mô hình. Vậy nó thuộc về đâu?

Có ai muốn làm sáng tỏ vấn đề này không?


1
Đó là lý do tại sao bạn nên hỏi bốn câu hỏi riêng biệt.
John Farrell,

3
Từ khóa là "gần như". Đó thực sự là một câu hỏi tương tự, có lẽ các câu hỏi phụ được sử dụng để minh họa câu hỏi chính.
Erik Funkenbusch

3
Bộ điều khiển xem mô hình. Có phải reposirory / BL View không? Không. Nó có phải là Bộ điều khiển không? Không. Còn lại gì :)? Đó là MVC, không phải MSVC, không phải MRVC, không phải MBLVC. Chỉ có ba lớp. Vì vậy kho lưu trữ là một phần của mô hình, BL là một phần của mô hình. Và bạn có thể thực hiện phân tách bổ sung, nhưng nó được thực hiện bên trong lớp mô hình.
LukLed

3
@LukeLed, @bslm - Không hẳn. MVC không nói rằng không thể có các lớp khác mà bộ điều khiển hoặc mô hình tương tác với.
John Farrell,

3
@LukLed - Không đồng ý - MVC chỉ là một mẫu lớp trình bày. Nó không ảnh hưởng đến cách bạn cấu trúc các lớp khác như BLL và DAL.
Nhà Cory

Câu trả lời:


69

Cách tôi đã làm - và tôi không nói là đúng hay sai, là có Chế độ xem của tôi và sau đó là một mô hình áp dụng cho chế độ xem của tôi. Mô hình này chỉ có những gì liên quan đến chế độ xem của tôi - bao gồm chú thích dữ liệu và quy tắc xác thực. Bộ điều khiển chỉ chứa logic để xây dựng mô hình. Tôi có một lớp dịch vụ chứa tất cả logic nghiệp vụ. Bộ điều khiển của tôi gọi lớp dịch vụ của tôi. Ngoài ra là lớp kho lưu trữ của tôi.

Các đối tượng miền của tôi được lưu trữ riêng biệt (thực tế là trong dự án của riêng chúng). Họ có chú thích dữ liệu và quy tắc xác thực riêng. Kho lưu trữ của tôi xác thực các đối tượng trong miền của tôi trước khi lưu chúng vào cơ sở dữ liệu. Bởi vì mọi đối tượng trong miền của tôi kế thừa từ một lớp cơ sở có xác thực được tích hợp sẵn, kho lưu trữ của tôi là chung và xác thực mọi thứ (và yêu cầu nó kế thừa từ lớp cơ sở).

Bạn có thể nghĩ rằng có hai bộ mô hình là trùng lặp mã, và nó ở một mức độ nào đó. Tuy nhiên, có những trường hợp hoàn toàn hợp lý trong đó đối tượng miền không thích hợp cho chế độ xem.

Trường hợp điển hình là khi làm việc với thẻ tín dụng - tôi phải yêu cầu cvv khi xử lý thanh toán, nhưng tôi không thể lưu trữ cvv (nếu làm như vậy sẽ bị phạt 50.000 đô la). Tuy nhiên, tôi cũng muốn bạn có thể chỉnh sửa thẻ tín dụng của mình - thay đổi địa chỉ, tên hoặc ngày hết hạn. Nhưng bạn sẽ không cung cấp cho tôi số hoặc cvv khi chỉnh sửa nó, và tôi chắc chắn sẽ không đưa số thẻ tín dụng của bạn ở dạng văn bản thuần túy trên trang. Miền của tôi có những giá trị này bắt buộc để lưu thẻ tín dụng mới vì bạn đưa chúng cho tôi, nhưng mô hình chỉnh sửa của tôi thậm chí không bao gồm số thẻ hoặc cvv.

Một lợi ích khác đối với rất nhiều lớp là nếu được cấu trúc đúng cách, bạn có thể sử dụng sơ đồ cấu trúc hoặc một vùng chứa IoC khác và hoán đổi các phần mà không ảnh hưởng bất lợi đến ứng dụng của bạn.

Theo ý kiến ​​của tôi, mã bộ điều khiển chỉ nên là mã được nhắm mục tiêu ở chế độ xem. Hiển thị cái này, ẩn cái kia, v.v. Lớp dịch vụ phải chứa logic nghiệp vụ cho ứng dụng của bạn. Tôi thích có tất cả ở một nơi để dễ dàng thay đổi hoặc điều chỉnh quy tắc kinh doanh. Lớp kho lưu trữ phải tương đối ngu ngốc - không có logic nghiệp vụ và chỉ truy vấn dữ liệu của bạn và trả về các đối tượng miền của bạn. Bằng cách tách các mô hình chế độ xem khỏi mô hình miền, bạn có thể linh hoạt hơn nhiều khi nói đến các quy tắc xác thực tùy chỉnh. Điều đó cũng có nghĩa là bạn không phải đưa mọi phần dữ liệu vào chế độ xem của mình trong các trường ẩn và đẩy nó qua lại giữa máy khách và máy chủ (hoặc xây dựng lại nó trên phần phụ trợ).

<% if (!String.IsNullOrEmpty(Model.SomeObject.SomeProperty) && 
    Model.SomeObject.SomeInt == 3 && ...) { %>

Mặc dù mọi thứ dường như trải rộng và quá nhiều lớp, nhưng nó có mục đích được kiến ​​trúc theo cách này. Nó có hoàn hảo không? không hẳn vậy. Nhưng tôi thích nó hơn một số thiết kế trước đây về việc gọi các kho lưu trữ từ bộ điều khiển và có logic nghiệp vụ được trộn lẫn trong bộ điều khiển, kho lưu trữ và mô hình.


Chỉ là một bản sao của những gì tôi có trong ứng dụng MVC doanh nghiệp của chúng tôi. Một kiến ​​trúc N-Tier. Ứng dụng MVC chỉ tương tác với các đối tượng và dịch vụ kinh doanh trong các khu vực N-Tier.
Ed DeGagne.

Chủ yếu là giống nhau ở đây. Các dự án riêng biệt cho định nghĩa, mô hình, mô hình xem, DAL, v.v. Sự khác biệt duy nhất là DAL của tôi bao gồm logic để làm phẳng dữ liệu cho web nhằm tối ưu hóa việc phân phối dữ liệu phức tạp cho các báo cáo hoặc chế độ xem khách hàng tùy chỉnh. Bây giờ tôi đã tránh xa việc giữ mọi thứ trong bộ nhớ cache của ứng dụng cho các bảng tra cứu, v.v., với các trang trại Web và đám mây Azure đang chơi.
Robert Achmann

1
@Josh, sẽ rất hữu ích nếu bạn có thể hiển thị ảnh chụp màn hình về dự án mẫu của mình?
shaijut

@Josh thì sao nếu dự án của bạn không có cơ sở dữ liệu. Nó tương tác với các tham chiếu dịch vụ. Tất cả các lớp miền và phương thức đến từ các tham chiếu này. Kịch bản này có phù hợp với cấu trúc phân lớp không?
user6395764 14/04

17

Tôi cũng thường tự hỏi làm thế nào các phần tử MVC phù hợp chính xác trong cấu trúc ứng dụng web truyền thống, nơi bạn có các chế độ xem (trang), bộ điều khiển, dịch vụ và đối tượng dữ liệu (mô hình). Như bạn đã nói, có rất nhiều phiên bản của điều đó.

Tôi tin rằng sự nhầm lẫn tồn tại là do kiến ​​trúc được chấp nhận rộng rãi ở trên, sử dụng mô hình "miền thiếu máu" (được cho là) ​​-anti. Tôi sẽ không đi sâu vào chi tiết về "tính chống khuôn mẫu" của mô hình dữ liệu thiếu máu (bạn có thể xem nỗ lực của tôi để giải thích mọi thứ ở đây (dựa trên Java, nhưng có liên quan cho bất kỳ ngôn ngữ nào)). Nhưng tóm lại, nó có nghĩa là mô hình của chúng tôi chỉ chứa dữ liệu và logic nghiệp vụ được đặt trong các dịch vụ / trình quản lý.

Nhưng giả sử chúng ta có kiến trúc hướng miền và các đối tượng miền của chúng ta giống như mong đợi - có cả trạng thái và logic nghiệp vụ. Và trong quan điểm định hướng miền này, mọi thứ sẽ xảy ra:

  • chế độ xem là giao diện người dùng
  • bộ điều khiển thu thập các đầu vào của giao diện người dùng, gọi các phương thức trên mô hình và gửi lại phản hồi cho giao diện người dùng
  • mô hình là các thành phần kinh doanh của chúng tôi - nắm giữ dữ liệu, nhưng cũng có logic kinh doanh.

Tôi đoán rằng câu trả lời cho các câu hỏi chính của bạn. Mọi thứ trở nên phức tạp khi chúng ta thêm một số lớp nữa, như lớp kho lưu trữ. Người ta thường gợi ý rằng nó nên được gọi bởi logic nghiệp vụ được đặt trong mô hình (và do đó mỗi đối tượng miền có một tham chiếu đến một kho lưu trữ). Trong bài viết của tôi mà tôi đã liên kết, tôi lập luận rằng đây không phải là cách thực hành tốt nhất. Và trên thực tế, nó không phải là một điều xấu khi có một lớp dịch vụ. Nhân tiện, thiết kế hướng miền không loại trừ lớp dịch vụ, nhưng nó được cho là 'mỏng' và chỉ phối hợp các đối tượng miền (vì vậy không có logic nghiệp vụ nào ở đó).

Đối với mô hình mô hình dữ liệu thiếu máu, được áp dụng rộng rãi (dù tốt hay xấu), mô hình này sẽ là cả lớp dịch vụ và các đối tượng dữ liệu của bạn.


Điểm xuất sắc! Một nhận xét: có cùng một mớ hỗn độn với Dịch vụ. Ít nhất các dịch vụ có thể là dịch vụ Ứng dụng và dịch vụ Miền. Dịch vụ ứng dụng chỉ là một lớp bao bọc mỏng, thu thập thông tin từ Kho lưu trữ, v.v. Dịch vụ miền cung cấp logic nghiệp vụ, sử dụng kết hợp các mô hình miền hoặc chỉ những thứ không phải lúc nào cũng phù hợp trong mô hình miền.
Artru 13/1213

điều gì xảy ra nếu dự án của bạn không có cơ sở dữ liệu. Nó tương tác với các tham chiếu dịch vụ. Tất cả các lớp miền và phương thức đến từ các tham chiếu này. Kịch bản này có phù hợp với cấu trúc phân lớp không?
user6395764 14/04

3

Theo ý kiến ​​của tôi,

Mô hình -

Không nên chứa logic nghiệp vụ, nó phải có thể cắm được (như kịch bản WCF). Nó được sử dụng để liên kết với chế độ xem như vậy, nó phải có các thuộc tính.

Logic kinh doanh -

Nó nên được đặt ở "Lớp dịch vụ miền", nó là lớp riêng biệt hoàn toàn. Ngoài ra, sẽ thêm một lớp nữa ở đây "Dịch vụ ứng dụng".

Dịch vụ ứng dụng trao đổi với lớp Dịch vụ miền để áp dụng logic nghiệp vụ và cuối cùng trả lại Mô hình.

Vì vậy, Bộ điều khiển sẽ yêu cầu Dịch vụ ứng dụng cho Mô hình và quy trình sẽ diễn ra như thế nào,

    Controller->Application Services(using domain services)->Model

2

Mô hình MVC và khung công tác Asp.net không phân biệt Mô hình nên là gì.

Các ví dụ riêng của MS bao gồm các lớp bền bỉ trong mô hình. Câu hỏi của bạn về tư cách thành viên trong mô hình. Điều này phụ thuộc. Các lớp trong mô hình của bạn có thuộc sở hữu của thứ gì đó không? Có mối liên hệ nào giữa người đăng nhập và dữ liệu nào được hiển thị không? Có phần lọc dữ liệu của hệ thống quyền có thể chỉnh sửa được không? Có phải ai đã cập nhật hoặc chỉnh sửa lần cuối cùng một đối tượng là một phần trong miền của bạn như một người khác cần xem nó hoặc một cái gì đó để được hỗ trợ phụ trợ không?

Ví dụ về email cũng tùy thuộc vào nó. Bạn có quen thuộc với sự kiện miền hoặc sự kiện cụ thể không? Bạn có một dịch vụ riêng để gửi email không? Hành động gửi email có phải là một phần của miền của bạn hay đó là mối quan tâm ở cấp ứng dụng nằm ngoài phạm vi hệ thống của bạn? Giao diện người dùng có cần biết email đã được gửi thành công hay chưa? Những email không gửi được có cần thử lại không? Nội dung email được gửi có cần được lưu trữ để hỗ trợ hoặc yêu cầu dịch vụ khách hàng không?

Những loại câu hỏi này quá rộng và chủ quan nhưng tôi đang trả lời để bạn và tất cả những người đã bình chọn bạn có thể hiểu điều này.

Tất cả các yêu cầu / thời gian / tài nguyên của bạn đều được đưa vào kiến ​​trúc hệ thống của bạn. Ngay cả mô hình doanh thu cũng có thể có ảnh hưởng. Bạn cũng phải xem xét mẫu bạn đang chụp. DDD khác nhiều so với các ứng dụng mô hình liên tục và tất cả các lỗi ở giữa cũng hợp lệ cho một số ứng dụng nhất định. Bạn có đang chụp để thử nghiệm ứng dụng không? Tất cả những điều này đều có ảnh hưởng.

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.