【问题标题】:Does the law of Demeter also apply to standard ActiveRecord object methods?得墨忒耳定律是否也适用于标准的 ActiveRecord 对象方法?
【发布时间】:2013-04-29 12:45:38
【问题描述】:

假设你有一个班级Car,它有一个Driver。如果你想访问司机的年龄,你会这样做:

@car.driver_age

代替

@car.driver.age

如果您在 Car 模型中委托了驱​​动程序的年龄属性(前缀设置为 true)。

但是,如果你也有一个Passenger 类并且你想访问车内乘客的数量,那么以下是否违反了得墨忒耳法则,或者我的想法过于狂热:

@car.passengers.count

【问题讨论】:

  • 过度热心是这个词:)
  • LoD 并不是严格意义上的点数。

标签: ruby-on-rails ruby law-of-demeter


【解决方案1】:

我认为count 太笼统了,我觉得没有必要代理呼叫。我会问自己这个问题:

以后有没有可能实现passengers,不会响应count

由于passengers 极有可能永远是一个容器类型,并且Ruby 中的所有容器类型(ArrayHash、...)都会以您期望的方式响应count,我会回答这个问题用“否”提问,因此坚持使用@car.passengers.count

编辑

但如果你这么严格,你确实违反了得墨忒耳法则。例如,考虑一个完全没有乘客的班级RobotCar < Car。现在,跟随 LoD,您可以简单地从方法 car.passenger_count 返回 0,而当不跟随 LoD 时,您必须从 passengers 返回一个空容器,以免破坏其他代码。

最后,您必须自己决定界面发生变化的可能性有多大。如果你非常确定它永远不会改变,那么我想不服从 LoD 是可以的。

【讨论】:

  • 一个空的乘客列表可能是合适的,因为机器人汽车可以有乘客。还有另一层抽象,例如,它是一辆 能够 载客但只是空车的汽车,还是完全没有座位,这就是 RobotCar 类所暗示的。不知道,我在围栏上——如果你要求机器人汽车的乘客,你仍然想返回一些合理的东西,或者抛出一个异常,否则你的界面将需要特别检查。
【解决方案2】:

如果您的类/方法需要知道驱动程序的年龄,它应该直接引用驱动程序:

@driver.age

或者到乘客数组:

@passengers.count

通过@car 访问这些会产生许多假设。想象一辆没有司机的自动汽车或一辆没有乘客的玩具车。 @car.driver_age@car.passengers_count 没有多大意义。

【讨论】:

  • meh,driver_age 将为零,passengers_count 将始终为零。
  • @kch 我不希望汽车一开始就知道司机的年龄。
  • 公平。 (亲爱的,这是我评论的全部内容,感谢您的照顾。)
  • @Stefan,确实,但这是一个人为的例子。
  • @railsuser400 当然,这取决于,但检查引用的对象通常是一种代码味道:Tell, Don't Ask
【解决方案3】:

LoD 不仅仅是“计算点”,用下划线换一个点也无济于事。

汽车有一个有年龄的司机;这没有什么不合理的。

(嗯,不是真的,因为我们即将进入无人驾驶汽车时代,而这种模型可能无法解释这一点,但这是一个单独的问题。)

函数的得墨忒耳定律要求对象 O 的方法 M 只能调用以下几种对象的方法:

  1. O 本身
  2. M 的参数
  3. 在 M 中创建/实例化的任何对象
  4. O 的直接组件对象

特别是,一个对象应该避免调用 另一个方法返回的成员对象的方法。

【讨论】:

  • 欢迎评论反对意见。我没有发现答案有什么过错,而且它的说法得到了支持。
猜你喜欢
  • 1970-01-01
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多