【LSP】“三维度”逻辑编程语言的设计

syf1313113   ·   发表于 25天前   ·   编程代码

Actor,顾名思义:演员。在我们的“三维度”逻辑程序中,使用Actor这个词来表示扮演角色的原生对象。Actor对象需要扮演多种角色,在不同的地点(比如在家,在公司)、不同的时期扮演不同的角色。Actor是“社会化意义”上的人,比如行驶一个人或一群人的意志的团体,或者机构、公司,或者一部机器。如果Actor是一个人,就一定会扮演一个角色,一生要扮演很多角色,所以,Actor与角色的关系就像人和影子一样,只要在阳光下总是形影不离。

在当前这个“游戏人生”程序中,下面的示例代码描述了张三和貂蝉两个Actor对象具有的一些角色:张三是一个员工,张三同时也是貂蝉的丈夫;貂蝉是张三的妻子。

//创建实体Actor对象
Woman diaochan = new Woman() { Name = "貂蝉", Birthday = new DateTime(1990, 1, 2) };
Man zhangsan = new Man() { Name = "张三", Birthday = new DateTime(1988, 3, 5) };
//陈述事实:XX是YY角色
Worker worker1 = new Worker(zhangsan);
Wife wife1 = new Wife(diaochan,zhangsan);
Husband husband1 = new Husband(zhangsan,diaochan);

注意上面的代码只是在申明Actor对象的实例,陈述Actor对象具有的角色事实关系。这里借助C#对象的构造函数,来为Actor对象申明一个相关的角色,这个角色会添加到Actor对象的角色集里面。但是为什么要用角色对象的构造函数而不是Actor对象的角色集合添加角色对象呢?比如下面这样子的代码:

zhangsan.Roles.Add(new Worker);

zhangsan.Roles.Add(new Husband(diaochan));
上面的代码的确可以实现Actor Has a Role的效果,但是有几个问题:

1,上述代码没有之前的代码简洁;

2,以Actor对象为主,角色对象是Actor对象的附属对象

3,描述多个Actor对象之间的关系不方便,语义不清晰。

4,无法体现出逻辑编程中的谓词关系。

所以,要解决这些问题,或者说要弄清楚“三维度”逻辑编程的特点,需要深刻的认识角色的含义,角色与Actor真正的从属关系。

Actor的马甲--角色谓词
谓词(参考定义)是用来刻画个体性质以及个体之间相互关系的词。在当前程序中,角色对象定义了对象的性质,也可以定义对象之间的关系,因此这里的角色就是一个谓词,Actor对象就是谓词对象的参数,一个谓词也可以表示多个Actor对象参数之间的关系。所以Worker、Wife、Husband都是谓词,是表达Woman/Man称谓的词。在逻辑编程中,强调对象之间的逻辑关系,这种关系就是谓词关系,逻辑编程就是谓词演算。为了更好的将逻辑编程与“三维度”(角色+场景+时间)理论联系起来,在“三维度”逻辑编程中将谓词称为角色谓词,程序的运行依赖于角色在系统中的交互。那么角色是什么,为什么这么重要呢?

角色是一种特定的关系
人的社会性表现在人和人之间各种关系的总和,这些关系形成一个复杂的网络,角色是其中的一种关系。这种关系有时候是不稳定的,有时候是稳定的。例如:

员工角色,他表现为某个特定的人当前是某个公司的雇员,员工和公司之间的关系是不稳定的、松散的,公司可以随时解约,所以员工角色定义的时候可以不指定从属的公司对象;
丈夫角色,他表现为一个男性跟一个女性的家庭关系,这种家庭关系是稳定的,强有力的,要解除这种关系(离婚)需要复杂的法律手续,所以丈夫角色定义的时候必须明确指定男方对象和女方对象,女方对象从属于南方对象。
妻子角色的定义与丈夫角色的定义类似。
通过这些角色关系,我们的社会有机的组织了起来,有条不紊的运行着。总之,角色表达的是一个主体对象跟一个或者多个从属对象的关系,如果角色关系是不稳定的,从属对象可以不明确指出,当它仍然存在。

1 Reply   |  Until 25天前 | 2835 View

py2815
发表于 25天前

Actor的演技--角色的使用
演员的天分
没有Actor,角色将毫无意义,作为演员,它为角色而生。所以Actor对象需要内置一个角色集合,且不可移除,不可重置,只能向角色集合添加或者移除某个角色。每一个Actor对象最终都继承自一个Actor抽象类,它有诞生时间,也有名字。此文,它还有扮演某个角色的方法,这让Actor天生有了当演员的才能。
再好的演技也需要角色
上面Actor抽象类的设计,让Actor具有了扮演角色的能力。我们知道扮演角色是为了能够执行角色定义的方法,由于Actor的角色并不是稳定的,角色在需要的时候才有,也会在特定的时候失去,所以在设计上Actor不能继承角色接口,也不应该将接口的方法直接定义在Actor对象中。那么能否让Actor对象直接执行角色对象的方法呢?也就是让对象动态添加一个方法/函数,这个功能在动态类型语言不是什么问题(比如Javascript、Python、Lisp等),但对于静态类型语言却是非常困难的问题(比如C++、Java、C#、go等)。

下面演示的是Javascript动态添加属性和方法的例子:

var object = new Object();
object.name = "name";
object.age = 19;
object.fun = function(){
  console.log("这是一个动态添加的方法")
}

object.fun();//调用新增的方法

然而,采用动态类型语言这种动态添加方法的方案难以在语义上表达调用这个方法所包含的角色语义,更为重要的是调用这种动态的方法不能保证类型安全,比如让一个员工(角色)对象调用了老板角色“发工资”的方法这种错误的事情发生。“三维度”逻辑编程提出了角色谓词的概念,并且在设计上明确要求由Actor对象来扮演角色,通过角色对象来安全的执行角色的方法,这不仅在代码上体现了角色语义,也保证了类型安全,让指定的角色干指定的事情,不会越俎代庖,每个人职责分明,系统有条不紊。

Actor通过切换角色来实现不同的功能,这个可以通过Actor对象的ActAs泛型方法来切换当前Actor对象的角色。ActAs泛型方法遍历Actor当前角色集合中所有的角色,如果找到就返回这个角色类型,找不到抛出异常,详细代码请看上面【演员的天分】。

回顾一下前面程序中Actor对象通过ActAs泛型方法切换当前角色执行角色功能的的示例代码示例:

//场景参与人开始扮演角色
diaochan.ActAs().Child_bearing();
zhangsan.ActAs().Money += zhangsan.ActAs().Work();
zhangsan.ActAs().Child_rearing();
上面的代码通过Actor对象切换角色来执行角色对象才有的方法,如故事男女主角作为夫妻功能才有的生孩子功能,以及男主作为员工角色进行工作赚钱的功能。事实上也本来如此,整个过程理解起来非常自然。

好演员更需要好剧本
好演员当然说到是饰演某个角色演的淋漓尽致、惟妙惟肖的演员,然而一个演员要饰演这样的角色,除了自身的演技,还得遇到非常好的剧本,毕竟同样的角色大家都有机会来当,比如我也想来演一次当老板的角色,但你是当一个小卖部老板还是世界500强公司的CEO,这就要看导演给你的剧本了。演小老板有小老板的演法,演大公司CEO就必须有CEO的演法,这里的区别就是剧本中设定的角色规则,比如小老板角色设定的身价不能大于100万,而CEO角色的身价过亿,CEO可以聘请10000名员工而小老板只有自己一个员工。哪怕是同样的小老板,有的剧本是小老板一路开挂三五年做到大公司CEO,有的剧本是小老板当了不到一年就破产下岗了。这些剧本中决定角色命运的,就是编剧/导演给角色设定的规则。

所以,我们的“游戏人生”剧本要讲好故事,介绍完了演员和角色,还需要重点讲讲角色的规则,这是下一篇文章准备讲的内容,也是“三维度”逻辑编程语言的重点内容,这部分内容在《SOD框架“企业级”应用数据架构实战》已经做了相应的介绍,手里有这本书的朋友可以先一睹为快。

评论列表

  • 加载数据中...

编写评论内容
LoginCan Publish Content