“卡是用户的映射”这并不是我的观点,我的观点早已说明了:“领域中不存在卡”。甚至我认为存折上的记录只是一个View层的东西。

“卡是用户的映射”是我从jdon007的代码中读出来的。因为他从“人使用卡”出发,认为是“卡”才是行为的执行者。

(我的习惯是用记事本写回复,然后复制过来提交的,忘记提交了-。-|||,以下是我之前想要说的:)


看来你,还是不了解我之前所讲的:内存领域中的实体和现实(或应用层的实体)不是同一个实体。这两者不是等价关系的。上面liam就已经说过“领域内的角色(Role)”。我从来也没说过,领域实体(参与者)只能对应一个现实实体(系统用户)。

应用驱动者与领域角色(场景参与者等)不是同一个。你完全可以认为内存领域中的实体“我”,不是我,它是一具行尸走肉,只不过它带着我的信息而已(从这里看,和你card很像),现实中我点击存钱,则系统产生存钱场景,内存领域中的“我”和相关实体进入场景,执行交互。现实中的我换一个帐号,则内存领域中出现另一个实体“我”。因为存在注册登录认证过程,所以可以称这样的一“我”为我的镜像。镜像的意思并没有现实中的我干什么,内存中的“我”干什么,而是我有什么,他也有什么,而镜像不像影子,镜像可以无限多,而影子只有一个(当然不是完全的,与领域相关的个人信息才会存在上面,这跟你的Card理解是一样的,但是我不叫Card,我叫他为Reader,一个领域角色,而且我的Card另有所属——应用层登录)。镜像,没人说过只有一个

领域中有很多的参与者,但这些参与者并不等于用户。因为注册后领域中就出现“我”,所以叫镜像,多次注册,就会出现多个镜像,你去申请多张卡,就会出现多个“你”镜像。而领域看到的是镜像,而非你,或者说领域认为那就是“你”。领域中所发生的事与现实中的系统用户无关,只与领域中的角色相关。

若果你真要说人使用杯子喝水的方式去理解的话,翻译过来就是人使用卡去借书。于是Card.borrowBook(Book);则有Cup.drink(Water);突然有一天人不用杯子喝水,把嘴张着,直接在水龙头下面接水喝,那这是Tap.drink(Water);?!?!

比起这样,我觉得Reader.borrowBook(Book);Drinker.drink(Water);更加自然。加入场景思维的话,可表示为borrowBookContext(Reader,Book).borrowBook();(BorrowBookContext.borrowBook(Reader,Book);)。这样看起来多自然。若果需要考虑使用物而引起不同效果的话,则增加方法(Reader.borrowHistoryBook();Reader.borrowBook(HistoryBook);),或者引入策略(BorrowBookContext(Reader,Book).borrowBook(HistoryBookStrategy);BorrowBookContext.useStrategy(MathsBookStrategy).borrowBook(Reader,Book);,或者增加使用物实体进入场景,同时把策略放到使用物实体上(这样可以简化)。当然,使用Mixin的写法又不一样了。

人使用刀去杀人,杀人的是刀,人不在领域,不在场景中,所以有不在场证明成立,最后判决——无解。(我觉得,理解驱动者,和参与者就能很好解析这句话错误了。)驱动者可以理解为客观规律(或者“道”),或者上帝,他们促使(规定/要求)这样的场景发生,于是参与者人.杀(人);,当中为啥没“刀”,因为并非关注点。若果刀也需要关注的话,那么刀决定效果,而并非决定行为。(或者当作看电影也可以)


分清楚:“系统使用者”与“领域角色”(或者“场景参与者”)不是同一个东西。人使用卡,是使用系统,并非在谈领域,卡是依赖系统的,并非依赖领域的。若果把卡归到核心领域,那么这样的核心模型就只能适合使用卡的图书馆了。(当然现在大多数是这样)


关于图书馆聚合根,的确,在图书馆领域中,人的方方面面都是和图书馆在打交道。如买菜者是跟卖菜者交互。如jivejdon的account跟forum(不过我个人意见认为account应该分离出passport和user,所以我之前有一篇帖子说过,user不应该存在account和password,因为这些不是领域业务,而是进入领域,一切开始之前的条件,这是题外话了)。

可以把这样的思维写成一个填词句子:( )与图书馆进行借还书行为。我填的是Reader,jdon007填的是Card。我俯视领域,我看到Reader在和Library交互。而jdon007看到的是Card在和Library交互,而我认为这样的Card模型是在拟人化。而非直接性拟人化也未尝不可。

[该贴被SpeedVan于2011-02-13 13:27修改过]

[该贴被SpeedVan于2011-02-13 14:25修改过]

借书活动是这个图书馆领域的核心场景之一。领域模型必须能够清晰地描述这个核心场景。

()与图书馆进行借还书行为,这个说法,没有说明这个行为如何进行,其中的交互过程是如何实现。

“欠条”是活动的结果,“写欠条”是活动的过程。“写欠条”的参与者是“借书人”,但“欠条”既然可以自动化地替“借书人”这一角色完成“写”的过程,就可以不需要“借书人”,就像“借阅条款”的执行者“管理员”也可以没有,如果“借阅条款”也可以履行“执行条款”的职责的话。

卡是“借书活动”的记录,卡“借”书,实际含义,是卡“自动记录”借了什么书。Card.borrowBook(book),的含义是卡“替”借书人“填写”借书记录。杯子是“盛水”,而不是“喝水”,Cup.hold(water),人可以不需要杯子,用手或口盛水,然后喝。
现在有“杯子”替“人”完成了(用手或口)“盛水”的职责。

杯子是饮水者?杯子不过替饮水者盛水而已。卡是借书人?卡不过替借书人填写欠条而已。至于饮水,读书,这才是饮水者与借书人的真正职责或真正想做的事情,盛水与借书(填写欠条)是可以由其他角色代劳的。

借书人向图书馆借书必须填写“欠条”,“欠条”的形式可以是“纸”或“卡”或未来的进化形式,这是领域的发展决定。当然这里用“卡”命名“欠条”确实太“具体”了,不妥!也许BorrowingRecord
更能体现其意义,与BorrowingTerm呼应。BorrowingRecord可以自动记录,BorrowingTerm可以自动执行。

至于用户与角色,我们的定义可能不同。举例,比如企业管理系统的用户是“张三、李四、王五、赵六”等人,“角色”是“员工、经理、主管、总裁”等。碰巧的是,在图书馆里系统的用户,恰好只扮演领域中的“借书人”这一角色。如果用户还可以扮演其他角色,你会发现“角色”与“用户”不能简单地理解镜像之类的,当然可以解释为这是多对多的映射关系,但我认为,两者之间的相对独立的意义,比映射关系要重要的多,更值得强调。

我想谈到这里,彼此的观点应该清晰了,应该也可以达成一致了。也许如banq所言,讨论的方向可能错了。

2011年02月13日 15:55 "jdon007"的内容
如果用户还可以扮演其他角色 ...

注意,思考领域时,就别牵涉到领域外,系统用户可以扮演其他角色,这样的思考不属于领域的。在用户登录时,基础身份已被确定,是管理员就管理员,是业务员就业务员,是客户就客户。站在领域中心向四周看,看到的是业务员1,业务员2,客户1,客户2,但领域不会去思考谁在用业务员1,或者客户2,在领域中最基层的角色就是业务员,客户等,最基层的角色实体就是业务员1,客户2等,与我们现实用户无关。你用banq的帐号登录发表文章,那么领域当中就是发生banq(这是领域中的实体)发表文章一事,与“你”没有任何关系。领域认为就是banq发表文章,没有其他可能。而这个角色实体banq,就是板桥的一个镜像。只是这个镜像banq,受到jdon007控制而已。

若果从细分的角度,你认为借书还需要写欠条,那么写欠条还需要拿纸拿笔。还有拿书呢?借书就是写欠条,不拿书?写欠条不是借书,而是欠条是借书的结果,banq都有说到,欠条是一个结果,其实欠条就如相当于日志。

这里就说到写欠条,写欠条是什么时候需要想到的呢?就是需要对借书进行细分之时——借书分为“检验身份合法性”check();,“写欠条”new Record();,“给书拿书”remove(); add();。而我们把这三项合并起来就是借书了。也就是一次借书所需要做的事情,但别把“写欠条”当作完整的借书。“盛水”和“写欠条”,已经不再是“喝水”和“借书”了。
[该贴被SpeedVan于2011-02-13 17:50修改过]

2011年02月13日 17:49 "SpeedVan"的内容
注意,思考领域时,就别牵涉到领域外,系统用户可以扮演其他角色,这样的思考不属于领域的。 ...

呵呵,我自始自终一直在强调“无之用”,“领域独立于用户”,可以看看上面的帖子,几乎每个帖子,都在反复强调这点。是你们一直在强调什么映射、镜像之类的。

领域模型是对客观领域的素描,描述客观存在。模型中不可能出现,现实中“物理上”的借书过程,领域模型的本质可以说是一种“语言”,该“语言”描述“现实”,显然不是“现实”本身。“欠条”本身既是结果,也从“借书人”这一角色的角度描述了“借书”之一场景。

从“借书人”这一角色的角度看,借书过程若要细化,可以分为:
1)“图书馆”愿意“借书”给你。相当于你拿到了卡。
2)拿一张用来记录的白纸。相当于卡本身。
3)你写下欠条,把书拿走。相当于你在卡上写下记录,但卡可以替你写,自动记录。

除了第1)点放在应用层实现,相当于用户进入领域的资格审查,如果很重要,可以考虑移入到领域中。至于其他两个过程在MI代码中已经体现了。“借书过程”的“给书”这一动作或职责是“图书馆”做的事情,与“借书人”这一角色无关,这在MI代码中也有体现。

盛水喝 = 借书看
盛水 = 借书
喝水 = 看书

杯子是饮水者?杯子不过替饮水者盛水而已。卡是借书人?卡不过替借书人借书而已。至于饮水,读书,这才是饮水者与借书人的真正职责或真正想做的事情,盛水与借书是可以由其他角色代劳的。

晕了,“领域独立于用户”我没有反对过吧?

这里的图书馆的系统,是借还书系统吧,哪来的看书?

从你的回复我看出我们思维的差别在什么地方了,我从一开始压根儿就没有把读书包括进来,借还就是领域的基本业务,而不是业务的方式(借来读)。

我理解的三个“=”应该是下面这样:

盛水喝 = 拿书借
盛水 = 拿书
喝水 = 借书

人想喝水,是以喝为核心的行为,人想借书,是以借为核心的行为。人“是否想借”与“是否想看”是无关的,借还系统与物品使用何关呢?借还系统和阅读系统的差别。

摘录

家里有两个孩子,孩子们对妈妈说,妈妈我要喝水。
妈妈说好,分别给孩子倒了一杯水。
学校里有两个学生,学生们对老师说,老师我借书,
老师说好,分别给孩子一张借书卡。

光这句就带有误导性质了,我要喝水,妈倒水给我,我要借书,是老师拿书给我。若果引入借书卡,则应该是:我要喝水,妈给我杯,我要借书,老师给我借书卡。第一句是关注行为与行为结果,第二句是关注行为与行为方式。

[该贴被SpeedVan于2011-02-13 21:46修改过]
[该贴被SpeedVan于2011-02-13 21:56修改过]


2011年02月13日 19:31 "jdon007"的内容
从“借书人”这一角色的角度看,借书过程若要细化,可以分为:
1)“图书馆”愿意“借书”给你。相当于你拿到了卡。
2)拿一张用来记录的白纸。相当于卡本身。
3)你写下欠条,把书拿走。相当于你在卡上写下记录,但卡可以替你写,自动记录。 ...

这三点我也来说说:
1)图书馆愿意借书给我,相当我拿了卡,也就是说卡,代表的是愿意,也就是一种身份认证,权限认证。
2)拿一张用来记录的白纸。相当于卡本身。这句我不认同,卡不是那张白纸,那张白纸是在系统内部。因为卡中的Record不能决定系统任何数据,卡只是单存的View,卡内的Record只能当为单纯的结果,而非实体Record,或者说并非“借”这一事件。数据事实只能依据一个地方,除非卡内信息能跟系统同步,而且保密。银行所用柜员机,是跟银行系统同步的,别以为它是根据你的卡内有多少钱来进行业务的。
3)我写下欠条,是在系统中出现欠条Record,而并非保存到卡上,若果卡上真有Record信息,那么它就相当于RecordForm,这是结果展示,而且申请卡上的协议一定写着:“一切以系统为准”,不相信系统咋办?在银行上,银行会出示纸张证明和监控记录,若果还不信,则是以违背协议为根据,一概认为无理取闹。银行本身就是信用机构。系统的关键信息从卡中读取本身就是一个滑稽的做法(除帐号,卡号外)。学校的饭卡?请看清楚你打卡的机器所连着的网线(不一定是相交线,更多的是机器专用的线)。这就是物联网。

把金钱余额存在卡上的做法并非没有,这要看风险问题。至少在我看来图书馆的书是其命根,银行的钱是其命运,他们不会把命根和命运放到用户手上。试想若果卡余额决定购买,若果卡的余额大于系统余额,呵呵,到时候谁亏了呢?


在这里我补充下,“镜像”一词的说法依据,镜像一词跟“领域模型是对客观领域的素描,描述客观存在。”是同一层次的,是模型跟客观的一种关系描述,我们想到的有客户,管理员,这些思考很直接,是模型,但在思考时,往往我们是先思考实体的,纯技术角度说,实体对应的是对象,但朴素的角度说实体对应的是“镜像”。客户是领域里的一个模型,那么从客户模型得到的客户1是现实客户1的什么呢?我称之为镜像(其实就是模型,更为通俗的说法而已,若果叫模型的话那么,客户就变成模型的模型)。从模型中得到的永远不是现实,但他们之间肯定有一种关系。

[该贴被SpeedVan于2011-02-13 22:29修改过]
[该贴被SpeedVan于2011-02-14 09:59修改过]

主要的观点,如果可以理解,就不纠结了。

1)用户不是角色,可以扮演角色,用户与角色的关系可以理解为多对多的映射,但我认为其相对独立的意义更重要,更值得强调。
2)领域中的其它角色,如果可以替用户进入领域将扮演的角色完成其职责,就可以将用户所扮演的这一角色从领域中去掉;如果不能则保留用户进入领域时将扮演的角色。

邮箱替用户收发邮件,杯子替用户盛水,借书卡替借书人书写借书记录,自动取款机替业务员执行业务规则。只要不是用户最根本的需求,用户进入的领域的角色都可以由其它角色代劳。比如喝水、吃饭、看书,至于盛水、买饭或做饭、借书或买书,都是可以由其它角色代劳,
或者说使用其它角色来完成职责。

其余的细节问题,比如交易涉及的利益关系、相似例子的类比,前面的帖子应都有所解释,如果没有,也算了。看帖的、顶贴的,如果有其它方面的高见不妨也说出来,确如banq所言,不再纠缠这个细节问题了。

2011年02月14日 21:34 "jdon007"的内容
都是可以由其它角色代劳,
或者说使用其它角色来完成职责。 ...

是的,原来的观点差别是在这里,我们论点也扯远了。我之前就说到了,其他角色来代劳,即是我之前所说到的拟人化,也未尝不可(Card与Reader是同一个概念——行为执行着)。只不过,我认为更直接地认为是客户,借书人这样的参与者,可以避免因为“使用”所带来的绑定。客户,借书人这些角色是领域中肯定存在的,而使用的东西缩小了模型的适用范围。缩小范围也没错啊,因为它一样能够准确表达该系统模型。

时隔半年,一些看法已经有所改变。比如对DESC的认识已经发生了极大的变化,将部分观点放在这里,作为修正和补充。

一般情况下,getter/setter是针对实体的单个属性,而对值对象的getter/setter是针对实体的多个属性。
为什么要对实体的属性进行分组,这要考虑实体的哪些属性是否有强烈的关联,是否可以凝聚在一起成为一个完整、相对独立于实体的概念。

《实现模式》上有一个例子,可拿来说明一下为什么可能需要值对象?

比如金融票据的数值与币种会同时变化,那么这两个字段最好放到一个辅助对象Money中:


setAmount(int value, String currency) {
this.value = value;
this.currency = currency;
}

上面这段代码就变成了:


setAmount(int value, String currency) {
this.value = new Money(value, currency);
}

然后进一步调整:


setAmount(Money value) {
this.value = value;
}


值对象是DDD(广义上,是一种设计模式)的一个概念,在分析模式中对应的概念是四色原型中的DESC,在实现模式中对应的是变化率实现原则,即把具有相同变化率的逻辑、数据放在一起,把具有不同变化率的逻辑、数据分离。

值对象数据一致性,是变化率原则的必然结果;不变性,则看值对象需要共享。

《领域驱动设计》这本书,行文风格是深入深出,没有做到平易近人、浅显易懂。四色原型(彩色UML)和实现模式那两本书还写得浅显一些。一个概念,最好能从分析、设计、实现三个维度,去理解它,这样可能容易些摆脱思维的困境。

此外,个人认为四色原型的DESC相当重要,把它对应为DDD的值对象,没有完全呈现它的内涵,上述的解释,也只是其丰富内涵的一鳞半爪。

我心中的四色原型(与彩色UML那本书的定义相比已有所变化,确切地说已经演变成一种系统观,与《易经》象、数、理一样,成了自己内在的认知语言)比DDD、DCI、MVC、CQRS、EDA的内涵都要丰富,这些所谓的设计模式或架构模式都没有完整地表达四色原型。

DDD缺少了Role这一概念,也许可以通过聚合根来差强人意地顶替;DCI和MVC缺少了DESC概念的支持;CQRS、EDA更是缺胳膊少腿,在概念完整性上几乎不值一提,当然其在局部的应用还是非常价值,比如消息分类(cqrs分为:命令、查询)、消息传递(eda:异步、同步、单播、广播等)。

唯一的例外,就是REST架构风格,其设计完整地呈现了四色原型分析模式的所有内涵,是一个非常成功的案例。分析模式最为抽象,设计模式是对分析针对某个应用的具体化(比如REST除了体现四色原型的固有内涵,还考虑诸多架构约束),实现模式是设计的实例化。

关于Value Object的更多论述,可以参照VO的一些个人认识。和本贴上面的一些讨论一样,大多是未经仔细整理的思考,有些凌乱和枯燥,关于Value Object banq和SpeedVan的论述我明白,但你们似乎不太赞同我的观点,不争论了,因为我现在尝试提出一套更浅显的建模原语,来诠释我的领域建模观。

前几天,还打算从系统的角度去解释四色原型(分析模式)、领域驱动设计(设计模式),发现这种做法可能会比较枯燥,放弃了。

现在,结合隐喻的方式,看是否能将两者解释得通俗易懂,并且提供一组领域建模的原语,作为分析、设计、实现阶段的通用语言。

大家先回想熟悉的画面:
1)花木兰从战场凯旋归来,辞去将军之职,脱下戎装,现出女儿身。
2)花木兰战场上英勇作战,披上戎装,行将军之职,无人知晓是女儿身。

四色原型的描述:戎装是Desc,花木兰是PPT, 将军是Role,作战是MI。
DDD的描述:戎装是Value Object, 花木兰是Entity, 将军是Aggregate, 作战是Service。
DCI的描述:花木兰是Data, 将军是Interaction, 作战是Context。
生活化的描述:戎装是“道具”,花木兰是“演员”,将军是“角色”,作战是“剧本”。

在上面的分析之上,提出四个建模原语:

状态特征(state feature), 别名特征(feature)。
模型(model),别名实体(entity),事物(thing)。
行为特征(behavioral feature),别名角色(role)。
场景(context),别名服务(service)、活动(activity)。

模型是领域的核心。
状态特征是从模型(model)上剥离的具有“一致性”的状态特征。
行为特征是从模型(mdoel)上剥离的具有“交互性”的行为特征。
场景中模型将“剥离”的状态和行为特征重新“凝聚”起来,相互作用,完成任务。

--------------------------------------------------------
采用这套建模原语从新设计“图书馆”这个案例。

0) 工厂:CardFactory
----------------------------------
1)模型: Libarary, Card, Book
2)状态特征:CardType、BookDetail
3)行为特征:BorrowedBook
----------------------------------
4)场景:BorroweBook、BorrowedBookReturn、BorrowingIterm

模型,将现实中最核心的事物自然映射到领域模型中。

状态特征的剥离,看模型的部分属性是否具有“一致性”。上面的CardType, 剥离的有必要,但BookDetail则没有明显的业务需求,可以不剥离。

行为特征的剥离,看模型的部分行为是否具有“交互性”。BorrowedBook实际上并不表示“交互过程”,而是“交互结果”,但能反映“交互”特征,所以实现时可这样表达。

场景:BorrowingTerm包含场景的前置条件、交互约束,体现业务规则。DDD的术语好像是规约(Specification),是一种深层次的重构。之前我几乎无意识地把“借阅规则”放在一块,看来是对了。


参与场景时,如果模型符合场景的规约,模型就会凝聚剥离的特征—状态特征(根聚合)和行为特征(扮演角色),成为真正的“对象”,“对象”在彼此之间形成的关系网络中传递消息(可采用事件驱动),完成任务。

--------------------------------------------------------

总结一下建模过程:

1)从业务中将最核心的事物自然映射为领域中的“模型”。
2)从“模型”上剥离出状态特征和行为特征,剥离的基本角度是“一致性”与“交互性”。
3)根据在场景中业务规则,“模型”重新凝聚剥落的“特征”,成为真正的“对象”。
4)“对象”之间相互“传递消息”,完成任务。

不知道banq是否赞同我提供的这套“术语”:模型/事物、状态特征、行为特征、场景/活动。我觉得这套术语非常浅显,甚至可以给对DDD、DCI、四色原型一无所知的人讲,应该可以在很短时间内就可以懂个大概了。如果banq赞同,不妨将其推而广之,消除了术语上含义的不一致,我们交流起来更流畅,可以腾出更多的时间,去探讨更深入、更细微、更优雅的实现手段。

VALUE OBJECTS are instantiated to represent elements of the design that we care about only for what they are, not who or which they are.

这是VALUE OBJECTS的定义,我很欣赏这个定义,这才是VALUE OBJECT的内涵,不变性与一致性都是其外延。这点上我与banq的看法完全一致。

只是SpeedVan一值强调不变性才是VALUE OBJECT的本质,所以我必须引入“时间”这个概念来解释清楚。

VALUE OBJECT实际上表示事物或系统的特征,特征普遍意义的数学描述是一组时间函数。这组时间函数具有相同的变化率时,特征就具备了一致性;这组时间函数是一个恒等变换式时,特征就具备了不变性(常数特性)。

但banq说Value Object是名词“静”物,这点我不完全赞同,Value Object实际上是名词“动”物,从上述的VALUE OBJECT的数学描述就可以看出来。

1)面向类(抽象的对象),不是真正的OO, 面向对象(静态的对象),也不是真正的OO;类+对象+时间,才是真正的OO。

2)关系代数,关系的定义不是指外键,外键只是外部对关系一个字段属性的约束而已,字段属性有很多种约束,外键只是其中一种。

3)关系的数学描述是一个集合,在OO中,等价于“类及其所有对象之和”。关系运算,即对“关系”的操作,是真正意义上对“对象”的操作。

4)目前的数据库没有时间观,目前的OO也没有时间观,但是关系代数,有!

5)GoF设计模式没有时间观,其灵感源于《建筑的永恒之道》,建筑是一个空间艺术,永恒试图超越时间,即追求特征不变性。

6)没有时间的OO世界观中,状态共享是并行之道;在有时间的OO世界观中,状态共享只是一种特例,消息传递才是并行之道。

7)掌握并行编程,最好能掌握爱因斯坦的广义相对论,在物理意义和数学意义上深刻认识时间和空间,如果不能,也要尝试去了解,因为并行
编程实际上是时空观在计算机上的落实。

8)数学是一个伟大的学科,是所有学科中最“无为”的一个学科,为其他学科提供必要的工具,可谓“利万物而不争”。不要去批判数学思维
,要去批判那些对数学有误解和偏见的思维。因为“无为”,数学“无所不为”,被人封为“无冕之王”,功高震主,“哲学”的霸主地位岌岌可危。但“数学”本身并不想争夺“帝位”,是它的崇拜者,要把它推向至尊的王位。“数学”的崇拜者,想通过让“数学”登上宝座,来获取更多的荣耀与话语权,但忘记了“数学”崇尚“无为”。

9)比如,数学上一个矩阵,可以是一堆无意义的数据的堆积,可以是一幅图像的表示,可以是一个电路的描述,可以是一个化学反应方程组的
表示,可以是一个网络的描述,可以是一个系统的描述,... 这就是“数学”,“无为”而“无所不为”。

10)我喜欢数学,但不是数学的崇拜者,更不想通过让“数学”登上宝座,使自己获取更多的荣耀,因为“数学”根本不在乎这个“宝座”,那是其崇拜者自己心中的欲望而已。

11)我也喜欢领域建模,也试图提取一套建模原语。这个帖子,就是开始做这个尝试,关于实施的细节,需要更多的思考和讨论,我会先写一部分,抛砖引玉。

2011年07月28日 21:54 "@jdon007"的内容
不知道banq是否赞同我提供的这套“术语”:模型/事物、状态特征、行为特征、场景/活动。我觉得这套术语非常浅显,甚至可以给对DDD、DCI、四色原型一无所知的人讲,应该可以在很短时间内就可以懂个大概了。 ...

我很赞同,这是一种角度,揉合了象数思维,容我有时间深入沿着你的思路考虑一下。

每个人的建模思路和他的接受知识的背景是有关系的,实际也是模型和Context一种依赖关系,建模如果一定要统一语言,是否会造成大家都钻在一个角度里出不来呢?多角度多思路有时比某种角度著名的方法如DDD更重要。事物只有从多角度才能全面认识。

先说说REST为什么是一个成功的案例?其根本原因是REST架构中的核心概念“资源”是时间函数,表征真正的事物或对象。

当然其设计包含诸多约束和实施的细节问题,目前我还没去分析。这是一个极好的建模案例。我将花时间使用上面的建模原语,对其进行仔细剖析,提炼出使用这套建模原语更详尽的一般思路。

先说说,一些关于在场景中模型凝聚“状态特征”和“行为特征”的思考,以后会更多的论述。

1)在复杂的场景中,模型对状态特征的凝聚,可能需要使用结构型模式;对行为特征的凝聚可能需要使用行为型模式。
2)比如,使用组合和修饰器模式去凝聚一些状态特征;使用命令和观察者模式去凝聚一些行为特征。
3)模型的创建可能需要使用创建模式,比如Card,使用CardFactory进行创建。
4)特征的创建也可能需要使用创建模式,比如行为特征(角色)在诸多场景中类似时,就需要使用“动态代理工厂”进行创建,控制特征类的数量的膨胀。

关于REST,我提议看看http://www.iteye.com/topic/82227,当然还有很多,我只是放个引子,希望能引发你思考。

关于值对象或特征的一些论述补充。

VALUE OBJECTS are instantiated to represent elements of the design that we care about only for what they are, not who or which they are.

看来你还是没有理解这句话(这是书中的定义呀),就拿合同这个的例子,balance是一个VO,为什么呢?因为除了contract,order也可以有balance, bank card也可以有balance, 这是值对象:只关心是什么,不关心它们是谁或者是哪一个。

再比如,花有颜色,衣服有颜色,颜色就是一个特征或者值对象;花是红色的,衣服是红色,红色也是一个特征或者值对象,只是此时特征是一个常量而已。

状态特征可以从模型上剥离,正如行为特征可以从模型上剥离,在场景中根据业务规则进行凝聚,成为真正的对象。

比如,I(t) = 2t+3,也是一个特征,可以用来描述交流电,也可以用来描述位移,甚至一条直线,特征的具体指向哪一个模型,在场景中凝聚时,自然确定。比如我们在讨论电流,它就是指交流电的特征;我们在讨论解析几何,它就是指直线的特征。

摆脱锁,不是值对象的目标。锁是多线程环境下,状态共享时的一种保护状态机制。任何东西只要具备不变性,就可以去掉锁,这跟是否是值对象一丁点都没有关系。消息传递并发因为没有状态共享这一说,所以天生就不需要锁,摆脱锁更谈不上是其目标。

关于值对象我已经尽力说清楚了,如果你还是有不同的看法,我也没辙了。我也已经舍弃了值对象这个概念,取而代之使用“状态特征”来描述。