我已经使用Rails超过4年了,所以很明显我喜欢Rails,喜欢用Rails Way做事,有时候我会在不知不觉中陷入黑暗面。
我最近选择了鲍勃叔叔的清洁代码。我在第6章并且有点困惑我们是否作为铁轨开发人员打破了OO设计的基本规则,即Demeter法则或封装? Demeter法则指出一个对象不应该知道另一个对象的内部,它不应该调用方法返回的对象上的方法,因为当你这样做时,它会建议一个对象对另一个对象了解太多。
但是我们经常从模型中调用另一个对象的方法。例如,当我们有一个像'一个订单属于一个用户'的关系时。然后我们经常最后做order.user.name或者为了防止它看起来像火车残骸,我们设置了一个委托来做order.name。
这还不像打破得墨忒耳或封装法吗?
另一个问题是:ActiveRecord只是一个与数据库接口的数据结构或数据传输对象吗?
如果是,那么我们不是通过将我们的业务规则放在ActiveRecord模型中来创建混合结构,即半对象和半数据结构吗?
答案 0 :(得分:15)
Rails是Rails。还有什么可说的。是的,Rails中的一些习语违反了良好的设计原则。但是我们容忍这个,因为它是Rails的方式。
话虽如此,在大多数rails应用程序中使用的模型太多了。我经常看到直接访问模型的视图代码。我将业务规则折叠到活动记录对象中。更好的方法是将业务规则与活动记录隔离开来,并将视图与模型隔离开来。这不会违反任何rails惯用语,并且会使rails应用程序更加灵活和可维护。
答案 1 :(得分:7)
恕我直言,如果你过分遵循纯粹主义的做法,那么你最终会像Java一样混乱,它会使用所有正确的设计模式,但是没有人能够记住你需要的八行代码才能打开文件并阅读它内容。
Rails的ActiveRecord框架是Martin Fowler的Active Record design pattern的实现。 Rails中的Active Records当然不仅仅是愚蠢的数据结构或DTO,因为它们具有行为:它们执行验证,它们可以告诉您它们的属性是否已经改变等等,并且您是自由的,而且确实是encouraged,以添加您自己的行为那里的商业逻辑。
一般来说,Rails鼓励良好实践,例如MVC和句法醋使做坏事变得困难和/或丑陋。答案 2 :(得分:4)
是的,ActiveRecord故意打破封装。这不是Rails的限制,因为它是基于它的模式的限制。 Martin Fowler,其ActiveRecord的定义几乎就是Rails使用的模板,在POEAA的ActiveRecord章节中也是这样说的:
针对 Active的另一个论点 记录是它结合的事实 对象设计到数据库 设计。这使得它更加困难 将任一设计重构为项目 继续前进。
这是来自其他框架的common criticism Rails。福勒本人说ActiveRecord主要用于
...对于不太合适的域逻辑 复杂......如果你的业务逻辑是 很复杂,你很快就会想要使用你的 对象的直接关系, 集合,继承等。 这些不容易映射到Active Record。
Fowler接着说,对于具有复杂域逻辑的更严重的应用程序,Data Mapper pattern更好,它可以更好地分离各层。这是Rails upcoming move to Merb一般被视为Rails的积极举动的原因之一,因为Merb除了使用ActiveRecord之外还使用了DataMapper模式。
我不确定Demeter是ActiveRecord的主要关注点。相反,我认为打破数据和域层之间的封装会打破Uncle Bob的Single Responsibility Principle。德米特我认为更像是如何遵循开放/封闭原则的具体例子。但我认为所有这些背后的更广泛的想法是相同的:类应该做一件事并且对未来的变化具有强大的功能,这在某种程度上是ActiveRecord不是。
答案 3 :(得分:1)
关于“德米特定律”,我没有看到的一件事是距离的概念。我的意思是,“涉及的对象有多紧密相关?”我认为,无论我是否关注“德米特定律”,这都会有所不同。
在ActiveRecord的情况下,大多数LoD违规所涉及的对象不可分割地绑定在一起成为一种紧密的关系。更改这些对象的内部数据结构需要更改数据库以反映该新结构。数据库的表通常“绑定”在一起成为一个数据库,甚至通过外键约束(或至少包含主键和外键)反映这些“关联”。
所以我一般不关心自己在AR对象之间跟随LoD。我知道,由于他们的本性,他们彼此紧密相连。
另一方面,我会更关心更远距离物体之间的LoD,特别是那些跨越MVC边界或任何其他此类设计装置的物体。