ORM和Rails的问题

看到一句英文:ORM变相鼓励你抹去许多对象的相关状态,而Rails则鼓励你耦合任何一切。

原文:
An ORM encourages you to smear related state across a lot of objects, and then Rails encourages you to couple everything else to that.

抹去对象的状态,那么对象的存在意义就没有了,对象的存在价值是状态+守护状态的行为。如:


public class A{
private int state;

public void change(Event e){
....

this state = xxx; //根据输入事件改变状态
......
}

}

在这个A对象中,A中的状态改变只有必须通过A的行为change去改变,而且输入参数是事件,在change方法中根据业务规则判断输入事件是否允许,如果符合实现设定的规则,那么就允许改变状态,这样做的好处是A的状态改变无法从外部去改变,反之,如果A的状态暴露了(通过字段public或setter方法),如果任何一个新程序员在一个角度直接对A的状态修改,整个状态就可能混乱,状态失去意义,被抹去了。如下面的贫血模型是一种抹去状态的做法:

通过public字段开放:


public class A{
public int state;//public暴露给外界直接修改
....
}

通过setter方法开放:


public class A{
private int state;

public void setState(int newstate){
this state = newstate; //被外界直接修改
}
}

往深处说,前者用对象行为守卫状态的对象模型是一种遵循事物一致性的做法,将一致性划分在一个边界内,比如北京的事情在北京市这个范围内,上海的事情在上海这个范围内。

总结:
1. ORM鼓励你使用贫血模型,贫血模型实际破坏了对象的本身定义,将对象沦为一种数据结构。范了逻辑悖论和偷欢概念的问题
2. Rails鼓励耦合一切,解耦是设计的首要目标,如果一种简单快速的方法却是违反解耦松耦合这个目标的,我们还不如回到delphi时代呢。

以上观点只代表一种看法。更多参考:
领域模型行为设计
足球案例

[该贴被banq于2014-08-23 09:56修改过]

个人认为,该句英文主要表达以下意思:
1、orm消除众多对象之间的关联状态,来降低对象间的耦合度
2、rails集中某对象相关的一切,来提高对象的内聚

楼上解释也有道理,为谨慎起见,我查看了twitter原文的对话:https://twitter.com/jcoglan/status/502432700406718464

他们的对话是起源于文章:Complexity in Software 3: The Constructal Law(文章中文翻译见:软件的复杂性与构造定律):

复杂性是被低估的。复杂越高,开发人员会感到不安。对其的理解认知负荷代价就越高,我们就更不快乐。真正的挑战是在构建我们的系统时要保持其有序以及工程师的生产方式。对于这一点,一个简单的物理规律可以帮助我们:构造定律。

构造定律的意思是:For a finite-size system to persist in time (to live), it must evolve in such a way that it provides easier access to the imposed currents that flow through it.

对于一个有限大小的持续活动的系统,它必须以这种方式发展演进,它提供了一种元素之间更容易访问的方式。

这个定理在自然中比比皆是,典型的是树的生长,先有根,再有枝,枝上再生枝叶,我个人理解为:这实际说明自然界中“统一对立”,而不是我们以前认为的“对立统一”,简单顺序变化意义完全不同,统一先于对立原理应用在软件建模中非常自然,聚合根作为一群对象的统一代表,外界访问首先通过聚合根,不能直接访问聚合群内部任何对象。这是一种自然的遍历父子树形结构的顺序,只有先访问父节点,才能访问到其下多个对立的子节点。

构造定律代表的这种自发性质的设计反映了这一趋势:他们允许实体或事物更容易地流动 - 以最少的能量消耗到达最远的地方,就连街道和道路这些人为地构建物体,往往也是有排序的模式,以提供最大的灵活性。

最后,关于ORM和Rails这种问题,他们在Twitter的对话还有:

Check out CQRS for an architectural solution to this problem, but the Rails community (esp DHH) is not a fan of this style.
CQRS可以解决这个问题,但是Rails社区特别是Rails创始人DHH不是这种风格的粉丝。

也有人认为如果只是围绕CRUD或简单问题领域,Active Record是一个好的解决方案:
Agreed. If what you're doing centers around CRUD or is a simpler problem domain, then Active Record is perfectly ok.

[该贴被banq于2014-08-24 11:25修改过]

该Twitter讨论推崇 Kent Beck的那句话:软件设计者应该是分离应该分离事物,而不是将本应一起考虑的事情进行分离。

Josh Kodroff认为Rails的问题是用同一个类进行又读又写,将一起耦合在一起,应该采取CQRS的读写分离方式。

也就是说,Rails是将应该分离的进行了混合。而ORM则是将应该一起考虑的却进行了分离,原因是我在主贴里谈到的。

ORM和Rails的错误在于顺序流错误。