标签:
值是能脱离appSystem但不再有意义的对象。实体是脱离不掉appSystem的对象。
没有空中楼阁。若不是先人留下的知识帮助我们,高楼大厦不可能拔地而起。人类文明近万年无数人共同维护着的知识结构体是个相当良好的树形的。任何一个分支在使用到任何一个词汇时引用的本意都不与它的父节点冲突,那些存在冲突或有歧义的不良节点往往会在我们第一次听到它之前就已经被先人过滤掉了,或者迟早被我们或者后人纠正过来,既然这样那么只要我们曾经系统的熟悉过整棵树上某一个分支或者部分分支的话就可以通过上溯和下钻来容易的熟悉其它分支的知识。先人鼓励后来者大胆假设、大胆思考,先人极力维护出一棵结构良好的知识树的目的就是希望后人可以容易的掌握知识的规律,通过思考、联想、加工去学习它,良好的知识树支持你望文生义。
我们的业务系统就类似一个小区(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的对象。
分拣集合的技术
现在的数据集权限控制到目录级(Catalog),每一个Catalog根节点定性了一棵树,有很多棵树。树上的节点可以到类型,到字段,到字段值域的某个区间,甚至最终到值域的某个取值(注意:这些在树上的节点叫做“实体”,而将树上的节点打在(赋值到)资源上去时叫做“值”,在图形化联想的时候想象为Catalog树上的节点(包括叶子)会发出很多条线,这些线连接了节点和打在资源记录上的值,之所以要想象这样的线的存在是因为我们后续要“提溜”它们)。
有了这片森林一切都有可能。这些来自于森林上的节点组成的多元组会在某个空间单元(比如一条数据库记录)中聚合在一起,我们专门为每一个资源记录都设计有Catalog字段。这个Ctalog字段比如是varchar(100)长度,我们可以制订并记录下Catalog字段的空间划分规则,我们将10棵树上的节点甚至20棵树上的节点聚集在这个Catalog字段空间内,我们对varchar(100)做规划,拆分为长度为1,2,4,8,16等相等或不等长度的区间,我们把来自于那片森林中的树上的节点对应的值放进这些空间单元中去。最终我们通过sql(非关系数据库也有类似的机制)截取这个Catalog字段的正确位置的正确单元来筛选结果集,和读取这个字段中正确位置的值把这个值传入制订的安全策略中去参与计算参与返回一个表示当前主体对当前资源记录是否有当前操作权限的结果。
Catalog字段是附加上去的,是专门为了将一个集合划分为具体的一个个子集而附加上去的字段。而那些固有的字段和这个Catalog字段中的各个子单元中的值本质意义上是没有任何差别的,那些具体类型资源上的固有字段和其中的值同样是来自于某棵树上的节点,只有在通过资源记录的固有字段不能筛选出想要的子集的时候才应去动用附加的Catalog字段。记录级权限其实跟功能级权限跟目录级权限都是相通的。目录可以很深很深,目录级权限靠近叶子那段就是记录级权限,靠近根那段就是功能级权限。它们本质上没有任何差别。
前面描述的那片森林和那个Catalog字段的原理是这样,意思就是说:我们建立些树,这些树通常在需要的时候正好在内存,我们为某些(或某个)主体把某些树上的某些节点插入到某些资源记录的Catalog字段中去,然后之后我们通过提溜这棵树上的这些节点所在的枝条来把那些资源记录从那个大集合中提出来。这可能就是数据库的词汇世界中的“索引”的意思。记录级和记录级往下更细致的权限我们都可以通过这种机制去建立树,把树枝插进去,然后拔出来。我们所做的这些事情都只是在空间维度上下的功夫,然后再加上时间(运动、变化)维度,反复灵活的使用这些技术就可以限定任何主体在任何时间任何空间干任何事情了(如果还要控制能干一“种”事情几次的话其实就是在资源记录节点上去生长出个用于存放干过了几次的空间节点)。这样就有办法办到“能看到小王和小利的数据,但是我看不到小明录入的数据”了。
DDD可能并非足够良好:使用两个凡是去整理你脑中的比如来自于DDD的不良概念
标签:
原文地址:http://www.cnblogs.com/acengine/p/4287804.html