連載03:軟件體系設計新方向:數學抽象、設計模式、系統架構與方案設計(簡化版)(袁曉河著)

統一化

打破了這種集合關係,那麼我們需要重新整理一下我們的思路,這些特徵到底是什麼關係呢?感覺有點亂。

不過沒有關係,我們先跳出面向對象的原有的思維方式,我們先從計算機的最基本的處理來看,在計算機裏面我們使用 (值,地址) 這樣的關係對來表徵整個軟件的框架體系,任何運行的最小單元,都可以具有某個狀態的值的信息,同時必須佔用空間,沒有無值的地址,也沒有無空間的值,就像計算機中的0和1,是相輔相成,對立統一的,而值和地址是可以相互進行轉換的,值可以通過間接地址進行指引,而地址可以轉換爲值進行表示。
其實這種(值,地址)的關係,對於我們的東方古人,其實已經見怪不怪了。我們的祖先就已經有:氣分陰陽,陰盡成陽,陽盡成陰,事物都是陰陽組合而成的,不存在孤立的陰,也不存在孤立的陽,陰陽相互相成,統一共存。而這也是矛盾的對立統一,所以(值,地址)就是我們的陰陽,而且兩者還可以相互轉換。只是我們在進行某一個方面的時候,我們着重談論起「值」的意義,或者在另一方面談論其「地址」的意義,但是實際兩者缺一不可。雖然我無法達到我們祖先那麼高深的境界,只是簡單粗糙的認識到這種對立統一。但是,對於本書談論到的陰陽(「值和地址」),其相對於計算機軟件設計來說,不僅僅是這兩者的關係,同時必要的是這兩者之間的轉換。 
對於賦值來說,是將一個值置換成另外的一個值,而通過間接訪問的指針可以在更改指針中的值信息來指引到另外的地址空間中,而這種指針具有一種地址位置更換的功能。
這就是計算機系統的基本框架,通過數據(值)與空間位置(地址)的相互轉換,構成了最爲基本的要素,而數據值與空間位置的相互轉換可以看成一種統一的變換過程,這種過程我們稱爲「置換」,其置換操作的結果就是,無論通過哪種方式進行獲取而得到的引用結果是確定的、唯一的、並且是等效的。
對於更多層面來說,值與地址的相互轉換,還表徵於其他不同層面的操作形式:賦值、指針、引用、函數、函數指針、繼承、抽象、實現、泛化、實例化等等方式來處理。這些操作是否也一樣具有這種「置換」操作呢?
先說說引用,經典的定義引用就是一個別名,而別名正好表達一種可置換邏輯上的語義表徵概念,而對於函數來說,是一種操作的簡單歸類和抽象,函數具有地址,所以可以表示爲函數指針,說明可以通過置換方式進行地址位置的置換,同時在調用的地方是一個站位符,需要通過具體的實現來置換這樣的一個處理。所以它們在定義和使用過程中也是具有這種相互轉換的「置換」的能力。
類的劃分。決定了類與類之間的關係,不同的類的劃分,呈現了不同的類關係。那麼哪一種方式更好呢?只是面向對象必須回答的問題。
類是按照操作集進行劃分的嗎?或是按照成員變量進行劃分的嗎?還是按照抽象意義進行劃分的呢?
爲什麼要使用抽象化原則呢?因爲複雜的策略並不比簡單的規則做得更好,而抽象的思想就是去繁化簡的過程,簡化其規則將更有利於進行方案的比較,面向對象、泛型編程、結構化等都是不同的抽象方法,抽象纔是成爲設計的基礎。
設計者的經驗是劃分方式之一,通過與現實或已經有的經驗進行劃分,這與現實世界的劃分是否相符呢?或者說現實世界的本身就是無序的,是無法進行劃分的呢?,其相互的關係必須由人的認識的層次決定的嗎?我們的對象模型按照不同的類關係(類結構)會導致不同的框架以及方案嗎?靜態結構和動態結構處理可能是不一樣的,對於置換方式來說,爲什麼此方式比彼方式更具有擴展性呢?


而對於面向對象的軟件設計,我們在前面進行了一些澄清,我們需要從另外的角度來考慮我們的抽象和繼承以及實現,但要求我們在概念上不要被故意引入集合的包含關係中。

面向對象的思路是從現實的物理世界中,意識的認知觀念上來重組計算機基本概念,它們相互之間的關係可以通過下圖來簡單描述。



通過上面我們可以看出,現實中的對象和我們在計算機世界中的對象不是一回事,其應該是抽取其部分特徵或根據認識的需要進行了一些轉換後的映射結果。所以:
    現實世界是不包含所謂的類,只存在的各種各樣獨立的對象實體,而這些對象實體也無法通過邏輯來完整定義的,而這些對象是客觀的,不是因爲我們如何歸類的方法而讓其改變其實質,所以現實對象是我們設計中的直接參照物,但是也並不是唯一的參照物,很多時候,計算機中的對象不僅僅描述現實中的對象的描述,也可能是這些對象中某些操作彙集而形成的對象。 在面向對象之外,對於一些例如結構化編程理念中,也是具有對象的概念,而這種概念不是通過所謂的類進行創建的,而是將其外部表現一致的實體都看成一個對象,一個很好的例子就是在windows操作系統中,對於進程、文件、信號量、圖形等都會返回一個統一的操作成爲句柄,這個句柄就是對象的ID,雖然對於這些不同的實體進行的操作各不形同,但是其傳入的句柄是一致的,在外部表現上,其操作的就是一個具有統一整理和編號的對象。所以在圖1-2中,我們將現實中的對象通過映射形成計算機中的對象。 在面向對象的理念中,希望通過模擬人在看待現實對象中的一些歸類的思想,在邏輯上對這些對象的部分特徵進行抽取形成不同的類屬,然後建立一套類的相互關係,並通過類以及類與類之間的關係,來簡化對物理世界的充分認識,這裏大家要注意,使用這種方式其實是一種簡化的操作,既然是簡化那麼就可能存在部分特性的消失(雖然,可能覺得這是一件多麼失望的理論,但是,我們應該認識到,簡化是一個具有重要意義的認識方法論,如果不採用簡化的方法,那麼我們永遠都無法去認識這個世界,我們還是要正確看到我們有限的一面)。 因此,面向對象的理念只是人類在看待和處理物理世界的一個方式和方法,是物理世界的一種劃分,這種劃分能夠讓人類意識形態更加方便和簡單,是否一定就是最好最準確的劃分,其實並非如此。這種劃分形式,其實在很多時候,就像人類利用工具一樣,利用面向對象的方式,在處理計算機世界中能夠達到降低成本、提高開發和使用的效率等功能性方面而推動面向對象的理論,所以,我們不能簡單地、片面地認爲面向對象是正確的不二法則,當然同時也要明白,面向對象的這種思想是一種在邏輯層面能夠簡化我們的設計和開發的一種非常好的手段。 其實這本身就是因爲意識形態只能無限接近於物理世界的,因爲物理世界是無限大的,通過有限的意識認識,只能無窮逼近無限大,而不能完全達到最後的彼岸。這句充滿哲學味道的話,也許你還十分的懷疑。不過對於計算機中的類,那絕對是隻抽取了意識形態認識的對象的部分特性,也就是說不管意識形態的對象是否達到物理世界的對象,但計算機中的類表達的肯定是物理世界對象的部分特性的邏輯簡化認識。 另外在上面我們也提到,人類在認識的過程中,有時候爲了統一劃歸,將一些現實對象的操作集合或者現實對象的狀態都劃歸爲一個類,這個類其實在現實世界中是很難找到對應的實體,但是這樣的劃歸卻給我們的設計和實施帶來了更加強大的便利,我們可以通過這樣的統一劃歸讓我們的設計的不同部件之間耦合程度大大降低,這樣的手法在設計過程在後面的描述過程中也是處處可見。 在面向對象理論的不斷深入過程中,人們猛然發現,如果將這些操作集合再進行分類,於是就形成了一個高度抽象的實體,這個實體就稱爲接口,而接口的概念更是體現這種邏輯上的劃分,在現實世界其實是沒有這個實體的,所以我們只有這樣規定,不能創建接口對應的對象,通過這樣的解釋,大家是否應該明白了這個道理了吧(邏輯與物理並非是一對一對應的,所以優秀的軟件設計師往往創造性的給出一些邏輯上新的概念,讓設計一下子簡單明瞭,這就叫妙筆生花)。這個接口的概念,對我們的設計帶了深遠的影響,它同樣讓不同部件之間大大解除了耦合。 在計算機中的對象是具有空間分佈和運動時間的邏輯實體,也就是說是(值+位置)的組合的一種方式。計算機中的對象的規則是通過計算機中的類來限制的,或者說計算機中的對象是通過計算機的類進行實例的結果,而計算機中的類是計算機中對象進行抽象而來的(這裏大家可能要注意,我並沒有按照傳統的方式認爲計算機中的類是通過現實的對象進行抽象的說法,而是說成是歸類,這樣會更加準確一些),因爲計算機中的類的確和計算機中的對象是相互對應的,一個是物理上的計算機的對象,一個是邏輯上的計算機的類。雖然有時候我們也可以將計算機的類通過一些其他的方式來描述,例如JAVA、VCL、MFC等的動態類,C++中的typeof的相關操作,但是面向對象的類的概念依然是邏輯上的,只是可能通過靜態方式描述,也可能通過動態方式進行描述的區別。 在新的百科上又是這樣的描述: 類是對某個對象的定義。它包含有關對象動作方式的信息,包括它的名稱、方法、屬性和事件。實際上它本身並不是對象,因爲它不存在於內存中。當引用類的代碼運行時,類的一個新的實例,即對象,就在內存中創建了。雖然只有一個類,但能從這個類在內存中創建多個相同類型的對象。 這是從類是否能夠實例化爲在空間和時間上具有的對象(實體)所表達的方式,類其實是可以描述的,而且在內存中也是可以描述的,只要我們通過「映射」方式能夠將具體的對象通過類進行映射,則類就可以存在於內存中。比如java語言中的反射機制也可以看到,類也是可以描述出來的,只是不能脫離「映射」方式來孤立描述,類是在「關係」中存在的。 從上面可以看出,由於面向對象的思想更體現了邏輯意義上的變換(所以面向對象會招致很多的質疑,其實這種質疑是一件好事,這樣可以檢驗我們設計過程中,這些通過間接方式的邏輯變換,是不是違背了物理世界的基本規則,是不是影響我們的設計結果)。 通過上面相關的描述,苟且希望我能夠比較清楚地理清了這些概念的關係,能夠爲下面的分析打下一個好的基礎。