为什么计算科学中最难的两件事是命名和缓存失效

2013-01-11 10:18 "@thinkjava"的内容
命名是有些笼统 ...

DDD的命名笼统好像是小事,但是反映了对事物的分析程度,有句老话:
"There are only two hard things in Computer Science: cache invalidation and naming things" - Phil Karlton

计算科学中最难的两件事是命名和缓存失效。

在DDD实践中,这两个问题都会同时碰到,命名反映了领域模型的提炼过程,聚合边界的划分,说白了反映程序员的分析能力:

事物分析方法之道:找出内聚性强的结构,以包含这个结构为边界进行切分。

找到聚合体名称后,实体和值对象等类的名称都能确定了。但是这个过程在对复杂业务情况下比较难。

关于缓存失效,其实也就涉及到实体的状态变化,现在计算机业界采取有态和无态划分方式,EJB也是这种划分,函数编程FP也是这种划分,专门针对无态。但是有态的变化是无法回避的,也是很难的。

见下图,当我们命名好我们的领域模型后,进入计算机代码实施时,这时我们的领域模型对象是生存在计算机的In-memory cache,而领域模型的对象状态是经常被事件改变的,那么不可避免遭遇状态在缓存中失效,也就是更新的问题:

下图演示用户的事件是如何改变领域模型状态的:

缓存失效还涉及到数据一致性等等问题,也可以说,很难用算法来精确进行缓存失效。

一个复杂系统只有将这两个问题解决了,系统基本意味成熟稳定了,也就表示良好的维护性和拓展性,否则越修改越乱,BUG越多。

有句笑话:程序猿成天象抓蚊子一样抓臭虫BUG,反映两个问题:
首先教育阶段只了解CPU是咋样脾气,不了解人如何与CPU计算机交互,或者说如何训练计算机作为自己的宠物狗;第二是因为不了解人分析事物方法,也就不知道有这个“道”存在,只能象无头苍蝇到处乱撞,拼命加班,浪费青春年华。

[该贴被banq于2013-01-12 10:05修改过]

2013-01-12 10:04 "@banq"的内容
一个复杂系统只有将这两个问题解决了,系统基本意味成熟稳定了,也就表示良好的维护性和拓展性,否则越修改越乱,BUG越多。 ...

这个句话让人是最为深刻

是的,这两个同时是哲学上的问题。

命名要考虑时空带来的逻辑问题。可以看看《命名与必然性》。

关于缓存失效,首先要知道实体是没有时空概念的,但在逻辑运算时,经过运算后哪怕是相等的,但也是不相同的——时间上不等。对于实体的缓存是困难的,因为他们格格不入,实体是可变的,而缓存的东西是不变的(所谓的实体缓存,其实是缓存ID,或者缓存引用)。

其实这一切是由“实体”带来的。但是我们又不能摆脱实体带来的认知,所以我们必须找到不让实体绑架的编程方法(不是否定实体,而是必须减少对其依赖,如减少事务,多使用值)。

2013-01-12 10:04 "@banq"的内容
找到聚合体名称后,实体和值对象等类的名称都能确定了。但是这个过程在对复杂业务情况下比较难。 ...

    的确,复杂场景下比较难。更为困难的是复杂业务的稳定性更差,导致分析出的领域模型不易稳固。

    另外,对于缓存失效的策略,我是这样设计的。我会把一次业务执行中所有对领域对象的修改放到一个key为线程名的cache里,如果最后发现异常,就会清空该次业务执行中的所有相关对象cache。这样做相比jivejdon的做法要精确很多。运行很久了,没发现什么问题。
[该贴被flyzb于2013-01-16 20:17修改过]

这两个难题其实都是一致性的问题:

1.命名问题是逻辑一致性的问题,只有发现事物内在的逻辑一致性,才能给这个事物取名。
聚合与一致性和有界上下文
DDD通过聚合这个重要的发明概念,对一致性更新也进行划分,聚合边界内实现严格一致性,而聚合体之间可实现最终一致的更新。

2.缓存冗余问题是复制一致性的问题,如何在可用性 分区性和一致性之间取得综合平衡(CAP定理)。
facebook弃用memcache替代以Mcdipper,解决缓存数据冗余非常艰难。
[该贴被banq于2013-05-02 09:29修改过]

有感触!

看jdon,是OO思想的大提升。