添加快捷方法或遵循ActiveRecord语义?

时间:2009-02-08 18:07:19

标签: ruby-on-rails ruby refactoring associations naming

与我的一个朋友又一次争吵。请考虑以下代码:

class User < ActiveRecord::Base
  has_many :groups
  def in_group?(group)
      groups.include?(group)
  end
end
class Group < ActiveRecord::Base
  has_many :members
  def add_user(user)
      members << user
  end
end

我的观点是,这些方法为代码增加了额外的不必要的复杂性,难以猜测 - 比如为什么#in_group?但不是#is_a_member_of?,或者为什么#add_user而不是#add_member,依此类推。根据我4年的Rails经验和20年的编程经验,我最好遵循AR语义并使用User#groups.include?(group)和Group#members&lt;&lt;用户。它们很容易猜到,如果我需要一些额外的功能,我可以使用has_many回调:成员并覆盖User#groups.include?在协会扩展模块中,如果有必要的话。

然而,我的朋友认为最好使用快捷方式来创建“抽象点”,最好扩展此代码而不是使用回调或重载。

你怎么想?

P.S。为了清楚起见,我讨厌“如果”的方法:)

5 个答案:

答案 0 :(得分:2)

我完全同意不应添加这些方法。创建其他相关对象不是模型的工作。这是协会代理的工作。我还要注意重写关联代理行为,因为你可能会因代理的实现方式而看到一些奇怪的副作用。

答案 1 :(得分:1)

您引用的样式在“Demeter法则”下是可辩护的,它会警告客户端代码直接操纵groupsmembers

答案 2 :(得分:1)

我绝对支持抽象,但不是在执行中。你的朋友提出了一个很好的观点,如果你如何确定一个成员是否在一个团体中会怎样改变怎么办?你需要进行大量的重构,祝你好运!

但是,我看到了将错误的功能放在错误的地方的论点。我说你的组织不正确,为什么不将它们附加到特定的关系模型对象?

示例:

user.groups.in_group?("admin")

group.members.add_user(user)

对我而言看起来更优雅,更加冗长,但你的分离更具相关性。

答案 3 :(得分:0)

对于in_group?:您的方法名称可以在一个方向上猜测 - 当您阅读它时,它的作用非常明显。这是一种可猜测的重要方式。当某人维护此代码时,他不会被in_group?电话跟上。它也更具说明性和简洁性,从而提高了可读性(在这种情况下略有提升,但通常也很好)。这是一种Smalltalky方法。

另一方面,我认为add_user方法是不必要的。它似乎不是特别简洁或直接,只是非标准。这个名字仍然相当明显而且并不是非常有害,但我没有看到它的好处。它似乎更像是一条风景优美的路线,而不是捷径。

答案 4 :(得分:0)

当有原因时(例如组中的“成员”改变意义),我赞成这些方法。使用这些方法可以封装随时间增长和变化的逻辑,并有助于测试。这不是OO编程的全部意义吗?