Demeter的定律是否也适用于标准的ActiveRecord对象方法?

时间:2013-04-29 12:45:38

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

假设您有一个班级Car,其中有一个Driver。如果你想访问驱动程序的年龄,你可以这样做:

@car.driver_age

而不是

@car.driver.age

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

但是,如果你还有一个Passenger课程并且你想要访问汽车中的乘客数量,以下是不是违反了得墨忒耳法则,或者我的想法过于热心:

@car.passengers.count

3 个答案:

答案 0 :(得分:5)

我认为count非常普遍,以至于我觉得没有必要代理这个电话。我会问自己这个问题:

  

将来可能会有passengers的实施,但不会回复count吗?

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

修改

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

最后,你必须自己决定接口改变的可能性。如果你非常肯定它不会改变,那么我想可以不服从LoD。

答案 1 :(得分:1)

如果你的班级/方法需要知道司机的年龄,它应该直接引用司机:

@driver.age

或者乘客:

@passengers.count

通过@car访问这些做出了许多假设。想象一下没有驾驶员或没有乘客的玩具车的自动驾驶汽车。 @car.driver_age@car.passengers_count没有多大意义。

答案 2 :(得分:1)

LoD不只是“计算点数”,并且用点数下划线也无济于事。

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

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

  

函数的Demeter定律要求对象O的方法M只能调用以下类型对象的方法:

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

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