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

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泛型方法切換當前角色執行角色功能的的示例程式碼示例:

           //場景參與人開始扮演角色
            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領域的大佬批評略多。在此感謝這些大佬的批評建議,但是與大佬的水平相比較起來大佬在天上我在地上,不在一個交集上,所以這篇文章以及整個系列被大佬批判無法避免。只是希望大佬能夠手下留情,在點選文章【反對】之前先回帖留言詳細說明您反對的地方,謝謝支援!

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

&n