【问题标题】:Controller A calling Model B: Code smell?控制器 A 调用模型 B:代码气味?
【发布时间】:2012-12-12 22:21:35
【问题描述】:

我有一个toys 控制器,用户可以使用它来认领玩具。现在,claim 方法是在控制器级别实现的(就像 answer 建议的那样)。

但是,现在声称确实不应该存在的逻辑变得有点胖了:如果一个孩子已经拥有 3 个玩具,他们就不能声称一个玩具,一个孩子不能声称另一个孩子声称的玩具,等等。该逻辑的合理点(在我看来)在 child 模型中,因为我正在描述一个孩子的行为(他们可以做什么,不可以做什么)。

也就是说,如果我这样做,toys#claim 控制器操作将调用来自child 模型的方法。这是代码异味/不好的做法吗?

(我猜有人会建议我为此使用服务对象。如果你这样做了,你能指出一个简单的教程吗?最近的 RailsCast 对我来说有点太复杂了。)

提前致谢!

【问题讨论】:

  • 我会说,将active record 用于除纯 CRUD 之外的任何内容并在控制器中具有应用程序逻辑,这不仅是代码异味,而且是架构错误。但这与任何给定控制器使用的模型层结构没有任何关系。
  • 我建议您真正需要的是Claim 模型。
  • @tereško:那我该怎么办?
  • @DanCheail 索赔模型?但这只是一个简单的一对多关联,只需要toys 表中的一个外键即可实现。为什么要为此制作另一个模型?
  • 但这不仅仅是一个简单的关联——你有一套相当复杂的规则/验证。另外,如果您想开始跟踪以前的索赔、玩具索赔的时间长度等怎么办?

标签: ruby-on-rails model-view-controller


【解决方案1】:

一般来说(在 Rails 之外),它根本不是一种气味。事实上,我认为在“模型”和“控制器”之间进行纯粹的 1:1 映射是一种味道。

注意:我不是 ROR 开发者。我在 ROR 或它如何实现事物方面没有经验。但是,我确实非常了解设计模式,并且了解应用程序架构。话虽如此:

与其担心 1:1 映射,不如退后一步考虑一下应用程序的结构。

控制器应该做什么?好吧,一般来说,它应该将用户操作路由到应用程序。这只是一个管道步骤。

那么模型(层)应该做什么?通常,模型是一个包含应用程序中所有业务逻辑的层。它将处理数据库交互、访问控制、业务操作等。因此,模型实际上是您应用程序的绝大多数。

另一方面,视图是您的表示层。它应该处理所有渲染,从模型层提取数据。

基于这种理解,您的模型、视图和控制器应该能够相互独立地变化。一般来说,我希望看到控制器和视图之间的关系相当 1:1。我的意思是每个存在的控制器,我都希望看到一个视图。但是可能存在没有用户交互的视图。在这些情况下,您可能需要一个控制器(用于渲染视图),或者根据您的架构,您可能不需要一个。

但是“模型类”是模型层的一小部分(充当较低模型功能的代理或适配器)与控制器或视图可能是或可能不是 1:1。例如,您可能有一个从多个模型中提取数据的视图。您可以拥有一个作用于多个模型的控制器。

现在您可以退后一步说,如果控制器需要对多个模型进行操作,则创建一个新模型来抽象该操作。有时这是正确的做法。有时不是。这一切都归结为所涉及的具体操作和关系......

归根结底,这里没有“对”或“错”之分。在构建应用程序时,确实需要做出设计决策。我不会太担心“气味”组件,只要它在您的应用程序中有意义...

【讨论】:

  • 绝对史诗!非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 1970-01-01
  • 2010-09-09
  • 2012-03-18
相关资源
最近更新 更多