关于实体和值对象
领域建模里区分的实体和值对象,其实没有绝对的分法,计算机是对现实问题的建模,建模的复杂度是要看解决问题的复杂度。模型的意义要和问题中的对象参与的业务相匹配。。
如果我们写字的笔丢了,我们要再拿一支来用,那你需要什么样的呢?如果你介意颜色,那你的需求就是再拿一个颜色一样的,如果你介意手感,就拿个型号一样的。在程序中对这样的需求做一个抽象的话,就是需求一个事物只关心它的一些属性,只要属性一样就可以满足需求,这样抽象出来的概念叫值对象。
但如这支笔是父母送的生日礼物,换一个就算看起来完全一样也不一样了,你也不会认为是同一个,就算送的那个坏了,也还是原来的那个。程序中对这样的需求认为是实体,它有生命周期,就算是属性改变了也还是原来的那个。
总结下,值对象是关心它的属性,如果属性值改变了,就认为是不同的对象,为了约束这一点,最好把值对象做成不可变的。实体关心的是生命周期,一般用不能重复的标识来标识这一点。
说到这可能会觉得一切都很明白了,但实际情况是,在现实生活中区分可能相对容易些,但要把要让计算机解决的问题分成值对象和实体就不是那么回事了。
因为计算机中所有的对象都是有限的,只要是计算机造出的对象,都能重新造出个完全一样的对象(对于计算机执行来说),举个例子,我正在做一个英语的软件,里面的生单词对象,如果当成实体当然可以,改变词义后,还是原来的单词。如果要改变单词拼写更合理的方法是要删除当前单词再新建一个单词了。但我也可以把它当成一个值对象,这样不管是改变了拼写还是词意,我都新建一个值对象。两种方式都是可行的。所以我首先要说一个观点,在计算机里没有说一定非得用值对象或实体才能做出来的东西。对于计算机来说,实体是在大部分情况下,对属性的改变不新建一个对象(除非影响到了实体的语义),只改变属性;值对象则是只要属性改变变就新建一个值对象。而且在很多情况下,很难抉择。如果通过业务(也就是现实世界)就能判断出来那是最好了,如果通过业务很难判断,因为有些东西在现实世界也很抽象。比如我的系统里的生词。
有一个在现实里很难区分时,怎么在计算机编程世界里区分的方法。成本分析法,可以先假设设计成值对象,值对象都做成不可变的。再考虑改变的情况多么,改变属性,就新建一个值对象,如果属性总变,而且对象很复杂,那么你当然会觉得每次因为一点改变就得重新建立一个对象,还得删除原来的对象太麻烦了,显然实体更适合。
总结下,实体比值对象的复杂,如果值对象就可以满足需求,就不要使用实体。
好不容易算是清楚一点了,想着想着又糊涂了,还是上面单词的例子,如果我只是想修改不想有重新创建对象的开销,我就让值对象可变不就可以了。又何必要让它为实体。怀着这个想法,查相关资料,果然在领域建模里对值对象描述的最好有写,值对象如果需求也是可变的,只是不可以共享。那可变的值对象还是值对象吗?它和实体的区别又是什么?因为值对象修改,我不重新创建值对象,明明还是一个对象,不是吗?这不就是一个有生命周期的对象吗?反观实体,如果两个实体什么属性都一样,包括主键,那它们不就是相等吗?有一个解释是说因为是实体,所以要有主建来标识。又用因为有主键不一样来解释它们是实体,这不是用答案来解释答案吗?一名话,没道理。所以这个事从技术上直接来找答案,还是不容易直接找到,至少我没找到。
那就从哲学上继续找,今天的你和昨天的你是不是同一个你,回答是同一个的,在软件里就应该设计成实体;回答不是同一个的,在软件里就是值对象。注意一点,这里说是不是不是真实的,而是使用系统的人。比如说我们人在人类世界大部分人认为昨天的你和今天的你是同一个,我们就把人设计成实体。但真实存在没准今天的你和昨天的你不是同一个你呢?那不重要,我是说真实的存在不重要,关键是在我们系统内,参与者的认知。所以考虑一个东西是不是实体时,只要在这个东西参与上下文中去询问。
我:生词,你改变词义后是不是同一个生词啊?
生词:当然是了,我有词义。
我:看来你是实体,那改变拼写呢?
生词:那当然就不是我了。
我:看来改变拼写就得是新建一个实体了,生命周期结束。还得删除重新建一个,换成值对象问问,生词你当成值对象不能有什么不好呢?
生词:我有拼写和词意,而且都可以改。你可以新建我,或者修改我,只要有这两者,就能代表我全部,不用关心是不是同一个我。
我:也没什么问题。看来当成值对象和实体都一样,既然都一样,我就选值对象吧,至少简单点。
再来解释用哲学讨论前的一段话,其实是不能用是技术上的属性或唯一标识来解释是否为值对象或实体的。事物存在的系统决定了它是实体还是值对象,而技术实现上我们把实体加了个唯一标识,当然也可以不加,用它的属性当唯一标识;值对象技术上如java会为对象加一个唯一标识,就是它的内存地址,也没什么大不了,虽然有标识,但我们不关心是不是同一个地址,只关心值。仅此而已。切记:不要因为有唯一标识所以是实体。因为是实体所以有唯一唯一标识的毫无意义的自白解释中去,我自己也陷进去了好了会。
附:我的英语学习软件里的单词指的是一个电影里字幕里含有的生单词,从电影里提取出来后,可以修改拼写及解释。在这里可以理解它只有拼写及解释两个字段。
本文里有时为主键,有时为唯一标识,是一个意思,以后再整理。
?