欢迎光临汤雪华的博客

一个人一辈子能坚持做好一件事情就够了!坚持是一种刻意的练习,不断寻找缺点突破缺点的过程,而不是重复做某件事情。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

建模原语:四象图

Posted on 2013-06-27 13:09  netfocus  阅读(4414)  评论(6编辑  收藏  举报

原文地址:http://www.douban.com/note/164191021/

“模型、状态和行为特征、场景”和“四象图”,建模观的命名与立象。


建模原语:四象图

作者:achieveidea@gmail.com

命名:模型、结构特征、行为特征、场景(及其规约)。

释义:
模型,描述事物为一组时间函数,蕴藏了与事物相关的所有事实。
特征,从模型上剥离的一组时间函数。特征分为两大类,一类是结构特征,一类是行为特征。
场景,模型凝聚相应的特征持续一段时间,描述一段时间内与模型相关的事实。场景中隐藏的一些规则、约定,称之为场景规约。

用法:
一笔一纸,一横一竖,四象顿生。
一象画景,三象画物,物在景中。
二象画形,四象画神,形神兼备。
万象入画,浑然一体,一目了然。

注:第一象限画景,即描述场景;第三现象画物,即描述模型。第二现象画物之形,即描述模型的结构特征;第四象限画物之神,即描述模型的行为特征。


诸子百家:
如果你熟悉四色原型,DESC可理解为结构特征,PPT可理解为模型,Role可理解为行为特征,MI可理解为场景。
如果你熟悉DDD, VO可理解为结构特征,Entity可理解为模型,Aggregate可理解为行为特征,Service可理解为场景, Specification可以理解为场景规约。
如果你熟悉DCI,D可理解为模型,C可以理解为场景,I可以理解为行为特征。
如果你熟悉MVC, M可理解为模型,V可理解为结构特征,C可理解为行为特征。
如果你熟悉Web,HTML可理解为模型,CSS可理解为结构特征,JS可理解为行为特征,“页面”可理解为场景,HTTP可理解为场景规约, URI可理解为场景的命名。
如果你熟悉Database, Table可理解为模型,View可理解为结构特征,Trigger可理解为行为特征,“增删改查”可理解为场景,SQL(关系代数)可理解为场景规约。

如果你对上述诸子百家的解释一无所知,恭喜你!你可能将在最佳的状态下,快速掌握四象图的精髓。

为了有一个感性的认识,以电影为隐喻。Actor(演员)表示模型,Props(道具)表示结构特征,Role(角色)表示行为特征,Script(剧本)表示场景。电影《英雄》中的陈道明是模型(演员),龙袍是结构特征(道具),秦始皇是行为特征(角色),刺伤秦始皇片段是场景(剧本)。
最后也会有两个简单的代码案例(都源自Jdon道友提出的案例),让你初步感受一下四象图的作用。


开放课题:
1)描述原语的具体语言
静态语言,动态语言?命令式语言,声明式语言?Web给我们树立了一个极好的榜样,模型使用HTML描述,结构特征使用CSS语言描述,行为特征使用JavaScript描述,场景规约使用HTTP描述,场景使用URI命名。事实上Android UI就汲取了Web的灵感,将UI的模型及结构特征使用XML描述。

2)特征剥离的方法
如果特征与模型使用同一种语言(比如Java),结构特征和行为结构的剥离需要付出额外的精力,比如前者侧重“一致性”,后者侧重“交互性”。而在Web中,结构特征和行为特征的剥离易如反掌。一致性要求画面在一段时间呈现相同的风格,这将给用户良好的界面体验的必要基础。CSS的设计者之一Bert Bos,解释了为什么CSS高度强调一致性。
Why “variables” in CSS are harmful?

3)特征凝聚的方法
模型凝聚特征,最简单的方法就是赋值。当模型具有复杂的结构特征时,可以使用“结构型”模式进行凝聚;当模型具有复杂的行为特征时,可以使用“行为型”模式进行凝聚。 凝聚特征的方法远不止赋值和GoF模式,比如JQuery中的selector、 Android中的R.java等等。

4)语言引擎的设计与实现
在不同的“系统”或“层次”之间,可能需要引入“语言引擎”这个概念,语言引擎的工作主要是协调两个说不同“语言”的“系统”之间的信息交流。比如Web应用的前端客户端说的是JavaScript语言,后端服务器使用是其它的语言(比如Java, PHP等)。Ajax(Asynchronous JavaScript and XML,由Jesse James Gaiiett发明)引擎负责两者的信息交流。Ajax的本意是通过JavaScript启动引擎,发送Request,异步接收以XML的数据格式返回的Response。现在XML已逐渐被JSON取而代之,因为相对于XML, JavaScript天生对JSON非常熟悉,是自家兄弟。

这里我修改Ajax的含义使其具有普适的意义。A = asynchronous, J = jabber, A = And, X = X。A 表示异步(同步是异步的特殊状态),Jabber的含义是“快而含糊不清的话”,X代表是任意对话者将的语言。

当某个层次或系统说的语言(Jabber),对于另一个层次或系统(使用X语言)而言可能就是“快而含糊不清的话(Jabber)”(我们多数人听老外讲话不就如此?老外听我们说话亦然!),此时就需要一个“语言引擎”进行翻译,使两者流畅地交流。语言引擎有两个工作模式:异步模式和同步模式。

对于Web UI来说,JavaScript为了自己的话能够被服务器(比如使用Java编写的服务器)听懂,使用Ajax语言引擎告知自服务器自己说了啥,要做什么。

对于Web Server(比如Java编写的服务器),为了Database能够听懂自己的话,知道自己想要些什么,做些什么,也需要构造一个Ajax引擎。语言引擎如果足够智能,可自动切换工作模式。比如在同步工作模式下,与SQL数据库建立会话;在异步工作模式,与NoSQL建立会话。

语言引擎的设计者需要具备精通数据库语言和服务器使用的语言,才可能建立通用的语言引擎。这个有能力的人可以考虑怎么实现,将其开源奉献给社区。 我目前是不知道啦。语言引擎不是Object/Relation Mapping,多多借鉴Asynchronous JavaScript and XML才是正道。

5)架构风格的设计与实现
Roy Thomas Fielding的博士论文《架构风格与基于网络的软件架构设计》是一篇极好的文章。李锟、廖志刚、刘丹、杨光的翻译也非常到位,感谢他们无私的奉献。我提出四象图的灵感部分(模型)源自于这篇论文对“资源”的定义,还有一部分灵感(特征)源于曾经对系统“特征向量空间”的痴迷。

Fielding在文中提及,“更精确地说,资源R是一个随时间变化的成员函数MR(t),该函数将时间t映射到等价的一个实体或值的集合,集合中的值可能是资源的表述和/或资源的标识符。”“REST对于信息的核心抽象是资源。任何能够被命名的信息都能够作为一个资源。”

在四象图中,Resource犹如“凝聚特征的模型”; Representational State表示“模型进入的场景”; State Transfer Protocol表示“场景的规约”;URI则是对“场景的命名”,其应绑定恰当的语义。

四象图与REST描述具有相似的“画面感”。 资源的表述性状态是一个持续一段时间的画面,状态转移协议切换各个画面。模型进入场景持续一段时间的画面,场景规约切换各个画面。两者之所以,具有相似画面感,是因为模型与资源的定义都是时间函数,是一个随着时间变化的概念。

体验与感受REST架构风格、四色原型、GoF设计模式,想象与其提出者进行交流,聆听、汲取其智慧,是我提出“四象图”的源泉。Web是一个成功的REST架构,运行了几十年。碰触Web,与接触TCP/IP协议栈、信号与系统、香农的信息论、机器学习一样,都令我感到震撼,开阔了原有的视野。

架构风格的设计与实现,我也是个在不断学习的初学者。之所以列出这个课题,是因为我觉得其非常重要,不可或缺。

6)程序之道:象数理
Niklaus Wirth提出公式“程序 = 数据结构 + 算法”,我认为这个公式少了一个东西,必须显现出来,即“模式”。古人有“象数理”之说,“象”在程序中抽象为“数据结构”,“数”抽象为“算法”,“理”抽象为“模式”。

“象”可以描述变量,过程,对象,函数,进程,事实,……,基于不同的“象”(数据结构),我们需要思考相应的“数”(算法),发现“象数”之后的“理”。这是无止境开放的课题,我们可能永远都无法找到永恒的真理。

建模原语和程序之道的来龙去脉,可以参考帖子《领域驱动设计之我见》和《Hello, World! 我心中的道》,但那两个帖子充斥着混乱和错误,有时间可以了解一下,没有时间,看这个帖子就行了。这些是我提炼、加工后的结果。

提出“六大开放课题”,因为其与“四象图”在虚拟世界中的落实息息相关。有空我会写一些特征凝聚的代码例子,作为参考。uda1341的设计的作品完成差不多了,可让他普及一下程序之道这个课题出现的新方法论:Fact-Oriented Programming。

希望有更多的人,了解和使用四象图,并对随之提出的“六大课题”感兴趣,去研究和解决他们。

欢迎转载此文。最好注明原出处。
achieveidea@gmail.com


一个中心,两个基本点。即以“模型”为中心,以“特征”与“场景”为两个基本点。

模型,描述事物为一组时间函数,蕴藏了与事物相关的所有事实。
特征,表示描述观察事物的角度,主要有两个角度:状态(结构)与行为(功能)。
场景,表示使用哪些角度观察和使用模型(模型凝聚特征),描述特定时间内所有与事物相关的事实。

MVC和DCI的提出者Trygve Reenskaug提倡用可读性极佳的代码直接捕获用户心中的模型,我采纳了这个观点,同时在编写原型时借鉴了四色原型及DCI的部分思想。

这里先陈述我的一些思考和观点,可能与一些经典著的定义有所出入,随后再将代码贴出来。

1)领域是客观的,不以人的意志为转移,但人之于领域具有能动性,可以认识和改造它。
2)领域模型是主观的,体现了程序员对领域的认识,是程序员心中对领域的素描。
3)用户需求是主观的,体现了用户对领域的认识,是用户心中对领域的素描。
4)领域模型需要捕捉和包容用户需求。领域模型与用户需求的关系十分重要,下面展开来讲。


“用户需求”是对领域的“素描”,用户的需求来自对领域的“诉求”,这些诉求往往是深刻的,因为其来源于用户对领域长期观察和使用的经验,比起我们程序员,一般更完整、更真实地接近领域的本质。我们对“用户需求进行素描”,就是“借鉴用户的宝贵经验”,可以更快、更好地素描客观领域,这可以说是一条认识(未知)领域的捷径。但是当用户需求不明朗或不清晰时,我们需要超越“用户需求”,对领域进行深入的摸索,去寻求更清晰的视角,对领域进行刻画。

此外,“用户需求”不能等同于“用户”,捕捉“用户心中的模型”也不能等同于“以用户为核心模型”,这是不同的概念,不能忽略其差异。《老子》书中有个观点:有之以为利,无之以为用。在这里,有之利,即建立领域模型;无之用,即包容用户需求。举些例子,一个杯子要装满一杯水,我们在制作杯子时,制作的是空杯子,即要把水倒出来,之后才能装下水;再比如,一座房子要住人,我们在建造房子时,建造的房子是空的,唯有空的才能容乃人的居住。我们建立领域模型时也要将用户置于模型之外,这样才能包容用户的需求。

现在尝试提出一套更浅显的建模原语,来诠释我的领域建模观。

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

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

大家先回想熟悉的画面:
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)“对象”之间相互“传递消息”,完成任务。

--------------------------------------------------------
1)面向类(抽象的对象),不是真正的OO, 面向对象(静态的对象),也不是真正的OO;类+对象+时间,才是真正的OO。
2)关系代数,关系的定义不是指外键,外键只是外部对关系一个字段属性的约束而已,字段属性有很多种约束,外键只是其中一种。
3)关系的数学描述是一个集合,在OO中,等价于“类及其所有对象之和”。关系运算,即对“关系”的操作,是真正意义上对“对象”的操作。
4)目前的数据库没有时间观,目前的OO也没有时间观,但是关系代数,有!
5)GoF设计模式没有时间观,其灵感源于《建筑的永恒之道》,建筑是一个空间艺术,永恒试图超越时间,即追求特征不变性。
6)没有时间的OO世界观中,状态共享是并行之道;在有时间的OO世界观中,状态共享只是一种特例,消息传递才是并行之道。
7)掌握并行编程,最好能掌握爱因斯坦的广义相对论,在物理意义和数学意义上深刻认识时间和空间,如果不能,也要尝试去了解,因为并行
编程实际上是时空观在计算机上的落实。
8)数学是一个伟大的学科,是所有学科中最“无为”的一个学科,为其他学科提供必要的工具,可谓“利万物而不争”。不要去批判数学思维,要去批判那些对数学有误解和偏见的思维。因为“无为”,数学“无所不为”,被人封为“无冕之王”,功高震主,“哲学”的霸主地位岌岌可危。但“数学”本身并不想争夺“帝位”,是它的崇拜者,要把它推向至尊的王位。“数学”的崇拜者,想通过让“数学”登上宝座,来获取更多的荣耀与话语权,但忘记了“数学”崇尚“无为”。
9)比如,数学上一个矩阵,可以是一堆无意义的数据的堆积,可以是一幅图像的表示,可以是一个电路的描述,可以是一个化学反应方程组的表示,可以是一个网络的描述,可以是一个系统的描述,... 这就是“数学”,“无为”而“无所不为”。
10)我喜欢数学,但不是数学的崇拜者,更不想通过让“数学”登上宝座,使自己获取更多的荣耀,因为“数学”根本不在乎这个“宝座”,那是其崇拜者自己心中的欲望而已。
11)我也喜欢领域建模,也试图提取一套建模原语。这个帖子,就是开始做这个尝试,关于实施的细节,需要更多的思考和讨论,我会先写一部分,抛砖引玉。


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

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

我尝试提出的这套原语意图在“分析、设计、实现”三个阶段通用,分析人员、设计人员、实现人员可以很自然地理解它,使用它。

这里解释一下定义这套术术语背后的思考过程。

1、模型,是事物的含义。但事物这个概念太广泛了,不宜直接拿来用,就像在REST中,使用资源这个词去代替事物,事物可作为别名。

那么为什么不选择DDD的Entity、四色原型的PPT或者DCI的Data呢?因为我们是在创建一套建模原语,最核心的概念自然要与模型有关,除了“模型”,我实在想不出更贴切的词汇了。模型,是建模的根本。

2、特征,描述事物(模型)具有怎么样的特点。特征既具有生活化的气息,也是一个在被各种学科广泛使用的术语,浅显而深刻。

比如矩阵轮、系统论上,特征向量、特征值、特征向量空间是出现频率极高的词语,常用于描述各种系统。我们使用特征来刻画、描述我们的模型。这里DDD的Value Object, 四色原型的Description,在直观上,在深刻性上,都远不如这个词汇。

3、场景,这也是一个生活化的语言,需求分析时,经常会有这个说法,有哪些业务场景。场景是一种活动,但活动与事物一样,太广泛了,只能作为别名。

这三个词汇,我个人觉得很好,因为它们既直观,又具有深刻性。

4、特征,分为状态特征和行为特征,代表从“状态”和“行为”两个维度去观察“模型”,它们是从“模型”身上剥离出来的,除了它们本身具有独立性和可复用性,更为重要的是使“模型”更为精炼。

5、在场景中,“模型”凝聚与此时此景有关的“状态特征”和“行为特征”,成为一个活生生的对象,与其他对象进行交互,完成任务。

这套原语的数学描述。
1)模型,表示为一组时间函数,包含状态特征和行为特征。
model = {f1(t),f2(t),...};
2) 特征,从模型的一组时间函数中,提取相对独立的状态特征和行为特征。
state = {f1(t),f2(t),...};
behavior = {f1(t),f2(t),...};
3) 场景,在场景模型凝聚特征持续一段时间(如从t0时刻到t1时刻)。
context => model-state-behavior = {f1(t0->t1),f2(t0->t1),...}。

借鉴四色原型的形象思维,使用四个原语。
在一张纸上画一个四象图,一横一竖的笛卡尔坐标平面。
1)把领域中的核心事物映射到四象中,放在第三象限,作为模型;(可以涂上绿色)
2)把领域中的业务场景映射到四象中,放在第一象限,作为场景;(可以涂上红色)
3)考虑所有场景,将模型的行为特征剥离出来,放在第四象限;(可以涂上黄色)
4)考虑所有场景,将模型的状态特征剥离出来,放在第二象限。(可以涂上蓝色)

不太一样,我的出发点是以“模型”为中心,以“特征”与“场景”为两个基本点。拿那个花木兰的例子分析一下。

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

分析过程,设计过程,实现过程将呈现高度一致。
1)很容易识别出“花木兰”是“模型”,放在“四象图”的第三象限,涂以绿色;
2)很容易识别识别在战场“作战”是“场景”,放在“四象图”的第一现象,涂以红色;
3)从“花木兰”这个模型身上剥离出“状态特征”,即“戎装”,放在第二象限,涂以蓝色;
4)从“花木兰”这个模型身上玻璃出“行为特征”,即“将军”,放在第四象限,涂以黄色。

再分析一下图书馆这个领域中的借阅场景,读者是不在这个图书馆领域中的,读者是图书馆领域的使用者和观察者,是图书馆领域模型的用户。

1)图书馆、图书卡、图书,是“模型”,放在“四象图”的第三象限,涂以绿色;
2)卡的类型,表征“状态特征”,放在“四象图”的第二象限,涂以蓝色;
3)被借阅的书,表征“行为特征”,放在“四象图”的第四象限,涂以黄色;
4)借阅场景、借阅规则,是场景,放在“四象图”的第一想象,涂以红色。


“四象图”不同于四色原型的画图方式,与UML的画图的角度差别更大。这是这套原语的“象”;如果具备一定数学常识,可以理解这套原语的数学描述,即“数”;实际上也可以从“理”即纯粹逻辑的角度来剖析这套术语,这个我着墨较少,毕竟“理”隐藏在“象数之中”,要解析出来,需要借助一些逻辑观并探讨世界观,这可能会使这套原语失去“亲和力”,所以暂时先不多说。

这套原语对分析人员、设计人员、开发人员都具有“亲和力”,甚至对于外行都具有亲和力,容易理解,“四象图”,这个工具,可以让他们几乎不用思考(不思考是不可能的,只能说解放了一部分脑力)就可以进行分析、设计和实现。如果能理解其数学描述,理解其背后的逻辑观,那当然更好,但不会太影响“四象图”的使用。

所以,“模型、状态和行为特征、场景”和“四象图”,可以视为对建模观的命名与立象,浑然一体而泾渭分明,强调了模型的整体观和动态性,不像UML将模型割裂为类、状态图、交互图、用例等等,而且UML的状态图与交互图不能直接落实为代码,而状态特征与行为特征可以,两者实际上是不能等价视之的。

四象图的整体性和动态性,体现在用一张图形象描述了领域中可能出现的所有静态或动态的画面;模型、状态特征、行为特征,横跨整个领域;场景根据业务规则(规约)选取模型,模型在此时此景内,凝聚了相关的状态特正、行为特征,进行协作,完成任务。

与四色原型看起来很像,但背后的思考却已经发生变化了。

1)这套原语的核心是以“模型”为中心,不同四色原型或DCI以“角色”或“场景”为中心,是把“角色”以及“描述”看作模型的附属物。

2)状态特征和行为特征,是因为具有独立性,从“模型”身上剥离。战场上的花木兰身上的“戎装”(状态特征)和“将军之职”(行为特征),是可以剥离出来复用的。戎装可以别人穿,将军可以别人当。

3)行为结果可以用来反映行为特征,行为过程也可以用来反映行为特征。角色是一个名词呀,能表示行为特征?实际上角色这个概念也是行为结果呀。行为特征的刻画方式,可以通过“角色”(行为结果),也可以通过“(时间)函数”(行为过程)来刻画。

4)场景是在一段时间内,模型根据业务规则凝聚相关的特征(披上戎装(戎装不一定是当将军的人才可以穿的),行将军之职)进行作战。

5)例子只是为了形象说明,便于大家理解。如果你看看数学描述,理解起来应该就不会有什么困惑了。

6)忘记四色原型、DCI、DDD等琳琅满目、层出不穷的词汇吧,提出这几个原语的一个目标就是希望消除这些buzzword,为大家腾出更多的时间和精力思考更优雅的技术实现。

这个不是角色,是一个活生生的对象,角色是行为特征的抽象。

模型(花木兰)凝聚了状态特征(批上戎装)和行为(扮演了将军),成为一个活生生的对象(真正的对象),在战场上进行战斗。
不是将军(角色)在战斗,完整的描述是一个披上戎装身为将军的花木兰在战斗。

如果你把模型凝聚特征后的对象,理解为角色,实际上还是以角色为中心,还是停留在一个“抽象”的层次,在场景中,模型凝聚特征后成为一个活生生的对象,一个活生生的生命。

你说的两个过程不一样:一个是用来“刻画”特征,一个是表示模型“凝聚”特征的过程。

行为特征可以表示为一个类(比如角色、比如事件监听器),可以表示为一个函数(比如function() {}),
状态特征可以表示为一个类(比如颜色、金额),也可以表示一个函数(比如2t+3)。

特征可以有更多的表达形式,甚至我们还不知道的形式。

行为特征与状态特征的区别不在于其在表现形式,在于从模型剥离出来的角度。

状态特征考虑模型部分特征的“一致性”从“模型”上剥离;
行为特征考虑模型部分特征的“交互性”从“模型”上剥离;

状态特征与行为特征,都是模型的特征,严格区分它们不是特别重要,
倘若特征剥离从两个角度都说得通,此时区分是模型的状态特征还是行为特征就没有必要了。

特征剥离的基本目标有两个:1)复用状态和行为特征;2)使模型更精炼。

注入,是模型在场景凝聚特征的一种方式,状态和行为特征都可以。

关于模型在场景中凝聚特征的方式,简单的可以通过传参的方式。
比如把状态特征和行为特征通过作为模型的构造参数传递进去。

还可以考虑使用设计模式进行特征凝聚,比如通过模型绑定事件监听器来凝聚行为特征(观察者模式),通过组合方式凝聚多个状态特征(组合模式)。

在前面,我已经写了一点关于场景中模型如何凝聚特征的思考。

结构型模式和行为型模式分别是模型凝聚状态特征和行为特征的有效工具,可以根据场景特点,灵活选择。

从模型上剥离特征(分),模型凝聚特征(合)的方式,是一个开放的课题,我只是在方向上,考虑了个大概。比如剥离的角度,一致性、交互性;凝聚的方式,结构型模式、行为型模式等。

你可以使用这套原语重新组织你的论坛代码。我在这里开个头。

模型:帐号、帖子、论坛
状态特征:帐号类型、帖子类型、帖子状态(置顶、锁定等)、论坛状态(主题总数,帖子总数,最新的帖子ID等)
行为特征:
场景:发帖子、跟贴等

这里模型好像没有明显的交互特征,业务场景相对单一,没有剥离的必要。
假如该帐号不仅可以用在论坛,也可以用在图书馆系统中,
那么帐号的行为特征就可以剥离出来,分成两类,一个与论坛有关的,一个与图书馆系统有关的。

发现图书馆的那个例子,有问题,需要修正一下。

图书卡这个现实中的事物,在系统中的映射实际上是帐号。
图书卡是用户在现实中使用的工具,帐号是用户在系统上使用的工具。
所以把Card全部改为Account,就可以了。
而且Account上的行为特征也可以剥离,如果Account的用途不仅仅在图书馆领域上,仅仅考虑图书馆领域时就不需要剥离。

帖子与图书基本上很相似。但还是有区别,帖子没有依赖场景的行为特征,图书却有(BorrowedBook)。

行为特征,一种直白的解释就是模型依赖于场景的用途,跟之前讨论的角色很相似,在定义行为特征时,角色是作为其别名的,所以关于角色的认识仍有效。

关于特征已经写了不少,下面再写一点关于场景的思考,算是终结吧。因为我已经倾囊相赠,拿不出更好的东西了。

场景可分为两大类:查询和命令,前者是观察模型及其特征,后者是让诸多模型凝聚特征一起做事情。

场景中模型凝聚行为特征的方式,可以是EDA,或所谓的Domain Events。

这套原语也可以从MVC的角度去理解。MVC的M表示模型,VC可以理解为场景,V和C将场景分为两大类,V表示从观察模型,C表示从控制模型。

从系统论的角度看,模型与特征(结构/状态和行为两个角度)是对系统的内部描述,场景时对系统的外部描述。

外部描述可以从很多个角度进行分类,比如输出、输入;比如查询、命令;比如视图、控制器;比如读和写;比如视图和触发器;其实它们是相通的。

这套原语用于理解和学习界面设计、数据库设计、领域模型设计都是可以的。原语,承载的是一种思想,一种看事物、看系统的思想,不会在乎你用它来看那种具体的东西,比如界面、比如数据库、比如领域,因为它是建模原语,不仅仅是数据库、界面或领域的原语,只要你想用,就有用。

这套原语可以从MVC、CQRS、DCI、四色原型、DDD、EDA、Domain Events、REST等甚至更多我们都还不知道的角度去理解和使用,原语本身不会去限定使用原语的角度,更不会去限定原语具体的实现方式,因为这套原语背后的数学描述实际上是“无为”的。