两个凡是:凡是在系统树上的才是有意义的,凡是脱离了树的都是无意义的。

我们的业务系统就类似一个小区(appSystem),一个小区中有很多资源,对小区中的所有资源按照类型进行树形的分类就是资源类型(resourceType),比如“停车位”是一种类型的资源、小区中的“绿化树”是一种类型的资源、小区中的“人”是一种类型的资源、“保安”是一种类型的资源、小区中的“业主”是一种类型的资源、小区中的“居住者”也是一种类型的资源。到底是把保安、业主、居住者挂接在人这个节点下呢还是剪掉人节点把大家作为兄弟节点挂接在appSystem下呢?这需要考虑这些资源的运动规律再做判断,不管以哪种形式组织这棵资源类型树ResourceType模块都得能够应对。

ResourceType树是相对稳定的树,这棵树基本上是由设计人员在设计时定义的。一条记录只对应一个ResourceType节点(对于数据库表中的记录来说也是这样的,一条记录只对应一个表,这个表就是ResourceType,ResourceType概念是站在用户主体的角度的概念,Table是站在程序员角度的概念),不可能对应两个ResourceType节点。

现在有这样一个问题:既然一条记录只对应一个ResourceType节点,如果一个人同时是保安又是业主怎么办?
办法有两个:1 为同时是保安又是业主的资源建立两条记录,一条是保安类型的记录,一条是业主类型的记录。2 增加两棵树,ResourceType是棵资源类型树,它只是一棵树,我们完全可以建立一片森林,现在我们从资源类型树上剪掉“保安”和“业主”两个节点,将这两个节点分别独立成两棵树,将这两棵新树命名为“是否是保安”和“是否是业主”,当然“是否是保安”和“是否是业主”这两棵树下只有两个True、False子节点,虽然只有两个节点但也是树。
Boolean树(所有的类型都是树不只是Bool型)这是一种特殊的树,它没有层级,没有层级就是字典或枚举了。将这“是否是保安”和“是否是业主”两棵树上的节点打在“人”这种类型的记录的身上。
上面这个过程就是:树的变换或演化。它由一棵变成两棵、三棵、四棵……反过来也可以合并,多棵树合并成一棵树。

我们的业务系统类似一个小区,大门是入口,小区外面来了个请求,有人要进小区“找人”。
“'找' '人'”找是动词,人是名词。人是资源类型,找是绑定在资源类型上的操作。
“找人”合起来标识了一“种”类型的运动。
对于大门口的保安来说,受限于他所知道的信息,他只能对“找人”这样的“种”运动进行授权,门口的保安往往没有被找人的人和请求找人的人的足够信息,所以让保安去对具体的某“个”找人运动实例进行授权是不合理的,保安负责对运动的“种类”进行授权就可以了。根据小区这个系统的配置,保安允许了“找人”这种请求的继续,保安放行。
找人请求者进入了小区,来到他要找的人所在的那个单元,那个楼层,那个房间,然后又遇到了一扇门。这个时候又会有一次类似在大门口遇到保安时那样的授权验证:你是谁?哪里来?干什么的?。被找的人比门口的保安具有更多的信息所以能做出更准确的判断,房间里的人依旧可以拒绝这“个”请求者的找人请求。

实体上的每个属性都是一棵树,表中的每个字段都是一棵树。每一条躺在那的资源记录都是来自多棵树上的节点在那个空间单元中的聚合(不是交差,树是永远不会交差的)。无论是什么类型的字段,到最后都是在树上挂着的节点,一个int下挂8个字节,一个字节下挂8个位,一个位下挂一对0 1。合理的使用Catalog模块的话ResourceType模块是可以删除的。

凡是脱离了我们的appSystem这个根节点下的那一片森林(算上appSystem根节点还是一棵树)就不再有意义的对象就是值,比如int、bool、guid、string这都是值,根据我们的系统的业务边界某些看起来比基本类型复杂的由基本类型组成的类型也是值,比如struct{ZipCode,Mobile}。
而那些无论如何运动都脱离不掉我们的appSystem树的那些类型对象都是实体。比如在电子商城这个apppSystem下,那个Customer类型的对象无论运动到哪里它都脱离不掉我们的appSystem下的树,因为Customer类型节点是直接打在它身上的并且在它身上打上一个appSystem定义的对象实例Id,它无论是在内存,还是躺在磁盘上,无论那个Customer类型在何种介质以何种形式表现的这个实体都摆脱不了这个在我们的appSystem下定义的有意义的"Customer"这个类型树上的节点。值是能脱离appSystem但不再有意义的对象。实体是脱离不掉appSystem的对象。