从数据结构+算法分析ORM的末日

大家讨论都挺好,我下面进行纯粹分析一下,今天脑子比较好些。

对象和数据库都是一种静态的数据结构,而SQL与LinQ或Lambda表达式或Stream都属于一种动态算法过程。两个分别对应内存和CPU,如同哼哈二将,阴阳一体,一个系统由这个两个组成比较和谐。但是有时会组合错误。

和谐:
数据结构+算法过程

不匹配阻抗:
数据结构+数据结构
算法过程+算法过程

使用ORM相当于对象和数据库两个数据结构,因此存在阻抗矛盾,相反,因为SQL属于算法过程,SQL+数据库反而比较协调,但是做些CRUD还可以,应对复杂的业务,需要翻看各种数据表设计才能明白业务,数据库表又混杂了各种技术性能优化等技术方言,相当于方言夹带普通话,只通普通话(代表业务语言)的人不容易听通,增加沟通的难度。

后来有了Java等对象语言,就有了SQL+数据库+DTO数据Java对象,这就是大部分系统的特点,两个数据结构发生阻抗,改了数据库表还要改Java对象。

Hibernate试图协调对象和数据库两种数据结构矛盾,其实是清官难断家务事,捣浆糊而已,因为从逻辑上对象和数据表两者本来就没有必要搞到一起,搞个映射对应。

Hibernate出来很讨人喜欢,但是做些简单CRUD没有问题,随着项目深入,加上程序员数据库思维影响,使用Hibernate觉得隔着靴子瘙痒,其实我一直认为,如果程序员有阅读一个框架的源码冲动时,说明抽象泄漏已经发生,泄漏出来的坏味道已经让使用者心神不宁了。最终现实是:使用Hibernate的人是SQL与Hibernate两个要一起掌握,其实是增加学习成本。

EventSourcing是因为DDD这个用对象分析复杂业务的方法出现以后才出来,ES属于算法,领域对象聚合根实体属于数据结构,两种阴阳搭配协调,如同SQL+数据库一样干净。

当然,LinQ+集合或Stream+Collection都属于和谐干净的阴阳合体。OO+函数也是。包括大数据分析中Stream+Cache都是这样。

总之:只要一个系统只有一个数据结构+一个算法过程,这个系统本身就干净和谐,只有系统架构干净简单,才不至于因为架构复杂而导致项目失败或导致项目维护困难。聪明的人不能因为自己发明解决问题的方法干扰了自己解决问题的目的。

[该贴被banq于2014-04-23 07:37修改过]

以上谈的对象是一种数据对象,只有对象属性除了setter/getter以外没有任何行为的对象,或称为失血对象贫血。比如:


class A{
private int id;
private String name;
....
}

这种贫血对象纯粹是一种数据结构,与数据库定义的数据库结构是同一的或者重复的,在这两者有天然阻抗之间做O/R Mapping映射会增加复杂性。Martin fowler比喻ORM为是看不到胜利希望的越战。

DDD聚合根实体对象是主张有业务行为的对象,是充血模型对象,而使用这种对象和数据库之间做ORM更加不匹配,因为数据库表记录只能记录充血对象中的属性状态,对象的行为轨迹也就是触发对象行为的事件无法记录,正好相反,ES是记录事件,事件能推导出状态,状态不能反推导出事件,因此只需要记录事件一个即可,无需再记录状态。

[该贴被banq于2014-04-23 08:41修改过]

event sourcing在数据订正方面很复杂,这也是它相对于记录最新状态的方案的一个缺点。

有的时候我们仅仅关注对象的最新状态,不太关心对象的变化轨迹。如果用传统orm记录对象最新状态,将最新状态保存在db,那出问题时,如果发现数据不对了,可以用SQL来数据订正即可。而用event sourcing,就非常麻烦,因为我们没有可以将数据进行订正的对应的event。试想为了修改一条数据的状态,我们没办法数据订正,而必须修改代码然后重新发布站点,这是多么不爽的事情啊。

另外,event sourcing要能还原对象的前提是我们的领域对象的结构要保持和原来兼容,否则无法再根据老的事件来还原聚合根了。这也是使用event sourcing要考虑的一个问题。

event sourcing通过记录对象变化的一系列事件来实现持久化,这种做法虽然有很多好处,但同时也让我们的模型和历史事件相绑定了,也就是说,模型的设计可能会受到已经发生的事件的约束,历史的事件反而成为了模型结构演化的绊脚石了(这点是和只记录对象最新状态的设计相比较得出的结论)。

所以,我的观点是,不要只看到好的方面,不好的方面也要诚然面对和寻找解决方案。
[该贴被tangxuehua于2014-04-23 09:34修改过]

嗯,有时候ES并不需要,同时需要ES的时候必须用。

我是把CQRS裁开用的,一般的业务系统不用ES,比如最近开发的一套系统。但会采用 CQRS 的其他组件。

有时候甚至不需要用cqrs ,但会采用aggre聚合根的设计原则编写 oo

Eventsource是忠实记录用户行为的最佳方式,有正向事件,也有反向事件,为大数据提供最好的数据来源。

2014-04-23 08:36 "@banq"的内容
使用这种对象和数据库之间做ORM更加不匹配,因为数据库表记录只能记录充血对象中的属性状态,对象的行为轨迹也就是触发对象行为的事件无法记录,正好相反,ES是记录事件,事件能推导出状态,状态不能反推导出事件,因此只需要记录事件一个即可,无需再记 ...

有没有想过如何查询指定状态的对象?到事件里去海捞?hadoop?

纠正一个观点:ORM不是不能做充血模型,把事件当实体一样能纪录对象的行为轨迹