MVC: Đặt logic nghiệp vụ ở đâu? [đóng cửa]


81

Trước hết, tôi đã thấy nhiều câu hỏi về điều này, nhưng không đủ lý do đằng sau đó. Nếu câu hỏi của tôi không đủ tốt và cần được loại bỏ, tôi sẽ hiểu.

Ví dụ, tôi đã xem qua câu trả lời này và hơn 45 câu trả lời được bình chọn cho biết anh ấy khuyên bạn nên đưa logic kinh doanh vào mô hình, điều này nghe khá hợp lý.

Tuy nhiên, dự án lớn đầu tiên của tôi mà tôi đã thực hiện với tất cả BL của mình hoàn toàn trong bộ điều khiển, bởi vì tôi không thắc mắc về những điều này và xem nó được thực hiện như thế nào trong AccountControllerđó được thêm tự động nếu bạn chọn MVC với xác thực biểu mẫu. Tất cả các phương pháp trông khá nhồi bông với BL. Hoặc có thể đó là số lượng mã ít nhất có thể được thêm vào và tôi đang bỏ qua mọi thứ?

Một người trên youtube đã hỏi tôi rằng liệu anh ta có đúng không khi đưa tất cả logic vào các mô hình của mình và lúc đầu tôi đã không! Sau đó tôi bắt đầu nghĩ rằng có lẽ anh ấy đã đúng !?

Vậy rốt cuộc, tôi phải đặt logic kinh doanh của mình ở đâu? Nếu nó nằm trong các lớp mô hình, thì bao nhiêu mã nên được coi là một lượng lành mạnh trong một phương thức nằm trong bộ điều khiển? Một dòng để gọi một số phương thức từ mô hình trong bộ điều khiển nhiều nhất và sau đó quay trở lại dạng xem?


1
Logic kinh doanh đi trong bộ điều khiển. Logic của mô hình đi trong Mô hình. Logic của mô hình là những thứ xử lý cụ thể / chỉ mô hình. Setters / getters / property / adders / Removers, v.v.
nghiền nát

1
@crush: Tôi không đồng ý. Như tôi đã đọc - ". Một đối tượng mô hình tổ chức dữ liệu và các ứng dụng 'logic kinh doanh' và 'điều khiển các đối tượng quan hệ mô hình và xem các đối tượng với nhau'.
ChiefTwoPencils

@BobbyDigital - bạn có thể cung cấp liên kết đến nguồn không? :)
Andrius Naruševičius

Chắc chắn, nó nằm trong phần giải thích về cách sử dụng MVC thích hợp trong Hướng dẫn Nông trại Big Nerd nhưng tiếc là bạn sẽ phải mua sách để xác nhận điều này.
ChiefTwoPencils,

Tuy nhiên, tôi sẽ nói rằng, tôi vừa cố gắng xác nhận điều này trong một cuốn sách C #, trong asp.net logic nghiệp vụ đi ở tầng giữa nơi tầng trên cùng sẽ là giao diện người dùng, giữa sẽ là bộ điều khiển và dưới cùng sẽ là db. Nhưng họ không nói cụ thể / rõ ràng về MVC. Điều này xuất phát từ C # cho lập trình viên :)
ChiefTwoPencils

Câu trả lời:


54

Tôi thích đặt logic miền trong mô hình vì một vài lý do.

  1. Mô hình không nên có mã giao diện người dùng trong đó và do đó dễ kiểm tra hơn. Bất cứ khi nào có thể, tôi muốn có một mô hình hoạt động đầy đủ (có nghĩa là hoàn toàn thử nghiệm) trước khi viết bất kỳ mã giao diện người dùng nào. Người điều khiển có thể tin tưởng rằng mô hình đang làm đúng và chỉ cần giải quyết các mối quan tâm về giao diện người dùng.

  2. Nếu bạn đặt logic miền trong bộ điều khiển, thì việc chia sẻ giữa các ứng dụng khác nhau hoặc thậm chí giữa các bộ điều khiển khác nhau sẽ không dễ dàng như vậy.


2
Có, tôi thực sự thích #2vì bản thân tôi thấy khó chia sẻ giữa các bộ điều khiển (phải sử dụng các phương thức như tĩnh)!
Andrius Naruševičius

Vâng @ AndriusNaruševičius, đừng làm vậy. Bạn nên thử và đưa các phụ thuộc của mình vào bộ điều khiển và không dựa vào các bộ điều khiển khác.
Mark Walsh

Lưu ý rằng tôi nghĩ câu trả lời này nói về "mô hình miền" (M một phần của patten MVC cổ điển) là một số thứ không liên quan đến "mô hình" ASP.Net MVC (một phần của mô hình MVVM).
Alexei Levenkov

1
Vậy ... bạn đặt logic dựa vào nhiều mô hình ở đâu?
Kolob Canyon

1
@Ferrucio Đó là một giải pháp tồi. Bạn kết thúc trong một "địa ngục phụ thuộc" nơi bạn tạo các đối tượng dựa vào các đối tượng khác để được tạo. Đó là một giải pháp tồi vì dữ liệu không cần thiết / không sử dụng được chuyển đi không có lý do. Bạn muốn các hàm chỉ lấy những gì chúng cần để hoàn thành công việc - nếu không thì mã trở nên không rõ ràng rất nhanh chóng. Giải pháp tốt hơn là tạo các lớp logic nghiệp vụ có mức tối thiểu để xây dựng (hoặc thậm chí tốt hơn, sử dụng phương pháp tiêm phụ thuộc để xây dựng). Bằng cách đó, bạn sẽ không bao giờ phải lấy một số đối tượng không liên quan để thực hiện logic nghiệp vụ.
Kolob Canyon

43

Tôi muốn giữ cho các mô hình của mình sạch sẽ, tức là Chỉ với các thuộc tính và không có logic kinh doanh. Tôi luôn nghĩ rằng việc đưa các phụ thuộc vào bộ điều khiển là điều tốt và những phụ thuộc này chứa logic mà tôi thực hiện trên các mô hình của mình. Tôi thích tuân thủ nguyên tắc trách nhiệm duy nhất nếu có thể và tôi nhận thấy rằng các mô hình với hàng tấn phương pháp sẽ bị phình ra rất nhanh. Có ưu và nhược điểm cho cả hai, việc đưa vào nhiều phụ thuộc có chi phí cao nhưng cho phép kiểm tra riêng biệt và giữ cho các lớp đơn giản và cuối cùng bạn sẽ có bộ điều khiển gọn gàng hơn. Mặc dù logic của tôi không thực sự tồn tại trên mô hình của tôi với tư cách là các thành viên của lớp, logic kinh doanh của nó vẫn là logic. Tôi có xu hướng không xác định logic nghiệp vụ trong bộ điều khiển vì chế nhạo những thứ như Httpcontext là một cơn ác mộng và không cần thiết.


5
+1 hoàn toàn đồng ý. Tôi nghĩ tôi là người duy nhất thích giữ trách nhiệm của người mẫu ở mức tối thiểu!
Lee

1
Chắc chắn, anh ấy là một ý chính để nhập điều khiển của tôi gist.github.com/markwalsh-liverpool/8fb361a9df0dcf034caf
Đánh dấu Walsh

1
Vì vậy, nếu bạn không đặt logic của mình trong các mô hình hoặc bộ điều khiển của mình - bạn sẽ đặt nó ở đâu?
niico

1
Làm cách nào để bạn truyền các đối số cho hàm tạo của bộ điều khiển? Không phải quá trình khởi tạo của bộ điều khiển thường được thực hiện ở hậu trường?
Jeff

1
Tôi sử dụng tiêm phụ thuộc.
Mark Walsh

23

Các doanh nghiệp lý thuộc về lĩnh vực vấn đề và tất cả những gì thuộc về miền vấn đề đi vào mô hình trong MVC.

Bộ điều khiển phải chịu trách nhiệm chuyển dữ liệu từ mô hình đến khung nhìn và từ khung nhìn trở lại mô hình. Do đó, bộ điều khiển là cầu nối giữa những gì người dùng tương tác và cách chương trình lập mô hình và lưu trữ trạng thái của vấn đề. Có thể nói hệ thống ống nước .

Chìa khóa ở đây là sự phân biệt giữa logic nghiệp vụ và logic đường ống dẫn nước. Theo ý kiến ​​của tôi, những gì Bộ điều khiển tài khoản được tạo tự động thực hiện chủ yếu là hệ thống ống nước, không thực sự là logic kinh doanh. Hãy nhớ rằng logic của hệ thống ống nước không nhất thiết phải ngắn, vì vậy bạn không cần phải áp đặt các giới hạn giả tạo (như "số cuộc gọi tối đa là X trong bộ điều khiển").


Tôi đồng ý với tất cả điều này. Tuy nhiên, tôi nghĩ có nhiều sự nhầm lẫn đến từ cách cấu trúc các lớp trong mô hình, đặc biệt là với EF. IE: bạn có sử dụng các lớp từng phần và xây dựng logic trong các tệp C # khác nhau không? một tệp cho EF và một tệp cho logic?
S1r-Lanzelot

13

Nhóm của tôi khi chuyển sang mvc từ webforms (asp.net) đã thực hiện rất nhiều nghiên cứu và đưa ra cấu trúc sau. Theo tôi nó không phải là ứng dụng lớn hay nhỏ. Đó là về việc giữ cho mã sạch và rõ ràng.

DALProject

AccountsDAL.cs --- > Calls SP or any ORM if ur using any

BLLProject

AccountsBLL.cs ---> Calls DAL

WebProject

Model
    AccountsModel --- > Contains properties And call BLL
Controllers
    IndexController ---> Calls Models and returns View
Views
    Index

Bộ điều khiển phải chịu trách nhiệm về việc truyền dữ liệu giữa mô hình và chế độ xem. Ngoài ra, nó không nên có bất kỳ mã không cần thiết nào. Ví dụ: nếu bạn đang ghi nhật ký, nó nên được thực hiện ở cấp mô hình hơn là bộ điều khiển.


13

Dường như có một số nhầm lẫn xung quanh chủ đề này. Hầu hết có vẻ như mọi người có xu hướng nhầm lẫn mô hình MVC với kiến ​​trúc N-tier như một tình huống hoặc /. Thực tế là hai cách tiếp cận có thể được sử dụng cùng nhau, nhưng một phương pháp không phụ thuộc vào phương pháp kia và không bắt buộc.

Kiến trúc N-tier liên quan đến việc tách một ứng dụng thành nhiều tầng. Một ví dụ đơn giản là nơi ứng dụng được chia thành lớp trình bày, lớp logic nghiệp vụ và lớp truy cập dữ liệu.

MVC là một mẫu thiết kế xử lý lớp trình bày của một ứng dụng. Hoàn toàn có thể thiết kế một ứng dụng theo cách tiếp cận MVC mà không tách logic nghiệp vụ và logic truy cập dữ liệu khỏi lớp trình bày và do đó kết thúc với một thiết kế cấp duy nhất.

Kết quả là, nếu bạn đang theo cách tiếp cận MVC mà không tách ứng dụng thành các cấp thì bạn sẽ kết thúc với Mô hình, Chế độ xem và Bộ điều khiển có các bit quy tắc nghiệp vụ và logic truy cập dữ liệu trộn lẫn với phần logic còn lại.

Theo định nghĩa, trong kiến ​​trúc N-tier, tầng trình bày chỉ được cho là có thể giao tiếp với lớp logic nghiệp vụ, vì vậy nó phải giữ rằng bất kỳ thành phần MVC nào chỉ có thể giao tiếp với lớp logic nghiệp vụ.

Nếu bạn đang xây dựng một ứng dụng không liên quan đến bản trình bày và do đó không phải là một lớp trình bày, bạn không cần phải quan tâm đến mẫu MVC. Tuy nhiên, bạn vẫn có thể chia ứng dụng của mình thành nhiều tầng và do đó tuân theo thiết kế N-tier mặc dù không có lớp trình bày nào liên quan.


8

Nói chung, logic nghiệp vụ không nên nằm trong bất kỳ trình phát MVC nào; nó chỉ nên được sử dụng bởi các hành động của bộ điều khiển của bạn.

Như nhiều người đã đề cập, tốt nhất bạn nên tạo một thư viện để lưu trữ logic nghiệp vụ dưới dạng một tập hợp các thành phần không thể sử dụng được của ứng dụng khách.

Khi thực hiện theo cách này, chúng tôi sẽ tăng đáng kể khả năng tái sử dụng, khả năng tương thích, khả năng mở rộng và khả năng kiểm tra với phần mềm của mình. Chúng tôi cũng giảm bớt sự phụ thuộc vào một số tính năng khung nhất định, giúp dễ dàng chuyển sang các công nghệ mới hơn / khác.

Tóm tắt logic kinh doanh của chúng tôi thành một tổ hợp độc lập (hoặc các tổ hợp) đã phục vụ chúng tôi rất tốt trong những năm qua. Logic kinh doanh của chúng tôi sau đó có thể được sử dụng bởi hầu như bất kỳ công nghệ .NET nào (ASP.NET MVC / API / Core, WPF, Win Forms, WCF, UWP, WF, Console, v.v.).

Ngoài ra, chúng tôi muốn tầng giữa của chúng tôi xử lý quy tắc nghiệp vụ và logic xác thực để giảm sự phụ thuộc của chúng tôi vào .NET MVC Framework's. Ví dụ: chúng tôi tránh sử dụng trình trợ giúp xác thực .NET MVCs và thay vào đó dựa vào trình trợ giúp của chính chúng tôi. Đây là một yếu tố khác cho phép chúng tôi dễ dàng sử dụng logic kinh doanh của mình từ bất kỳ công nghệ .NET nào.

Thiết kế tầng giữa của chúng tôi một cách hợp lý theo cách này đã cho phép chúng tôi dễ dàng đạt được kiến ​​trúc vật lý này:

nhập mô tả hình ảnh ở đây

Nó được viết bằng Peasy.NET và đã phục vụ chúng tôi rất tốt trong những năm qua. Trên thực tế, chúng tôi quyết định mở mã nguồn của nó.

Nếu ai đó tò mò về tầng giữa của chúng tôi trông như thế nào, thì đây là một ví dụ về tầng doanh nghiệp, khách hàng không thể biết được. Nó cũng cho thấy việc sử dụng nó bởi nhiều máy khách .NET (ASP.NET MVC, Web Api và WPF).

Hy vọng điều này sẽ giúp ai đó!


Chủ yếu là không cần sử dụng lại logic. Nếu tôi giả sử quyết định sử dụng ASP.NET Core MVC cho Web API, tôi sẽ không bao giờ muốn sử dụng logic nghiệp vụ đó trong WPF hoặc WinForms. Vì dù sao máy khách cũng sẽ giao tiếp với máy chủ. Đặt logic nghiệp vụ và đặc biệt là logic truy cập cơ sở dữ liệu ở phía máy khách là không tốt.
Konrad

Bạn càng thêm nhiều tầng, tôi sẽ nói rằng nó làm giảm khả năng bảo trì và khả năng kiểm tra. Cuối cùng, các bài kiểm tra tích hợp quan trọng hơn.
Konrad

8

Logic nghiệp vụ không nên đi trong Chế độ xem mô hình hoặc Bộ điều khiển của bạn. Cần có một Lớp Logic Kinh doanh riêng biệt ; mục đích duy nhất của lớp này là xử lý logic nghiệp vụ của bạn. Điều này phù hợp hơn với SOLID .

Nếu bạn đặt logic nghiệp vụ của mình trong MV hoặc C, bạn sẽ gặp phải đoạn mã khó kiểm tra / tái sử dụng.

Còn việc đưa logic vào Mô hình thì sao?

Đó là một giải pháp tồi.

Bạn sẽ kết thúc trong Địa ngục phụ thuộc nơi các đối tượng dựa vào các đối tượng. nhập mô tả hình ảnh ở đây

Ngay cả khi bạn có một hàm đơn giản đã chết, bạn vẫn phải đáp ứng tất cả các phụ thuộc để gọi nó.

Nó cũng sẽ khiến dữ liệu không cần thiếtkhông sử dụng được chuyển đi không có lý do. Điều này cũng có thể ảnh hưởng đến hiệu suất tùy thuộc vào mức độ tồi tệ của nó.

Tôi cũng nên đề cập rằng kiểm thử đơn vị trở thành một vấn đề khó khăn trong ** vì bạn phải giả lập nhiều đối tượng chỉ để kiểm tra một chức năng đơn giản.

Các nguyên tắc áp dụng mã sạch

  1. Lớp / Chức năng chỉ lấy những gì họ cần để hoàn thành công việc.
  2. Các hàm phải có 3 tham số trở xuống nếu có thể
  3. Đặt tên các lớp / hàm / biến một cách thông minh (theo tiêu chuẩn của Microsoft)
  4. Không ghép nối logic nghiệp vụ với Chế độ xem mô hình hoặc Bộ điều khiển

Bộ điều khiển

Trong bộ điều khiển của bạn, bạn sẽ có thể sử dụng tính năng tiêm phụ thuộc để đưa vào lớp logic nghiệp vụ . Đảm bảo rằng bộ điều khiển của bạn chỉ được sử dụng để định tuyến thông tin đến lớp logic nghiệp vụ. Bộ điều khiển KHÔNG nên có logic nghiệp vụ trực tiếp trong đó. Bất kỳ xác nhận nào cần được xử lý IValidatabletrên Model. Mọi logic nghiệp vụ cần được chuyển đến một lớp riêng biệt.


Ở đây nơi tôi làm việc, chúng tôi có một tầng kinh doanh và tôi chỉ muốn rằng chúng tôi không có nó. Các lớp nghiệp vụ là một mớ hỗn độn thuần túy, logic được cho là nằm trong mô hình.
Mateus Felipe

@MateusFelipe Vì vậy, bạn đặt logic yêu cầu nhiều mô hình (ví dụ: Thanh toán và Sản phẩm) ở đâu? Bạn có tạo một mô hình mới có PaymentProductdưới dạng một biến thể hiện không? Bạn đặt tên cho đồ vật đó là gì? Nếu một mô hình không được sử dụng trong một khung nhìn, nó không còn là một mô hình nữa. Nó là một phần của một lớp riêng biệt. Tốt nhất, lớp bạn thực hiện chỉ nên lấy những gì nó cần từ Thanh toán và Sản phẩm để hoàn thành công việc. Nếu nó chỉ cần productNameprice, nó chỉ nên lấy hai tham số đó, không phải toàn bộ đối tượng.
Kolob Canyon

4

Câu trả lời chung mà tôi có là logic kinh doanh thường phù hợp với hai loại:

Logic nghiệp vụ hướng đối tượng: Được mô hình hóa dưới dạng các đối tượng (trong mô hình), thường được đưa vào dưới dạng kho lưu trữ.

Logic nghiệp vụ theo thủ tục: Đi vào một dịch vụ có giao diện có thể được đưa vào bộ điều khiển.

Logic điều khiển: Logic điều khiển cách các lệnh được nhận và chuyển đến các mô hình / dịch vụ, sau đó cách các kết quả đó được chuyển đến dạng xem.

Bộ điều khiển không được có logic nghiệp vụ , đó là một phần rất cụ thể của mẫu thiết kế để kiểm soát cách giao diện người dùng chuyển đầu vào cho các mô hình xử lý logic nghiệp vụ (hoặc dịch vụ nếu các vấn đề của bạn mang tính thủ tục nhiều hơn).


2

Tôi cũng muốn giữ cho các mô hình của mình sạch sẽ (tham khảo: @Mark Walsh). Vấn đề không thể sử dụng lại logic được nhúng trong bộ điều khiển có thể dễ dàng được khắc phục thông qua việc chèn phụ thuộc hoặc, nếu bạn nghĩ rằng sẽ có quá nhiều điều đó, hãy hiển thị logic kinh doanh / miền của bạn thông qua các giao diện và sử dụng mẫu mặt tiền trong bộ điều khiển. Bằng cách đó, bạn có được chức năng bạn cần, nhưng giữ cho cả bộ điều khiển và mô hình đều đẹp và sạch sẽ.


1

Tôi cũng muốn giữ cho các mô hình sạch sẽ. Bộ điều khiển MVC chỉ nên được sử dụng để thực hiện cuộc gọi và cũng phải được giữ sạch sẽ. Vì vậy, tùy thuộc vào khả năng tái sử dụng, độ nhạy và mức độ liên quan của nó, logic nghiệp vụ có thể được viết trong

1.WebApi Controller: Ưu điểm của việc sử dụng webapi controller là bạn có thể hiển thị chúng dưới dạng dịch vụ sau này cho các thiết bị khác làm cho mã của bạn có thể sử dụng lại.

2. BAL / Common commonent: Có một số logic có cách sử dụng cụ thể và không thể được hiển thị dưới dạng api, có thể được đẩy trong lớp này.

3. Kho lưu trữ: Tất cả các truy vấn liên quan đến cơ sở dữ liệu được thêm vào một kho lưu trữ. Có thể có một kho lưu trữ chung sẽ triển khai tất cả các chức năng (hoạt động CRUD) hoặc các kho lưu trữ cụ thể cho mỗi bảng. Tùy thuộc vào các hoạt động được thực hiện.


1

Như ahanusa đã viết, bạn nên đặt logic kinh doanh của mình vào DLL riêng biệt hoặc thư mục riêng biệt.
Tôi thường sử dụng một thư mục có tên Logics ở cùng cấp Mô hình và Bộ điều khiển, nơi tôi đặt các lớp làm logic kinh doanh.
Bằng cách này, tôi để cả hai mô hình và bộ điều khiển sạch sẽ.


0

Tôi biết rằng đó là một câu hỏi về MVC, nhưng tôi nghĩ ví dụ mà tôi đang đưa ra (API Web) sẽ hữu ích.

Tôi đang phát triển API Web đầu tiên của mình và tôi đang sử dụng lại logic nghiệp vụ từ các ứng dụng khác. Cụ thể, nó đến từ một DLL bên ngoài, vì vậy API của tôi được sử dụng chỉ để "nói chuyện" với giải pháp SAP, nhận yêu cầu từ PO và gửi lại phản hồi.

Làm cách nào tôi có thể đưa logic (đã được triển khai) vào bộ điều khiển của mình? Tôi không cần nó. Bộ điều khiển của tôi sẽ chỉ nhận, xác thực yêu cầu và soạn phản hồi để gửi dữ liệu trở lại.

Tôi đang làm việc với các lớp ViewModel và tất cả những gì chúng phải có là chức năng ánh xạ, chỉ để đọc thông tin từ TransferObjects (đến từ DLL bên ngoài) và dịch sang ViewModel.

Tôi không thoải mái với việc ứng dụng của mình (trong trường hợp này là API Web) nắm giữ logic nghiệp vụ, tôi nghĩ rằng khả năng tái sử dụng sẽ bị mất theo cách này.

Tôi đang coi logic kinh doanh của mình như một phần phụ thuộc mà tôi đưa vào bộ điều khiển.

Tôi đã thực hiện rất nhiều cấu trúc lại trong phần kế thừa để cung cấp giải pháp Unit Testable, tôi đã phải tạo rất nhiều giao diện và triển khai một số mẫu thiết kế vào phần kế thừa để cung cấp giải pháp này.

Theo quan điểm của tôi, lớp nghiệp vụ phải nằm ngoài ứng dụng, tốt nhất là trong một thư viện lớp khác. Vì vậy, bạn sẽ có một khái niệm tách biệt thực sự được thực hiện trong ứng dụng của bạn.

Tất nhiên, nếu CORE (doanh nghiệp) của bạnứng dụng của bạn (API / WebSite) , các quy tắc nghiệp vụ sẽ được triển khai vào các lớp MVC của bạn. Nhưng trong tương lai nếu bạn muốn phát triển một ứng dụng mới và một số quy tắc kinh doanh giống nhau, tôi cá là bạn sẽ gặp rất nhiều vấn đề chỉ để duy trì cùng một logic được triển khai trong cả hai ứng dụ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.