jim yeh on 十二月 14th, 2006

最近HSDc有一篇文章,主題是《繼承或是一般化?》,作者Ringle Lai認為類別的繼承不應該用生物繼承的角度去看它。他提道:

現代人中的上一個分類其實是「人屬」, 「人屬」有一個重要的特性是會製作工具,而現代人種則除了製作簡單工具的這個重要特性外,另外可以進行縝密的思考,因此,產生了製作太空船這樣的行為。

但是,如果我們利用「繼承」的概念去解釋上面的設計圖,則會作這樣的解讀:現代人種繼承自人屬;這種觀念,似乎和我們一般的看法大異其趣。

因此,用「繼承」的語彙來形容類別間的關係,其實並不適合。

然而,到底生物學中的繼承是什麼呢?維基百科對「Biological inheritance」名詞做這樣的解釋:

Biological inheritance is the process by which an offspring cell or organism acquires or becomes predisposed to characteristics of its parent cell or organism. Through inheritance, variations exhibited by individuals can accumulate and cause a species to evolve.

(生物的繼承是後代細胞或生命體取得或變成先天傾向它的父母細胞或生命體的特性的過程。透過繼承,個體的變化可以累積並且造成物種的逐步演進。)

由上面解釋看起來,並不能證明類別繼承與生物繼承在意義上有顯著不同!換句話說,Ringle Lai在該篇文章所提到的「根據生物學的觀點來說,分類是沒有繼承關係的」論點,令我無法理解他的立論根據為何,因為以定義來看生物分類的繼承關係,繼承的重點在於特性的相似性,人種的特性是由人屬所衍生出來的,用人種繼承人屬以類別設計的角度和生物學上的定義並沒有太大的差異。

我和Ringle Lai對類別繼承看法的不同,我想問題應該是出在這一段話:

事實上,所謂的「繼承」,通常指的是實體物件依據某些特定準則(生殖或是法律)的某種移轉(基因或是法律權利);然而,在軟體設計領域中,繼承卻往往是「反向」的。也就是說,我們在設計時,通常會是先發現「子類別」的物件,接著,才抽象出「父類別」來。

設計類別時,得確是大部分先發現「子類別」,再抽象出「父類別」,但我認為這種現象並不是類別繼承的「反向」作用的結果;而是演化論,是指類別如同基因或生命體般經過變異遺傳自然選擇作用下的演變發展。因為依據子類別抽象出父類別時,子類別已不是原來的樣子了,它已經進行演化的過程了,繼承只是演化的手法之一種而已!為何需要演化?如同複雜系統的演化動機,為了讓系統獲取最大的價值,演化的驅力,其實是來至於環境的刺激(需求改變)。

生物學也是一樣,剛開始發現新生物時,或許我們並不知道它該如何歸類;直到發現它們與其它生物的共通點後,我們才會清楚它屬於什麼物種,這其實和設計抽象化類別的概念是一樣的概念啊!其實類別的設計只是實體(顆粒度)與關係(相依性)的取捨而已,類別會朝向問題領域(Problem domain)尋求最適解的演化。

然而Ringle Lai的用意,大概是要強調類別的由下而上的設計手法,而非結構化設計所習慣的由上而下的設計。由上而下的設計,在結構上若未能呈現出問題領域的關鍵,只是一味地採用繼承手法,卻是設計僵化的開始,因為缺少問題關鍵的設計,封裝必然不足,這樣的設計必須挖東牆補西牆或疊牀架屋才把軟體實作出來,但程式架構卻到處充斥著沒有必要的複雜度(Unnecessary Complex)

關鍵在抽象化!讓類別設計以簡御繁,力有未逮時再進行演化,類別設計基本觀念在於封裝,為了達成封裝的目的,交互運用兩種基本的手法來演化類別:

  1. 一般化的目的在以同樣之道去看待不同的實體-抽象化(封裝)
  2. 特殊化的目的則為相異之術去實現相同的概念-具體化(多型

前者為異中求同,後者為同中求異。

但至於是先抽象後具體,或後概念而先實現,那是不一定的;甚至會來回反覆多次,重構(變異/突變)是免不了的。務實的做法是:需求到那裡,就演化到那裡。

這正是易經所言:「窮則變,變則通,通則久」的道理。窮則變,相當於特殊化的做法;變則通,相當於一般化的做法;通則久,則相當於持續整合同中異、異中同。

演化的關鍵在於View,也就是面對問題對設計所抱持的觀點。然而「因無所住而生其心」,體會軟體設計的菩薩道,我們會抱持著「常見」-有需求產生所以我們會抱持特定觀點,此時態度是務實的,但執著於過去、現在與未來;但也可以抱持著「斷見」-無觀點的存在的,因為任何觀點都是無法執著的,此時態度是務虛的,不執著於過去與未來,但仍執著於當下;兩種觀點看起來似乎互相矛盾,但當我們悟透時,進入了「中觀見」的境界,也就是「不落有無」與 「不落去來」之中道空觀,這時就領會了軟體設計的「諸行無常,諸法無我,涅盤寂靜」三法印,此時並不會執著於虛與實,現在、過去與未來。

最後,回過頭來思考設計問題,以Ringle Lai舉的生物分類的例子來看,屬與種,到底是什麼關係呢?其實沒有關係!(斷見)

但沒有關係的話,怎麼解決問題領域呢?所以,他們之間必須有關係存在。(常見)

  1. 用一般化關係,代表我想要解決的問題是讓種與屬可以等同看待(種繼承屬,即代表可以以種取代屬)。
  2. 用結合關係,代表我想解決的問題是希望讓屬具有一般性的行為或屬性,而將特殊行為封裝成種,讓不同的種有一致性的行為操作。

P.S.以上只是眾多例子之二,Modeling的基礎,是建構在領域知識的認識,而非技術如何實作。

其實關係是因我的需求(因緣)而生,當需求不存在時,這種關係就自然破滅了。(中觀見)

總之,沒有問題就沒有設計,只有設計也無法解決沒有問題的問題。所以設計是因需求而調適的,沒有絕對的設計,而是要根據需求而演化。類別的演化,其實是存乎於設計者的巧思;然而,更重要的是由招熟而漸悟懂勁,由懂勁而階至神明



     

15 Responses to “類別設計演化論”

  1. 101 說道:

    …..

    1. 用一般化關係,代表我想要解決的問題是讓種與屬可以等同看待(種繼承屬,即代表可以以種取代屬)。
    2. 用結合關係,代表我想解決的問題是希望讓屬具有一般性的行為或屬性,而將特殊行為封裝成種,讓不同的種有一致性的行為操作。

    …..

  2. [...] 在與《類別設計演化論》相關主題的討論過程中,曾針對網友GameBoy所說的「運用 “is a” 和 “has a” 要能洞察 Problem domain(初學的人容易用 real world 直觀的認知來 model,這有點危險),甚至在某些場合併用更能達到 Model 中微妙的動態平衡發揮軟體的軟性」回應: 一味地求虛其實更危險,過度設計的結果是頑空! [...]

  3. GameBoy 說道:

    (初學的人容易用 real world 直觀的認知來 model,這有點危險)

    當初講這句話並非針對同人先生

    這裡指得直觀是 初學者的 直觀

    而非同人先生的 直觀

    誠如同人先生所言

    在 Concept Model 中的 Entity

    ㄧ個目的是要能和 user 溝通

    Domain Model 中的 Entity 對於 User 而言

    應當是很直觀的

    但 直觀的 Term 不一定會出現在 Domain Model 中

    敝人只是看到過去有些 出學 Modeling 的 member

    會不經消化

    很直觀的認為 "汽車" 應該要在系統裡被 model 成"汽車"

    敝人以 "汽車" 為例

    在同人先生的另ㄧ篇 PO 文做了回應

    http://www.lifeparty.idv.tw/bl.....7#comments

    並非 Challenge 葉先生

    僅出於一片善意

    提醒初學者 Model 要看清楚 業務需求

    誠如葉先生在

    http://www.lifeparty.idv.tw/bl.....7#comments

    ㄧ文中給的範例、說理和提醒 …

    其實我還看過更慘的繼承體系 …

    以上

    (當然如果葉先生 認為我們倆的想法是不一樣的

    That’s all right …

    畢竟文字的解讀

    有時候是兩樣情的)

    如有機會相遇

    如您樂意

    敝人會很歡喜地與你暢談一番的 …

  4. GameBoy 說道:

    因為我看到太多 beginner 的抽象化是

    僅僅源自於他們的直觀認知

    而非從 Requirement 下手

    但 Real World 中直觀的名詞

    不見得適合作為 Domain Model 中的 Entity

    但卻往往被他們誤植於 Domain Model 中 …

    有一位網友 John 提到

    不妨看看 Evans 的書

    我想他指的應該是這一本書

    Domain Driven Design …

    最近隨手翻翻

    該書再提到

    如何從與 User 的互動中

    Iterative 地焠鍊出 Domain Model

    有談及如何避免 用直觀的名詞來 Model 的 案例

    初學 Modeling 的朋友

    不妨做個參考

    (我並非 Challenge 葉 Sir

    只是我必須將敝人

    「用 real world 直觀的認知來 model,這有點危險」

    這句話交代清楚
    )

    供參考

  5. GameB 說道:

    (初學的人容易用 real world 直觀的認知來 model,這有點危險)

    當初講這句話並非針對同人先生

    這裡指得直觀是 初學者的 直觀

    而非同人先生的 直觀

    誠如同人先生所言

    在 Concept Model 中的 Entity

    ㄧ個目的是要能和 user 溝通

    Domain Model 中的 Entity 對於 User 而言

    應當是很直觀的

    但 直觀的 Term 不一定會出現在 Domain Model 中

    敝人只是看到過去有些 出學 Modeling 的 member

    會不經消化

    很直觀的認為 “汽車” 應該要在系統裡被 model 成”汽車”

    敝人以 “汽車” 為例

    在同人先生的另ㄧ篇 PO 文做了回應

    http://www.lifeparty.idv.tw/bl.....7#comments

    並非 Challenge 葉先生

    僅出於一片善意

    提醒初學者 Model 要看清楚 業務需求

    誠如葉先生在

    http://www.lifeparty.idv.tw/bl.....7#comments

    ㄧ文中給的範例、說理和提醒 …

    其實我還看過更慘的繼承體系 …

    以上

    (當然如果葉先生 認為我們倆的想法是不一樣的

    That’s all right …

    畢竟文字的解讀

    有時候是兩樣情的)

    如有機會相遇

    如您樂意

    敝人會很歡喜地與你暢談一番的 …

    GameBoy

  6. i'm gameboy 說道:

    "一味地求虛其實更危險,過度設計的結果是頑空!"

    建議無需替他人片段的語句設立假設點

    然後自行衍生解讀

    否則只是徒增曲解

    (原先將你這段話 Mark 起來

    並非要 Challenge 你的 PO 文)

  7. i'm gamboy 說道:

    >

    我想葉兄做如是

    "一味地求虛其實更危險,過度設計的結果是頑空!"

    的回應 應該是出於好意

    但我所謂的

    運用 "is a" 和 "has a" 要能洞察 Problem domain(初學的人容易用 real world 直觀的認知來
    model,這有點危險),甚至在某些場合併用更能達到 Model 中微妙的動態平衡發揮軟體的軟性

    與你提到的 "求虛 … 過度設計 …"

    無關

    建議你毋需針對敝人片段的文字

    或敝人過去的 po 文

    因而做任何的假設

    過度解讀
    …..

    結果只是曲解敝人的原意

    Thx

  8. 同人 說道:

    我想 Gameboy 看到這一系列的文字內容有些意見,然而您提到~

    我所謂的

    運用 “is a” 和 “has a” 要能洞察 Problem domain(初學的人容易用 real world 直觀的認知來
    model,這有點危險),甚至在某些場合併用更能達到 Model 中微妙的動態平衡發揮軟體的軟性

    與你提到的 “求虛 … 過度設計 …”

    無關

    然而這一段話是不是也代表了您對別人的假設,對此,我也感到您對我的文字內容做過度解讀,也很讓人覺得不舒服!

    這一段在HSDc的討論,如果您覺得我曲解您的原意,大可與我就事論事的討論。雖然我看到貴HSDc有些網友用了一些情緒化的字眼,但基本上我還是認為與您在軟體設計方面還是可以激盪些不一樣的東西,但看到這一段話,真的讓我質疑我看錯人了。

    我並不想對您的看法作任何解讀,我只是想從這一段討論中,分享我在設計上的心得而已。事實上,我們對 real world 的直觀的定義並不一樣,連帶地連語意抽象層次都不同,所以沒有必要在這方面尋求共識,如果您覺得有問題,歡迎共同討論,但請不要隨便對別人作假設並依此妄自下斷語,謝謝。

  9. GameBoy 說道:

    "然而這一段話是不是也代表了您對別人的假設,對此,我也感到您對我的文字內容做過度解讀,也很讓人覺得不舒服!"

    那句話不是針對你說的 … 你過度解讀了

    "… 但基本上我還是認為與您在軟體設計方面還是可以激盪些不一樣的東西,但看到這一段話,真的讓我質疑我看錯人了。"

    你太抬舉敝人了 (你應該是看錯人了)

    "… 但請不要隨便對別人作假設並依此妄自下斷語,謝謝。 "

    The Same to You …

    Thx

  10. GameBoy 說道:

    冷靜了一下

    想想

    在怪罪你誤解我之前

    想必我也有誤解你之處

    你這句話 …

    "如果您覺得有問題,歡迎共同討論"

    我的小心解讀是

    其實你應該是很熱心的

    而我其實是很想繼續討論下去的

    但的確

    你我對於某些文字的 定義 感受 是有落差的

    尤其想到好幾回的 Fighting

    我想還是作罷

    (彼此都讓對方不舒服 我們似乎都很容易讓對方不舒服)

    (如果你真如網站上註明的不惑之年 我想我應該多尊重長我幾歲(沒有很多就是了)的你)

    此生如果有緣碰面

    且你樂意

    我是有很多很多想法

    想跟你聊的 (而且是很歡喜地跟你聊)

    (用說的應該會比用寫的 相對清楚多了吧)

    未曾與你謀面的 GameBoy 留

  11. 同人 說道:

    Dear Gameboy,

    您我並非未曾謀面,只是您不知我是誰罷了。

    您的前一篇留言讓我看到您的不悅,然而事件本身並不重要,重要的是我的反應為何。如果您沒有寫這一篇留言,我心中可能會留有短暫的不滿,但卻不會有任何的回應,因為在這種情況下,我們之間不會有溝通可言,只剩下針鋒相對的言語攻擊或言不及義的言語閃爍對我的生活是沒有絲毫價值的。

    您寫了這篇留言讓我覺得欣慰,討論過程的誤會是在所難免,但如果您提出您的疑問,我會針對問題解答,反而可以減少誤解,但以為自己可以解讀對方的想法,往往會關閉了溝通之門,因為一方已做了結論,另一方就沒什麼好說的。

    我說:「一味的求虛更是危險,過度設計的結果是頑空」並不是指稱閣下是如是,而是一種提醒,注意不要忽略現實需求,而我在我的另一篇文章亦已提及,我的出發點可能與您不同的地方,然而我不知時至今日,您的反應如此之大,實在非我始料所及,仔細看看那些文章,我可從來沒說您用技術來主導需求呀!

  12. [...] 對問題採用不同的觀點會對 Business Semantic 有不同的認知,所以之前主要想表達的並不在於類別該用 is-a 或 has-a,類別設計該採用繼承或是組合並不是必然的,它們是自然而然偶然成形的,用 is-a 或 has-a 實作,只是一種手段。我們要培養應無所住而生其心的智慧,認清所謂的直觀是相對的,亦即當問題焦點變化時,原來的直觀就變成了「本來無一物」,既然如此,那我們「何須惹塵埃」呢?[...]

  13. [...] 不過,我倒認為這樣的論點雖然可以簡化設計思維,但對於進階設計者而言,卻會發現設計中,用這樣的觀點來看事情,對設計卻會造成一些困擾,因為真實世界的問題常常不如我們想像地那麼簡單,當我們發現問題領域需要同中求異或異中求同的過程中,就會出現類別這個有機體。 [...]

  14. [...] 姑且不論設計要不要與實作分開,也不要討論相依注入是不是好方法。針對真實問題來設計,在軟體開發的實際作法就是針對問題來設計界面,然後依界面來找尋適當的技術解決方案來實現。界面是一種規格,依據規格來實現技術方案,這樣才能使設計與實作達到均衡,而不會使軟體開發太抽象而無用或太僵化而無當,同時關注軟體開發的虛實之道。 [...]

  15. [...] 所以,善用多型的介面,靜態型別程式語言也可以大幅提昇程式碼的再用性。這是物件導向設計的重要原則-開放封閉設計原則(OCP)的實踐,讓物件的型別或代碼可以看成獨立可重用的物件實體來看待,在過程中,介面或抽象類別在其中扮演重要的角色-讓務虛的抽象概念與務實的具體實作能夠充分調合,這是只用繼承觀點來看程式碼的重用所看不見的呀! [...]

Leave a Reply

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">