jivejdon设计问题

个人认为,ForumThread,AccountProfile应该是ValueObject
值对象特征:
1.ValueObject是通过属性来比较的
2.它没有Identity
3.一创建即是最终状态
4.如果要修改ValueObject直接创建一个新的,而不是在原对象进行修改
5.不需要状态同步.

jiveJdon中ForumThread不可能独立存在,它必须依赖rootMessage(ForumMessage),而且是1:1的关系,要访问ForumThread必须通过ForumMessage,而且它的Identity是依赖rootMessage的(也就是说没用自己的Identity,并不是说在DB中它没主键).由于ForumThread,ForumMessage是1:1的关系,所以,任何时候获取同一个ForumMessage它说对应的ForumThread是相同的(即不需要状态同步)。
同理可得AccountProfile也是ValueObject

综上:ValueObject并不是不可以有Entity标识(DB主键),有Entity标识并不能说明它就是Entity(Domain Entity),具体应用具体分析.

以上纯属个人认识,如果有错误望大家指点.



[该贴被admin于2009-03-12 09:17修改过]

分析很深刻,同意ForumThread是值对象。这也是我后来逐步才认识到的,主要因为原来ForumThread有一个表,数据表概念影响了我,导致ForumThread和ForumMessage关系不紧密,导致一个BUG反复无法根除:就是在并发情况下,一个主题回帖后,这个主题thread不能及时更新其最新帖子的状态,这个问题单机测试是无法发现,一上线就出现,这从JiveJdon3.0和JiveJdon3.6版本不同比较中可以看出,我因为数据库思维影响也走了一段弯路,所以,现在才倡导不能太受数据库影响,最好的办法就是不学它,把它当作文件看到。

对业务需求进行类建模,从而知道了需求中的类和关联关系,类和关联在计算机运行是就是变成了内存中的对象和对象关系,电脑一关机,这些对象值和关联关系就没有了,所以,你必须保存对象值和关系到硬盘上,数据库不过就是这样一个持久化手段,如果把数据库看成对象值和关系的输出结果,就象人拉的屎一样,我们怎么能让屎来决定我们的脑袋呢?我经常这样脑袋好像被屎塞住一样。

相关帖:
对象在计算机生存空间:缓存
http://www.jdon.com/jivejdon/thread/35809.html
[该贴被banq于2009-03-12 16:56修改过]

sorry, I am doubt.

What is ForumThread and AccountProfile?

no matter these objects existed in DB or not, we do not care about the stat, just need some value. isn't it?

banq说的确实深有体会.数据表先入为主概念容易让领域建模误入歧途.面向数据库表的思维对现实世界进行抽象化和概念化比较困难.具体表现在我们的程序缺乏和现实世界领域的对应关系,对现实建模无能为力(或者是数据库建模对现实世界的模拟和映射并不自然和精确,因为数据建模无法映射现实业务实体抽象和具体,部分和整体的的关系,也无法映射业务实体与生俱来提供的行为和职责),建模就是将现实中的事务和计算机中的事务相互匹配和对应以及模拟,同时现实世界上是同时对数据以及对数据的操作是一个整体,而数据建模则没有.在实践中,我感觉到数据建模处理大型的异常复杂的业务是有些力不从心,前端表现层和后端耦合过紧,牵一发而动全身.数据建模解决了数学上的关系完整性的问题,却没有解决业务概念的完整性的问题(即不能完全模拟业务概念).
感觉到,jdon上面讲领域建模概念的和好处以及例子(如jivejdon)的很多.但是具体暴露建模的细节的这一思维过程的文章很少,也就是是说,如何去建模的文章太少(比如说如何去发现领域对象,如何发现领域对象的职责),希望banq以后多讲点儿建模过程的文章..呵呵
我个人觉得领域建模至少有以下几个步骤:
1.发现领域对象 方法有:领域的常识,前一个类似的系统抽取业务词汇 ,企业模型或供参照的体系结构 ,词汇表,报表,表单.一般可以通过名词语法分析来发现领域对象:这些名词一些是类,一些会成为类的属性,一些对我们的系统无关紧要 .每个名词或者形容词+名词的组合,我们把他们找出来,看哪些是我们候选的领域对象.一个常用的方法就是:用一些简单的问题来测试每个词.这个名词是否在系统的边界之内?这个名词可以拥有或者提供某些系统的服务或功能吗?这个名词拥有或者管理某些数据吗?这个名词和其它名词之间有什么关系吗?如果所有答案是"是",这个名词可能就是我们要找的领域对象.
2.弄清领域对象之间的关系 重点放在分析业务领域概念及其关系上,弄清领域对象的关系是:一般和特殊(继承),部分和整体(聚合和组合),还是关联和依赖等等
3.弄清领域对象的职责 CRC (类/职责/合作关系)方法 即通过基于角色的设计,通过角色的抽象和协作来弄清类的职责.即每个对象是一个角色,它对外提供什么服务,有什么职责,它维护和管理哪些信息,它和其他对象协作完成什么服务.CRC技术通过角色扮演的这种拟人的手法,以对话的形式模拟现实世界业务领域概念的行为,各种角色扮演不同的功能协作满足要实现的功能,是比较好的发现类的职责的方法.
4.弄清领域对象状态的变迁 使用UML状态图表示,如银行账户对象有正常,挂失,冻结,销户等状态.
5.领域对象相互协作提供服务 通过已有领域对象的组合和协作完成新的功能,领域对象的可重用性在此体现.
6.通过设计模式精化重构领域模型满足具体软件技术架构层次上的要求.
整个建模的思维过程就是一个探索复杂问题的过程,一个从模糊到清晰,从零散到系统的,从点到面的过程,从混沌到条理的逐步演进的过程.

[该贴被kylix_xp于2009-03-13 00:27修改过]
[该贴被kylix_xp于2009-03-13 00:28修改过]

这里有几个问题,在值对象中一直不明了。
1.值对象到底可以是组合多个对象的一个对象吗?
2.值对象存在的话它的好处和价值在哪里?
3.在DDD中除了domain对象就是值对象了吗?
-------------------------------------------
值对象的好处我认最大的就是共享。那么组合了多个对象的值对象类(如组合了创建时间这样的字段)那么共享基本不要想了。DDD的书中也讲了地址的例子,这是一个纯粹的值了。然后才是对象。
我再举个图片的例子。一个图片的内容是很少改的。但它他的上传时间等都是不一样的。有可能很多人上传了同一图片,那么这个图片是一个值对象。但它的上传时间可以组合到一个值对象吗?
其实threadcount它还是领域的概念,做为值对象很牵强。

从对象设计的原则来看。对象应该是最小的集合。那么domain object就可能聚合其它的对象是正常的。

综上:ValueObject并不是不可以有Entity标识(DB主键),有Entity标识并不能说明它就是Entity(Domain Entity)

这话是你说的还是evans 说的?别误人子弟呀

to: yananay

我并没有讲我的全正确,只是自己的认识.
具体您可以去看看DDD sample.
DDD sample application 中Leg,Itinerary皆是ValueObject,为何?
Leg中同样有主键啊,同时Itinerary也具有自己的主键啊。但他们却不是DomainEntity,而是DB Entity。
Leg与Itinerary关系是N:1(关系需要DB维护,要不然无法重建),没有Itinerary Leg有独立存在的意义吗?同样,没用ForumMessage哪来的ForumThread?一次完整航程(Itinerary)当然只属于某个特定的cargo(cargo是Entity),我们有理由拿着Itinerary的DB主键,去找Cargo的吗?(当然你可以用搜索).由此可得:
1.ValueObject有时也需要存储到DB中.
2.需要ValueObject在数据库的主键维护关系,可以有DB Identity.(这样才能重建)
3.ValueObject的主键,只是为了对象冬眠以后的重建,并不具有有业务有关的明确Identity(领域标识).
以上都完整的体现了DomainEntity与DB Entity之间的区别.并不是说要存储到DB的对象就是Entity,这只是数据库实体,而不是领域实体.不同的应用场景,有不同的区分规则.

[该贴被yinyousong于2009-03-13 13:01修改过]
[该贴被yinyousong于2009-03-13 13:09修改过]
[该贴被yinyousong于2009-03-13 13:14修改过]

to kylix_xp

--- 数据库建模对现实世界的模拟和映射并不自然和精确,因为数据建模无法映射现实业务实体抽象和具体,部分和整体的的关系,也无法映射业务实体与生俱来提供的行为和职责 ----

实体包括抽象和具体两种:比如化学反应就是一种抽象的实体概念,而铅笔是具体的实体概念。对于这两种概念,数据建模依然可以很好的模拟。对于实体的行为和职责,本来就不属于数据建模的范畴,而是行为的范畴。

恩,说说俺的想法吧!
首先建立领域模型的时候,我们就没有必要考虑数据库的问题。
所以,无论是 实体 还是 值对象,都是领域模型,和是否存储在数据库中有关系吗?---没有。

所以呢,"DB主键" 这个词明显不合适,为啥不合适?因为在设计领域模型的时候,咱们不考虑数据库,所以,哪来的 DB主键 ?正确的说法应该是 领域模型唯一的标识。

至于 domain entity, db entity,这样的词放在一起,更是让人发蒙。。。

ok, 通常来说, value object 确实不需要唯一标识,因为 value object 是可以被任意复制,创建的。也就是说,value object 不应该有自己的唯一标识。再说的简单点,我们不会直接去得到这个 value object,而是通过别的东西得到它。最简单的代码:
class A {
String userName;
}

这个 userName 就是一个 value object,我们会得到 A 的实例以后,再获得 userName。当然实际中我们不会无聊到关注这样的 value object。

至于你说的 ddd sample 中为啥那些东西是值对象?俺也不知道,我想是业务的需求,直接得到那些东西没啥意义,所以就设计他们为值对象了。但是如果业务变化了呢?他们就变成实体也说不准。

>数据建模解决了数学上的关系完整性的问题,却没有解决业务概念的完整性的问题(即不能完全模拟业务概念).
数据建模和类建模主要区别就在于后者以继承泛化为核心的设计,这个抽象层次数据建模是无法达到的。

>banq以后多讲点儿建模过程的文章.
不敢谈讲,只能有时分享思考的过程,其实大师们已经给我们写了很多文章,Martin Fowler的"分析模式"一书就谈了医疗保健软件、财务库存软件系统 项目计划管理软件 股票外汇期货金融软件等行业软件的建模分析过程。

正如他所说:对于一个大公司大系统来说:要识别分析其中的高层次问题是很容易的事情,但是要找出这些问题的根本原因却非常困难,这些公司产生的海量信息,能将任何一个视图分析他们的分析人员迅速淹没。

所以,分析能力深刻与否有时和天性相关,具有分析能力的人不善于说谎或搞虚的,因为他已经养成解剖“实”的习惯,做什么事情都会直奔主题,不拐弯抹角,虽然与人相处方面很差,但是他适合搞分析,搞软件分析,搞信息分析,搞股票金融分析,各取所长吧。

而缺乏分析的人经常会被骗上当,一个欠费电话或中奖电话就让他把钱交出来,这样的人基本分析能力都没有。

说这么多,主要说明:分析这个知识是创造性的艺术,是和经验和个性有关,很难有教科书定理学习的,所以,每个人只有对照自己的个性是否擅长来决定是否值得做分析,否则分析不是自己擅长,容易被事物表面欺骗,将是造成软件彻底失败的罪魁祸首。

除了MF提供的分析模式为我们列举分析方式以外,四色原型的有颜色的Java中,也将企业管理ERP涉及的人事 进销存 薪资计划 等系统进行了分析,这些都是可以学习的好题材,特别是搞企业软件的,不学就会走弯路。

to banq

-- 数据建模和类建模主要区别就在于后者以继承泛化为核心的设计,这个抽象层次数据建模是无法达到的。--

数据建模分为两种层次,一种是概念建模,一种是物理建模。对于继承泛化,概念建模是可以清晰的表达的,比如可以使用集合方式的表达,大集合套小集合(大集合对应的就是我们通常说的抽象父类,小集合就是具体的子类)。而您之所以认为数据建模无法表达继承泛化,个人猜测可能是您看到的是数据建模的第二种层次(物理建模),看到是缺乏层次的表结构。其实,表结构不是一个二维的结构,如果将每个列看成其具有的纬度,那么,表的形象也就自然的立体起来,成为一种多维的结构。
如果找来两拨人,对同一领域,一拨采用OO进行建模,一拨采用数据建模,我相信最终的结果会相差不大。

==Leg中同样有主键啊,同时Itinerary也具有自己的主键啊
没有找到你说的主键
Leg和Itinerary都是中间对象是没有数据库对应对象表的。DDD的书中也明说了的

to OOLA
------------
数据建模和对象建模是两种不同的范型.数据建模遵循三大范式,对象建模并不遵循它,建模的结果(关系模型和对象模型)没有可比性.喜欢用什么建模,只是个人习惯罢了.比如数据建模,表设计的尽量细粒度,消除冗余和多重依赖,最终可能是相当多的小表,表之间通过主外键关联,但是关联关系都是单一的.

对于业务极度复杂的项目,使用数据建模,即使我们用尽了各种复杂的SQL“技巧”,还嫌不够,很多人怀疑对象建模,因为怎么可以生成那么复杂,有时简直是任意复杂的SQL语句呢?
举个例子,织一件带花样图案的毛衣,其实只需要两根竹钎和一条毛线,织女甚至可以心不在焉地织!我们会恍然大悟,我们很多人用惯了各种复杂SQL语句和DBMS提供的专有技术,很多时候是因为我们的业务模型和业务逻辑的设计实在太差,甚至没有设计!于是,表和表之间形成网状关系,我们是被迫用千百根针和千百条线痛苦地编制只有我们自己才能理解的图案。

—— 对象建模。越是复杂的项目,受益越明显。

[该贴被kylix_xp于2009-03-17 13:42修改过]
[该贴被kylix_xp于2009-03-17 13:51修改过]

to pub

你自己想想看,Leg与Itinerary是N:1的关系,试问,如果他们没有自己的表,这中关系将怎么维护?

public final class Leg implements ValueObject<Leg> {

private CarrierMovement carrierMovement;
private Location from;
private Location to;

Leg 中包括的是实体。这个leg对象是在内存中构造出来的。
Leg也没有对象的仓储。