15

Trong một vài dự án MVC mà tôi đang nghiên cứu, rõ ràng là có một vài bộ điều khiển có vấn đề đã phát triển thành các lớp Thiên Chúa - mỗi vị thần trong miền của họ, nếu bạn muốn.Bộ điều khiển Thiên Chúa - Cách ngăn chặn chúng?

Câu hỏi này có thể là vấn đề 'đi đâu', nhưng tôi nghĩ đó là một câu hỏi quan trọng liên quan đến SRP (Nguyên tắc trách nhiệm đơn), DRY (Đừng lặp lại) và giữ mọi thứ ngắn gọn " nhanh nhẹn "- và tôi không đủ kinh nghiệm (với mô hình này và trong thiết kế chung) để có kiến ​​thức về điều này.

Trong một dự án, chúng tôi có một NutritionController. Theo thời gian nó phát triển bao gồm những hành động này (nhiều với mình, GET, POST, và DELETE phương pháp):

Index (home controller) 
ViewFoodItem 
AddFoodItem 
EditFoodItem 
DeleteFoodItem 
ViewNutritionSummary 
SearchFoodItem 
AddToFavorites 
RemoveFromFavorites 
ViewFavorites 

Sau đó, chúng ta có một ExerciseController, mà sẽ bao gồm nhiều hành động tương tự, chẳng hạn như tìm kiếm và hành động yêu thích. Chúng có nên được tái cấu trúc thành bộ điều khiển riêng của chúng sao cho nó giống như vậy?

SearchController { 
    SearchExercise 
    SearchNutrition 
    //... etc 
} 

FavoritesController { 
    ViewNutritionFavorites 
    AddToNutritionFavorites 
    AddToExerciseFavorites 
    EditNutritionFavorites 
    EditExerciseFavorites 
    //... etc 
} 

Dường như với tôi rằng nếu bạn chia chúng thành các bộ điều khiển riêng biệt, bạn sẽ tăng phụ thuộc lớn ở mức độ nào đó để xử lý thông tin bạn cần. HOẶC bạn sẽ có một ứng dụng xử lý hoàn toàn chung sẽ rất khó xử lý vì bạn sẽ phải nhảy qua rất nhiều vòng để có được hiệu ứng mong muốn của bạn (ở mức M, V hoặc C).

Tôi đang nghĩ về điều này một cách sai lầm? Ví dụ, tôi nên có một đối tượng yêu thích chung chung và sau đó để cho bộ điều khiển quyết định xem cái gì để ném nó vào?

* Xin lỗi vì đánh vần ra các từ viết tắt - Tôi đang làm như vậy trong trường hợp bất cứ ai khác đi qua câu hỏi này và là tránh khỏi thất bại như những gì những thứ đó là

EDIT: Tất cả các logic tôi thực hiện là xử lý khá nhiều trong các lớp dịch vụ. Ví dụ, bộ điều khiển sẽ gửi FoodItem 'mới' vào dịch vụ. Nếu nó đã tồn tại, hoặc có một lỗi với nó, dịch vụ sẽ bong bóng nó trở lại với bộ điều khiển.

Trả lời

12

tôi sẽ phá vỡ danh sách đầu tiên của bạn lên dựa trên trách nhiệm:

HomeController

  • Index

FoodItemController

  • ViewFoodItem
  • AddFoodItem
  • EditFoodItem
  • DeleteFoodItem
  • SearchFoodItem

NutritionController

  • ViewNutritionSummary

FavoritesController

  • AddToFavorites
  • RemoveFromFavorites
  • ViewFavorites
  • SearchFavorites
  • cách tiếp cận

Django 's để MVC là tách trách nhiệm vào "ứng dụng", đều có mô hình riêng của họ , bộ điều khiển và thậm chí cả các mẫu nếu cần. Bạn sẽ có ứng dụng Thực phẩm, ứng dụng Dinh dưỡng, ứng dụng Tìm kiếm và ứng dụng Ưa thích, rất có thể.

Chỉnh sửa: OP đề cập rằng tìm kiếm cụ thể hơn cho từng bộ điều khiển, vì vậy tôi đã thực hiện những hành động đó. Tuy nhiên, tìm kiếm cũng có thể chỉ là một thứ chung chung, vì vậy trong những trường hợp đó, SearchController sẽ ổn.

+0

Vì vậy, tôi sẽ lặp lại những điều tương tự cho Bài tập hoặc thêm chúng vào các bộ điều khiển đó? I E. sẽ SearchController xử lý các phương pháp SearchExerciseItem, hoặc đó sẽ là một bộ điều khiển khác như SearchExerciseController? – MunkiPhD

+0

Nếu đó là cách bạn thiết lập nó, tìm kiếm là một hành động ON bộ điều khiển, không phải là bộ điều khiển tại thời điểm này. Là tìm kiếm một cái gì đó chung, nó có thể là bộ điều khiển riêng của nó sau đó. Tôi đã sửa đổi câu trả lời của mình để phản ánh điều này. – Soviut

+0

MVC làm việc với REST theo cách rất tự nhiên: Tất cả các bộ điều khiển của bạn "điều khiển" một loại tài nguyên và biết cách thực hiện các hành động khác nhau trên tài nguyên đó (tức là trả lời các thông điệp khác nhau được chuyển đến tài nguyên đó) đối với các kiểu thực thể kiểu miền chủ yếu là một đối một (đó là điểm có mô hình miền). – yfeldblum

1

Tôi không quá quen thuộc với khuôn khổ đó, nhưng tôi có thể đưa ra một số lời khuyên chung. Một bộ điều khiển có lẽ chỉ nên biết cách hoàn thành một hành động đơn lẻ, hoặc gọi các bộ điều khiển hành động đơn lẻ khác để hoàn thành một chuỗi các hành động liên quan. Bất kỳ thông tin nào phải được truyền xung quanh từ hành động đến hành động có thể bằng cách nào đó được truyền qua lớp mô hình, vì thông tin đó có nhiều khả năng liên quan đến mô hình cơ bản.

+2

Đó không phải là cách nó hoạt động trong nhiều khung công tác MVC (ví dụ: Rails, ASP.NET MVC). Một bộ điều khiển duy nhất biết cách thực hiện nhiều hành động trên một loại thực thể duy nhất, nhưng không nên biết cách thực hiện bất kỳ hành động nào trên các loại thực thể khác. – yfeldblum

2

Làm như Soviut nói. Bạn muốn giữ cho bộ điều khiển đơn giản. Nghe có vẻ như kết thúc của bạn với logic phối hợp quá nhiều trong bộ điều khiển của bạn. Hãy nhớ rằng họ có trách nhiệm hooking lên một cái nhìn và một mô hình. Logic phối hợp này có lẽ nên được tách ra thành các dịch vụ.

Tôi nhận được cảm giác này bởi vì bạn đề cập đến khả năng bộ điều khiển của bạn đang phát triển phụ thuộc rất lớn. Vâng Nếu FavoritesController cần biết về dinh dưỡng và tập thể dục yêu thích (để hiển thị trong cùng một chế độ xem) không làm cho bộ điều khiển của bạn phụ thuộc vào 2 kho lưu trữ như các lớp học. Thay vào đó, đóng gói hành vi phối hợp đó. Có thể tạo ra một FavoritesService mà biết làm thế nào để trả lại cả hai yêu thích dinh dưỡng và tập thể dục. Dịch vụ đó có thể ủy quyền cho NutritionFavoritesService và ExerciseFavoritesService.Bằng cách này, bạn điều khiển chỉ kết thúc với 1 phụ thuộc, bạn đang giữ mọi thứ KHÔ, thực thi SRP, và tập trung logic kinh doanh của bạn ở một nơi nào đó ngoài bộ điều khiển.

+0

Tôi có hầu hết các logic phối hợp trong các dịch vụ, nhưng có vẻ như tôi có các phương thức rất cụ thể trong cả hai bộ điều khiển và các lớp dịch vụ của tôi. Ví dụ, bộ điều khiển sẽ có cuộc gọi 'GetFavoriteFoodItemsForUser' đến lớp dịch vụ nơi tôi xử lý mọi thứ và trả về một danh sách, mà bộ điều khiển sau đó đổ vào một khung nhìn. – MunkiPhD

+0

Ah. Tôi sẽ cố gắng và đưa ra một số quy tắc chung và cập nhật câu trả lời của tôi. Đối với ví dụ bạn cung cấp, tôi có thể có một UserController với một phương thức FavoirteFoodTiems chỉ chấp nhận HttpMetthod GET. –

+0

Chỉnh sửa của bạn đã xóa một chút đối với tôi - Cảm ơn – MunkiPhD

1

Tôi cũng đã trải qua những loại đau đầu bảo trì này và tìm cách bám vào một "Rails" như phương pháp rất hữu ích trong việc giữ cho bộ điều khiển của tôi tập trung và không được yêu thích.

Nếu tôi thấy mình thêm hành động có tên khác thường Ví dụ: Để sử dụng một ví dụ viết blog, AddPostToBlog, đó sẽ là một lá cờ để tạo một bộ điều khiển Post mới với một hành động Tạo.

Nói cách khác, nếu hành động không phải là một trong các hành động Chỉ mục, Mới, Tạo, Hiển thị, Chỉnh sửa, Cập nhật và Tiêu diệt, thì tôi thêm một bộ điều khiển mới cụ thể cho hành động tôi yêu cầu.

Ví dụ của bạn.

SearchController { 
    SearchExercise 
    SearchNutrition 
    //... etc 
} 

tôi sẽ cấu trúc lại này để ...

SearchExerciseController { 
      Index 
    } 

    SearchNutritionController { 
      Index 
    } 

Điều này có nghĩa có nhiều bộ điều khiển, nhưng theo ý kiến ​​của tôi thats dễ dàng hơn để quản lý hơn bao giờ mở rộng "thần" điều khiển. Nó cũng có nghĩa là các bộ điều khiển tự tài liệu hơn.

Ví dụ: Hành động SearchExercise có trả lại Chế độ xem để tìm kiếm bài tập hay thực sự thực hiện tìm kiếm không? Bạn có thể chắc chắn xác định điều này bằng cách nhìn vào các thông số và cơ thể, nhưng nó không dễ dàng như ví dụ một cặp mới và tạo, hoặc chỉnh sửa và cập nhật hành động.

SearchController { 
    SearchExercise  
}