Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

God Controllers - How to prevent them?

In a few MVC projects I've been working on, it has become apparent that there are a few problematic controllers that have organically grown into God classes - demi-gods each in their own domain, if you will.

This question might be more of a matter 'what goes where,' but I think it's an important question with regards to SRP (Single Responsibility Principle), DRY (Don't Repeat Yourself), and keeping things concise, "agile" -- and I am not experienced enough (with this pattern and in general design) to be knowledgeable about this.

In one project, we have a NutritionController. Over time it's grown to include these actions (many with their respective, GET, POST, and DELETE methods):

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

Then we have an ExerciseController, which will include many similar actions, such as the searches, and favorites actions. Should these be refactored into their own controller so that it's something like so?

SearchController {
    SearchExercise
    SearchNutrition
    //... etc
}

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

It just seems to me that if you break them out into separate controllers, you're going to grow an unbelievably large dependency at some level to deal with the information that you will need. OR you are going to have a completely generic handling application that will be very difficult to handle since you will have to jump through so many hoops to get your desired effect (either at the M, V, or C level).

I am thinking about this the wrong way? For example, should I have a generic Favorites object and then let the controller decide what view to throw it to?

*Sorry for spelling out the acronyms -- I'm doing so in case anyone else comes across this question and is clueless as to what those things are

EDIT: All the logic I perform is pretty much handled in the service layers. For example, the controller will send the 'new' FoodItem to the service. If it already exists, or there's an error with it, the service will bubble it back up to the controller.

like image 720
MunkiPhD Avatar asked Jun 21 '09 16:06

MunkiPhD


1 Answers

I would break your first list up based on responsibility:

HomeController

  • Index

FoodItemController

  • ViewFoodItem
  • AddFoodItem
  • EditFoodItem
  • DeleteFoodItem
  • SearchFoodItem

NutritionController

  • ViewNutritionSummary

FavoritesController

  • AddToFavorites
  • RemoveFromFavorites
  • ViewFavorites
  • SearchFavorites

Django's approach to MVC is to separate responsibilities into "applications", each with their own models, controllers, and even templates if necessary. You'd have a Food app, a Nutrition app, a Search app, and a Favorites app, most likely.

Edit: The OP mentioned that searching is more specific to each controller, so I've made those actions. However, searching may also be just a general global thing, so in those cases, a SearchController would be fine.

like image 101
Soviut Avatar answered Oct 19 '22 14:10

Soviut