代码之家  ›  专栏  ›  技术社区  ›  MunkiPhD

上帝控制者-如何防止他们?

  •  15
  • MunkiPhD  · 技术社区  · 15 年前

    在我一直从事的几个MVC项目中,很明显有一些有问题的控制器已经有机地发展成了God类——如果你愿意的话,每个都在自己的领域中。

    这个问题可能更像是一个“何去何从”的问题,但我认为这是一个关于SRP(单一责任原则)、DRY(不要重复你自己)和保持事物简洁、“敏捷”的重要问题——我没有足够的经验(使用这种模式和一般设计)来了解这一点。

    在一个项目中,我们有一个营养控制器。随着时间的推移,它逐渐包含这些操作(许多操作都有各自的GET、POST和DELETE方法):

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

    SearchController {
        SearchExercise
        SearchNutrition
        //... etc
    }
    
    FavoritesController {
        ViewNutritionFavorites
        AddToNutritionFavorites
        AddToExerciseFavorites
        EditNutritionFavorites
        EditExerciseFavorites
        //... etc
    }
    

    在我看来,如果你把它们分成不同的控制器,你会在某种程度上产生一种难以置信的巨大依赖性来处理你需要的信息。或者,您将拥有一个完全通用的处理应用程序,该应用程序将非常难以处理,因为您将不得不跳过许多障碍以获得所需的效果(在M、V或C级别)。

    我想得不对吗?例如,我是否应该拥有一个通用收藏夹对象,然后让控制器决定将其扔到哪个视图?

    *对不起,我把这些首字母缩写拼出来了——我这样做是为了防止其他人遇到这个问题,并且不知道这些东西是什么

    4 回复  |  直到 12 年前
        1
  •  12
  •   Soviut    15 年前

    我会根据责任划分你的第一份名单:

    家庭控制器

    • 指数

    食品控制器

    • 编辑部
    • 删除食物
    • 搜索食物

    营养控制员

    偏爱控制器

    • 加多福莱特
    • 从收藏夹中删除
    • 查看收藏夹

    Django MVC的方法是将职责划分为“应用程序”,每个应用程序都有自己的模型、控制器,甚至必要时还有模板。你很可能会有一个食物应用程序、一个营养应用程序、一个搜索应用程序和一个收藏夹应用程序。

    编辑:OP提到搜索对每个控制器都更具体,所以我已经做了这些操作。然而,搜索也可能只是一个通用的全局事物,因此在这些情况下,SearchController就可以了。

        2
  •  2
  •   keparo    15 年前

    照索维特说的去做。您希望使控制器保持简单。听起来你的控制器中有太多的协调逻辑。请记住,它们负责连接视图和模型。这种协调逻辑可能应该划分为多个服务。

    我有这种感觉是因为你提到了你的控制器可能会变得越来越依赖。如果FavoritesController需要了解营养和运动收藏夹(显示在同一视图中),请不要让您的控制器依赖于两个类似于存储库的类。相反,封装该协调行为。也许可以创建一个偏好服务,知道如何返回营养和运动偏好。该服务可能会委托给NutritionFavoriteService和ExerciseFavoriteService。通过这种方式,您的控制器最终只有一个依赖项,您保持了干爽,强制执行SRP,并将业务逻辑集中在控制器之外的某个地方。

        3
  •  1
  •   SingleNegationElimination    15 年前

    我不太熟悉这个框架,但我可以提供一些一般性的建议。控制器可能只知道如何完成单个动作,或者调用其他单个动作控制器来完成一系列相关动作。任何必须从一个操作传递到另一个操作的信息都应该以某种方式通过模型层传递,因为这些信息很可能与底层模型相关。

        4
  •  1
  •   Matt    14 年前

    我也经历过此类维护难题,发现坚持“Rails”式的方法非常有助于保持我的控制器专注且不受干扰。

    换句话说,如果操作不是索引、新建、创建、显示、编辑、更新和销毁操作中的任何一个,那么我将为我需要的操作添加一个新的控制器。

    SearchController {
        SearchExercise
        SearchNutrition
        //... etc
    }
    

    我会把它重构成。。。

       SearchExerciseController {
               Index   
       }
    
       SearchNutritionController {
               Index   
       }
    

    这可能意味着拥有更多的控制器,但在我看来,这比以往扩展“上帝”控制器更容易管理。这也意味着控制器更加自我记录。

    例如,SearchExercise操作是否返回视图以搜索该练习,或者它是否实际执行搜索?您可能可以通过查看参数和主体来确定这一点,但这并不像新建和创建、编辑和更新动作对那样简单。

    SearchController {
        SearchExercise       
    }
    
    推荐文章