Actor:人生如戲全靠演技--“三維度”邏輯編程語言的設計(3)


上一篇介紹了邏輯編程的作用,介紹了邏輯編程中的一些概念,包括邏輯程序的結構:事實、規則和問題;知識的表達方式:謂詞演算、產生式規則,以及這些概念與三維度(角色+場景+時間)理論的契合關系,正式提出了“三維度邏輯編程”這個概念。為了更好的體現“三維度”的關系,今天要重點介紹一下角色的扮演者--Actor。

其實,我是一個演員

這個標題來自電影《喜劇之王》周星馳的台詞。人生如戲全靠演技,星爺這樣說,我們又何嘗不是呢?

(圖片來自網絡,侵刪)

在我們的“游戲人生”這個游戲中,三好男人張三在家是丈夫,有了孩子后是父親,他在老婆面前必須當好丈夫角色,在孩子面前必須當好父親角色,同樣張三在單位工作的時候必須當好員工角色,為了賺錢養家,老板要求996也得忍。。。加班回家一身疲憊,也得面帶微笑,當好丈夫或者父親角色。只有在夜深人靜的時候,張三才能做回張三自己。張三一天深夜在某個聊天群寫下了一段話:

夜深了,
我還沒有睡,
想着寫了2年半的代碼,
是一種情懷,
能堅持到最后的勇氣,
像極了18歲的自己。
我很菜,卻依然堅持,
群里全是我膜拜的大神,
談的我全不懂,
我依然願意在群里,
發點感慨
明天繼續!
           -----致和我一樣努力寫bug的垃圾碼農

 

Actor就是那個演員

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稱謂的詞。在邏輯編程中,強調對象之間的邏輯關系,這種關系就是謂詞關系,邏輯編程就是謂詞演算。為了更好的將邏輯編程與“三維度”(角色+場景+時間)理論聯系起來,在“三維度”邏輯編程中將謂詞稱為角色謂詞,程序的運行依賴於角色在系統中的交互。那么角色是什么,為什么這么重要呢?

角色是一種特定的關系

人的社會性表現在人和人之間各種關系的總和,這些關系形成一個復雜的網絡,角色是其中的一種關系。這種關系有時候是不穩定的,有時候是穩定的。例如:

  • 員工角色,他表現為某個特定的人當前是某個公司的雇員,員工和公司之間的關系是不穩定的、松散的,公司可以隨時解約,所以員工角色定義的時候可以不指定從屬的公司對象;
  • 丈夫角色,他表現為一個男性跟一個女性的家庭關系,這種家庭關系是穩定的,強有力的,要解除這種關系(離婚)需要復雜的法律手續,所以丈夫角色定義的時候必須明確指定男方對象和女方對象,女方對象從屬於南方對象。
  • 妻子角色的定義與丈夫角色的定義類似。

通過這些角色關系,我們的社會有機的組織了起來,有條不紊的運行着。總之,角色表達的是一個主體對象跟一個或者多個從屬對象的關系,如果角色關系是不穩定的,從屬對象可以不明確指出,當它仍然存在。

名不正言不順

天下人無非追求的就是名利,要想做事就必須有一個名頭,大到行軍打仗需要“出師有名”,小到送個外賣,沒有一個合適的工作角色就沒法正大光明的去做事情,能做某件事情的名頭就是角色,這個名頭代表一種身份、社會地位以及權利。科學的解釋是角色即為”一定社會身份所要求的一般行為方式及其內在的態度和價值觀基礎“。總而言之,一個人必須以某種角色去做某些事情,在做事情的時候扮演一種角色。為了明確區分不同的角色,需要給每種角色一個約定俗成的名字,一個稱謂,這便是角色謂詞。

在“三維度”邏輯編程中,每一個角色都是一個唯一的角色類,它們都繼承自一個角色接口,該接口定義了角色名字和角色的擁有者,在定義具體角色的時候必須確保名字的唯一性和名字的約定俗成。

 interface IRole<out T> where T : Actor
    {
        string RoleName { get; }
        T Owner { get; }
        bool MatchRules(string ruleName);
    }

上面接口的定義反映出一個接口必定有一個它的擁有者,這個擁有者必定是一個Actor對象。這里角色擁有者作為角色對象的一個屬性出現,也體現出來了角色和角色擁有者之間的主從關系。

角色才是真正的主人

前面說了角色的重要性,人必須要扮演一種角色去做某件事情,這是人的社會性的必然。人類社會就是由一套復雜的角色驅動着。這套角色,中國儒家稱之為“禮”,君臣有禮,三綱五常,通過這套體系維持封建社會的穩定運轉。現代國家更是設置了嚴密的等級體系,每個二年都在這個體系里面生活、工作,比如體制內外的人社會地位有明顯的差別,我們每個人都想去當公務員,都想當大老板。正是這些理想的社會角色,讓我們每個人為之期盼、奮斗,永不停留腳步,有人叫你一聲所以XX總,YY局,是不是很愜意?所以,你叫別人是什么不重要,別人叫你是什么才重要,角色才是我們每個人真正的主人。

這段話表明在描述角色和Actor之間的關系的時候,應該以角色為主,Actor為輔助,所以在我們的邏輯編程中使用角色為謂詞,稱為角色謂詞,以Actor對象為角色謂詞的參數,使用C#來表達,就是前面已經說過的樣子:

            Worker worker1 = new Worker(zhangsan);
            Wife wife1 = new Wife(diaochan,zhangsan);
            Husband husband1 = new Husband(zhangsan,diaochan);

 通過使用角色對象的構造函數,更容易將目光關注到對象的構造申明上,而不是構造的過程。我們忽略無關的細節,更容易重視代碼表達的語義,體現出了角色對象和Actor對象之間的從屬關系。

雖然說角色對於劇本講故事很重要,但是再怎么重要的角色也需要一個出色的演員。演員的演技是能否駕馭角色的關鍵,下面需要我們再來介紹下這位演員了。

 Actor的演技--角色的使用

演員的天分

沒有Actor,角色將毫無意義,作為演員,它為角色而生。所以Actor對象需要內置一個角色集合,且不可移除,不可重置,只能向角色集合添加或者移除某個角色。每一個Actor對象最終都繼承自一個Actor抽象類,它有誕生時間,也有名字。此文,它還有扮演某個角色的方法,這讓Actor天生有了當演員的才能。

    abstract class Actor
    {
        public Actor()
        {
            Roles = new List<IRole<Actor>>();
            AtTime = DateTime.Now;
        }
        protected internal List<IRole<Actor>> Roles { get; private set; }

        public T ActAs<T>() where T : class,IRole<Actor>
        {
            foreach (IRole<Actor> role in Roles)
            {
                if (role is T)
                    return role as T;
            }
            throw new InvalidCastException("Actor沒有此角色:" + typeof(T).Name);
        }

        public DateTime AtTime { get; set; }
        public string Name { get; set; }
    }

 

再好的演技也需要角色

上面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泛型方法切換當前角色執行角色功能的的示例代碼示例,由於可以通過Actor對象來切換到擁有的角色對象,所以申明角色對象的變量都不需要了,這樣能更加顯示出角色謂詞的強大力量:

           //使用角色謂詞表示事實關系
new Worker(zhangsan);
new Wife(diaochan,zhangsan);
new Husband(zhangsan,diaochan);


//場景參與人開始扮演角色 diaochan.ActAs<Wife>().Child_bearing(); zhangsan.ActAs<Husband>().Money += zhangsan.ActAs<Worker>().Work(); zhangsan.ActAs<Husband>().Child_rearing();

上面的代碼通過Actor對象切換角色來執行角色對象才有的方法,如故事男女主角作為夫妻功能才有的生孩子功能,以及男主作為員工角色進行工作賺錢的功能。事實上也本來如此,整個過程理解起來非常自然。

好演員更需要好劇本

好演員當然說到是飾演某個角色演的淋漓盡致、惟妙惟肖的演員,然而一個演員要飾演這樣的角色,除了自身的演技,還得遇到非常好的劇本,畢竟同樣的角色大家都有機會來當,比如我也想來演一次當老板的角色,但你是當一個小賣部老板還是世界500強公司的CEO,這就要看導演給你的劇本了。演小老板有小老板的演法,演大公司CEO就必須有CEO的演法,這里的區別就是劇本中設定的角色規則,比如小老板角色設定的身價不能大於100萬,而CEO角色的身價過億,CEO可以聘請10000名員工而小老板只有自己一個員工。哪怕是同樣的小老板,有的劇本是小老板一路開掛三五年做到大公司CEO,有的劇本是小老板當了不到一年就破產下崗了。這些劇本中決定角色命運的,就是編劇/導演給角色設定的規則。

所以,我們的“游戲人生”劇本要講好故事,介紹完了演員和角色,還需要重點講講角色的規則,這是下一篇文章准備講的內容,也是“三維度”邏輯編程語言的重點內容,這部分內容在《SOD框架“企業級”應用數據架構實戰》已經做了相應的介紹,手里有這本書的朋友可以先一睹為快。

 

 

--------------分界線-------------------------

構思整個系列花了2年多時間,寫這篇文章寫了3天,反復刪改,但限於本人對於編程語言知識能力的淺薄,其中謬誤肯定很多,前幾篇文章的內容也被PL領域的大佬批評略多。在此感謝這些大佬的批評建議,但是與大佬的水平相比較起來大佬在天上我在地上,不在一個交集上,所以這篇文章以及整個系列被大佬批判無法避免。只是希望大佬能夠手下留情,在點擊文章【反對】之前先回帖留言詳細說明您反對的地方,謝謝支持!

如果僅反對而不回帖留言,本人只好當您為空氣,您的舉手之勞毫無意義,一律略過。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM