数据、事实、实体、值对象、事务、不变性

数据有两个重要属性:首先数据是基于时间的,数据是表达一段时间内一个逻辑为真的事实。另外一个属性是数据本质上是不可变的,因为和时间有关,我们是不能回到过去改变数据的真实性。这两个属性就意味着:对数据你其实只有两个主要的操作:读取现有数据,并(随着时间)添加更多新的数据,CRUD(增删改查)称为CR(增读)。这样,CRUD其实没有U修改,因为修改对不可变数据是不其作用的(非常类似DDD中值对象不可变,不能修改,只能更换)。CRUD中也没有删除Delete,其实大部分删除其实是一种创建新数据,如果Bob停止跟随Mary,但是他们不能改变他曾经跟随过他的事实,删除那个他不跟随她的数据,你会增加一个数据记录,说他在某个时刻不再跟随她了。

其实状态变化有两种思维:一种是过程形式,一种是逻辑形式。

过去我们的实体都是列出对其认识的内在属性,当事件发生致使实体发生变化时,往往就是加锁后逐一改变,或者事务方式(类似副本方式)。“逐一改变”就是过程式,具体详细地描述变化过程,于是在并行的时候缺失原子性,为了实现避免脏读等问题,加锁成了一种手段。当然,事务方式也解决了这样的问题,这与非副本的不变值对象方式,是达到同样目的的不同方式,同时这两者都属于逻辑表达。以前我作过比较,在领域当中谈论逻辑变化,我认为后者较好。

值对象是实体状态的一种落实,我过去提出过的观点,这是源自于状态变化的逻辑形式思维。谈论逻辑时,状态迁移必须具有原子性,所以我在某个帖子说值对象不变性,可以达到去锁的目的。

注意:值对象不变性源自值,并非因为实体状态,是因为值对象具有值的不变性,所以才能成为实体状态的落实。

一些更深入的认识:

存在状态变化即存在副作用(side effect),所以实体是副作用存在的因。很多人认为副作用是坏的,应该去掉,但这只限于逻辑运算时。只要人们想获得信息,副作用就根本不能避免,最容易理解就是print。

可变的实体与不可变的状态,正好就是副作用存在的分界线。实体之所以会存在,其实是因为人们想获取信息,于是值对象(值)载体便出现了——引用对象(即实体对象)。

状态迁移,就是实体发生变化,它说明实体从一个状态迁移到另一个状态。这里面最小单元是状态,也就是说我们考虑的不是状态的构成及其内在变化(逐一改变),而是计算出新状态,然后以“替换”的手段来实现实体变化。这与我们所说到的值对象不变性和事实是最小单元如出一辙。(所以“状态迁移”是一种事实观)

状态是表达一段时间内一个逻辑为真的事实,这句话很好说明了事实观与实体观的联系。

过去我思考“什么是实体”,其实实体很简单,就是一个KEY,是为了区别与其他存在的存在。而我们写类的时候,其中的id并非实体KEY,而“类名+类id”才是实体KEY。所以关系数据库中表方式与类方式类似,并不完全满足事实观,而key-value数据库能更好展现逻辑。关系数据库的数据平铺方式,使得查询速度极快,同时实现了逻辑查询,但这并非从实现“产生事实的逻辑”角度出发的——事件的角度。

immutable is eveything,不可变是一切。

状态变化是由事件引起的,从事件来划分。

The immutability exists not for the sake of itself. Immutability is abstraction. It does not "exist" in nature. World is mutable, world is permanently changing.....

一、

其实这就是一种“连续”和“离散”思维的区别,尽管世界在我们感官中是连续的,但连续过程和中间的“切面状态”不是我们关注的,业务说的是规则,是逻辑的,正如我们经常说的“业务逻辑”。在规则或者逻辑中,不存在所谓的切面状态。例如“借书”这一个原子动作,有人会“借一半”,或者说“借一半”是我们所关注的状态?

二、

若果我们一个个地改属性,当改了第一个属性值,没改第二个属性值时,这就存在了所谓的切面状态。单线程时,因为顺序执行,不会读出切面状态,变相成为原子操作,但多线程并发时,读出无效的切面状态是可能的。解决的方式:

1)改的时候不能读,就是我们以前用得最多的锁;

2)随时可读,改的时候必须“同一时间”完全改完,而这就是不变性的整体替换;

3)当然后来又想到一种,读与改不会同时进行,暂时感觉比较复杂,没有深入,浅思考了下,感觉实时相对较弱。

三、

还有一点,事务性和不变性,个人认为两者很像,但又有点不同:

事务讲究复制隔离,达到不相互影响,而且最后也需要替换。

不变性无需复制,因为其一开始就要求在逻辑运算期间是“不能改”。

两者相似点:

1)并行时都是相互不影响;

2)更新时都是替换手段。

不同点:

1)事务的参与逻辑是在逻辑执行前就复制好,得到隔离性;事务包装整个过程,实现原子性。

2)不变性方式的“结果对象”是在逻辑执行完后,根据各种条件创建的,其原子性体现在替换,并不是包装过程。

总的来说就是一前一后,事务有点像“平行世界”的概念。还有有趣的一点是,不变性前后两个状态不要求是同构的。不变性还有很多有趣的地方,这里就不一一列举了。而不变性也有缺点的,如要多对象同时改变时,需要机制来处理。

为什么有这样大统一美妙大道至简的现象呢?因为计算机软件系统是本身是符号逻辑或者形式逻辑或分析逻辑的一种体现,而不变性是逻辑上的一个基础概念(蒯因与引用透明),如果你学习了分析逻辑的这个基础,你就找对了方向,但是如果你学习几十年数据结构和算法基础,你不一定能悟出其背后的逻辑真义。

VO相对的是RO(ReferenceObject),独立于“状态、实体”概念的,或者说是不同层次的。只是VO和RO出现相对较早,而且比较吻合“状态、实体”概念。所以,值对象只是状态的落实,或者说实现。

“实体状态在某个时间点上状态是静止的”,瞬时的实体状态映射到计算机就是不变的数据,在对象思维中就是值对象。而实体则是RO,不过注意的是这个引用概念有点变化,并不是引用地址,而是变成实体KEY。

值对象的不变性是源自于值概念的,试想为啥非要叫做“值对象”,而不叫“不变对象”。

时间: 2024-10-21 12:31:04

数据、事实、实体、值对象、事务、不变性的相关文章

聚合(根)、实体、值对象精炼思考总结

1.      聚合根.实体.值对象的区别? 从标识的角度: 聚合根具有全局的唯一标识,而实体只有在聚合内部有唯一的本地标识,值对象没有唯一标识,不存在这个值对象或那个值对象的说法: 从是否只读的角度: 聚合根除了唯一标识外,其他所有状态信息都理论上可变:实体是可变的:值对象是只读的: 从生命周期的角度: 聚合根有独立的生命周期,实体的生命周期从属于其所属的聚合,实体完全由其所属的聚合根负责管理维护:值对象无生命周期可言,因为只是一个值: 2.      聚合根.实体.值对象对象之间如何建立关联

DDD领域驱动设计:聚合、实体、值对象

关于具体需求,请看前面的博文:DDD领域驱动设计实践篇之如何提取模型,下面是具体的实体.聚合.值对象的代码,不想多说什么是实体.聚合等概念,相信理论的东西大家已经知晓了.本人对DDD表示好奇,没有在真正项目实践过,甚至也没有看过真正的DDD实践的项目源码,处于极度纠结状态,甚至无法自拔,所以告诫DDD爱好者们,如果要在项目里面实践DDD,除非你对实体建模和领域职责非常了解(很多时候会纠结一些逻辑放哪里好,属于设计问题)以及你的团队水平都比较高认同DDD,否则请慎重...勿喷! 代码在后,请先看D

json序列化对象后,json里面的list数据怎么取值赋给下面的“entryNode_Text”

问题描述 json序列化对象后,json里面的list数据怎么取值赋给下面的"entryNode_Text" XmlNode entryNode = xmldoc.CreateElement("entry"); XmlText entryNode_Text = xmldoc.CreateTextNode("231234"); entryNode.AppendChild(entryNode_Text); XmlNode title1 = xmldo

EJB 3.0开发指南之依赖值对象

在上面的章节我们提到,实体bean的属性可以是java基本对象.Date等,事实上,实体Bean的属性也可以是其他的java对象.这些Java对象不能直接从持久化上下文中读取,它依赖于主实体bean.不象关联实体Bean,在EJB3.0中不支持依赖值对象的集合. 依赖值对象不支持继承,这将在EJB3.1中在讨论. 依赖类需要使用◎DependentObject来注释: @Target({TYPE}) @Retention(RUNTIME) public @interface DependentO

数据-前台取值的问题。。。。。

问题描述 前台取值的问题..... 后台拼sql语句查询到的2个表的list 前台如何获取每条数据铺出来 实体类对象不能修改 解决方案 什么编程语言都不说,鬼才知道.建议你遇到这种问题,直接google输入你用的语言+前台+list取值 解决方案二: 用forEach表达式 解决方案三: 如果是在页面上解析可以用el 表达式 解决方案四: 已经解决了 只是list变量都没名字 不方便取而已 解决方案五: ckeditor取值问题 前台+后台 取值方法

innerhtml-无法设置属性“innerHTML”的值: 对象为 null 或未定义

问题描述 无法设置属性"innerHTML"的值: 对象为 null 或未定义 function getdbxx(posturl, paramstr, spanid, inputid) { $.ajax({ type : "post", url : posturl, dataType : 'json', data : 'portletConfigJson=${portletConfigJson}&'+paramstr, success : function(

关于将数据中的值作为复选框

问题描述 怎么将数据中的值作为复选框,然后可以动态的添加和删除复选框.求解啊 解决方案 解决方案二:CheckBoxList?items.add(数据库返回值);解决方案三:值作为复选框的什么??问题描述不清楚,打回重写.解决方案四:复选框实现绑定数据库并删除.更新信息//获取数据库信息加载到页面publicvoidGV_DataBind(){stringsqlstr="select*fromtb_inf";sqlcon=newSqlConnection(strCon);SqlData

数据类型-通过类反射获取实体类对象

问题描述 通过类反射获取实体类对象 private String[] colName = null; // 属性名数组数组 private String[] colType = null; // 存放实体类的数据类型 如java.lang.Long private String[] colValue = null; // 要存进去的值 请问一下我有一个实体类 要把colValue里的数据以colType类型存到TbUser实体类的属性里 并且返回这个实体类 的对象 请大神给个思路 ... 多谢

Java---设计模块(值对象)

场景和问题 在Java开发时,需要来回交换大量的数据,比如要为方法传入参数,也要获取方法的返回值,该如何能更好的进行数据的交互? 基本的编写步骤 ◎第1步:写一个类,实现可序列化(如果以后数据是往数据库里存的,那么可以不序列化,节省资源) ◎第2步:私有化所有属性,保持一个默认构造方法(public无参) ◎第3步:为每个属性提供get().set()方法(如果是boolean型变量,最好把get改成is) ◎第4步:推荐覆盖实现equals().hashCode()和toString()方法