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

1. 完備和相容

 

完備性可以這樣來簡單理解:當一個對象具有完備性,即它不需要添加任何其他元素,這個對象也可稱爲完備的或完全的。完備性最爲強烈的表現在數學之中,因爲在整個體系中可以將之轉化爲一個一組公理系統,這組公理系統只有具有完備性,才能以此推廣到這個領域,但是針對一個系統來說,在指定的範圍內,雖然物理的系統是一個完備的系統,但是由於我們的有限的資源,有限的運行時間以及一些特殊的要求,我們描述系統常常又是非完備的。當然,我們需要通過有限的手段更爲通用的設計方法來將完成一個絕大部分達到完備的系統。

完備系統有一個突出的優勢就是:在完備系統中運行的系統是可靠的,是值得信任的。實際上,完備性和可靠性是互爲可逆。這就表示兩者具有等價的效果。

當然,我們此處不去討論完備性和哥德爾的不完備性的各種理論或者哲學上的思辨,這裏我們特別需要讓大家知道如何在軟件系統設計中做到完備性以及如何檢測系統是否是完備的。

在具有狀態變遷這樣的系統中,我們發現其是否是完備的方法就是通過圖例來表徵系統的狀態變遷情況,在這個變遷圖中,一個是狀態是否是完備的,一個是變遷方式是否是完備的。當進行有效的清理以後,如果不完備,這就可以直接從圖中就會直觀的表現出來。因此如何構造狀態變遷圖成爲這類系統的一個基本的能力要求。

同樣,在一個系統中,有些具有相互矛盾的業務或者處理方式也是我們判斷是否具有完備性的一個檢驗方法。例如一個系統是否同時兼顧了“讀和寫”的能力,一個系統是否考慮了“輸入和輸出”的處理,一個系統是否具有“增加和刪除”的功能等等。這些具有矛盾的處理方式在我們的設計過程中應該不斷地檢測和驗證。

當然,很多系統在一些特徵上都具有“對稱”的特點,對稱是完備系統中最爲簡單有效的處理方式。其實就算哪些具有“非對稱”的系統中,在更大的領域其實也是具有“對稱”的特點。例如在非對稱加解密的應用中,在更大的範圍內可以使用加解密和簽名認證上就是對稱的出現。

另外,完備性還表現在一些特殊的非正常情況下的異常處理機制中,針對異常情況下我們的應對策略,是否將這些異常情況的處理也同時統一到我們正常的處理機制中,這樣我們就能夠更好的滿足系統的可靠性。

比如,在某些登錄系統中,當用戶傳入的用戶不存在或者密碼不正確的情況下,我們是否可以提供給用戶是否需要重新註冊,或者忘記密碼,通過將註冊和密碼這兩個正常業務引入過來,這樣能夠顯著提高用戶的體驗,同時也讓登錄系統完備化,這其實也是我們在處理異常情況下的一種通用的方法。

在應用層面上完備性是很難體現出來的,這就如同我們在一個完備系統中,我們沒有參照物又何從指導我們是一個完備系統呢?所以,我們需要通過具有一些方式和方法來進行驗證是否是在完備之中,比如如果我們預先知道我們是在一個對稱系統中,此時可以通過對稱來推測是否具有完備的設計。而在一個非完備系統中,常常會有一些無法定義的狀態也是我們判斷的依據。

相容:

數學中,在形式化的邏輯系統中,其相容性是指其中沒有矛盾,或更精確的說,不存在一個命題P,P和非P都可以在這個系統中證明。

分佈式領域CAP理論:

ü Consistency(一致性), 數據一致更新,所有數據變動都是同步的。

ü Availability(可用性), 好的響應性能。

ü Partition tolerance(分區容錯性) 可靠性。

定理:任何分佈式系統只可同時滿足二點,沒法三者兼顧。

在系統設計中,常常存在無法相容的情況,需要我們進行適當的取捨。這些相容是由於在物理層面上,無法通過技術上的改造解決其相容性,這需要考慮實際的需求和運行環境,對此需要做的就是能夠針對不同的場景能夠通過配置進行切換,這樣讓系統能夠根據需要進行不同模式的適應。

軟件兼容:

軟件的兼容性是衡量軟件好壞的一個重要指標,兼容性指與軟件可從某一環境轉移到另一環境的能力有關的一組屬性,它包括以下幾個屬性:

1、 與軟件無需採用有別於爲該軟件準備的活動或手段就可能適應不同的規定環境有關的軟件屬性

2、 使軟件遵循與可移植性有關的標準或約定的軟件屬性

3、與軟件在該軟件環境中用來替代制定的其他軟件的機會和努力有關的軟件屬性 。

在具體測試中可以從以下幾個方面來判斷:

操作系統兼容性  軟件可以運行在哪些操作系統平臺上,理想的軟件應該具有與平臺無關性。有些軟件需要在不同的操作系統平臺上重新編譯即可運行,有些軟件需要重新開發或是改動較大,才能在不同的操作系統平臺上運行,對於兩層體系和多層體系結構的軟件,還要考慮前端和後端操作系統的可選擇性。

異構數據庫兼容性  現在很多軟件尤其是MIS,ERP,CRM等軟件都需要數據庫系統的支持,對這類軟件要考慮其對不同數據庫平臺的支持能力,如從ORACLE平臺替換到SYBASE平臺,軟件是否可直接掛接,或者提供相關的轉換工具。

新舊數據轉換  軟件是否提供新舊數據轉換的功能。當軟件升級後可能定義了新的數據格式或文件格式,涉及到對原來格式的支持及更新,原來用戶的記錄要能繼承,在新的格式下依然可用,這裏還要考慮轉換過程中數據的完整性與正確性。

異種數據兼容性  軟件是否提供對其他常用數據格式的支持。例如辦公軟件是否支持常用的DOC、WPS等文件格式,支持的程度如何,即可否完全正確的讀出這些格式的文件。

應用軟件兼容性  主要考察兩項內容:一是軟件運行需要哪些其他應用軟件的支持,二是判斷與其他常用軟件如MS OFFICE,反病毒軟件一起使用,是否造成其他軟件運行錯誤或軟件本身不能正確實現其功能。

硬件兼容性  考察軟件對運行的硬件環境有無特殊說明,如對計算機的型號,網卡的型號、聲卡的型號、顯卡的型號等有無特別的聲明,有些軟件可能在不同的硬件環境中,出現不同的運行結果或是根本就不能執行。

以上一些方面是中國軟件評測中心在大量的軟件測試實踐中提煉出來的比較有共性的內容,對於不同類型的軟件,在兼容性方面還有更多的評測指標,並且依據實際情況側重點也有所不同。

例如在軟件升級的過程中,往往由於沒有考慮到原來的處理方式或者數據格式這樣的前向兼容,導致升降級失敗。

例如下面的命令字不兼容的有這樣的一個系統,如圖7-6所示。

image.png

7-6

 

上層軟件是由我們自己完成,而固件是購買的第三方,而所謂的固件,就是說這些軟件是一些邏輯性的軟件,是固化在硬件上。上層軟件和固件的通信是通過命令字的方式進行,按照道理這種方式應該是耦合性最弱的方式。另外上層軟件和固件由於是採用命令字方式,不是通過靜態的函數接口,所以其兩個部分都單獨可以發佈版本。其命令字通過如下枚舉的方式表示:

 

enum

{

CMD_INIT = 0,

CMD_GET_DEV,

CMD_SET_INFO,

CMD_GET_INFO,
}enm_COMMAND_DEVICE;

 

由於之前沒有充分考慮到枚舉類型應該分段表示(注:實際開發中常常存在這樣的情況,對於系統不可能完全考慮周全,對於這樣的細小部分可能很容易忽略掉,但是一旦釀成事故,就變得十分嚴重),所以其命令字按照編譯器的自動編號,將後面的枚舉值進行編號。

這種方式在開始時候還沒有引起大家的注意,原因是固件大多時候是不更新版本的,因此我們已經按照上面提供的命令字的版本發給了客戶使用。後來固件也進行版本更新,由於第三方提供商同時存在給不同的廠家供貨,所以他們也發佈一個新的版本。不過他們對命令字是這樣添加的。

 

enum

{

CMD_INIT = 0,

CMD_GET_DEV,

CMD_OTHER,//添加的新命令字

CMD_SET_INFO,

CMD_GET_INFO,
}enm_COMMAND_DEVICE;

 

結果導致命令字不兼容,我們就存在原來的上層軟件就無法配套新的固版本,新的上層軟件無法配套舊的固件版本。由於就是小小的接口命令字不兼容,導致我們不得不進行其他間接方式進行映射處理,同時向客戶道歉,屈辱地更新客戶當前運行的版本,真是勞力老財結果還不得一個好。

當然,對於一些並行處理的場景中,其實就算使用統一的處理機制也是容易導致衝突的,此時就需要通過一些方法來進行規避,例如在多版本並行開發中解決命令字衝突。

當前存在一個產品系列多個版本並行開發,而命令字的命名如果沒有統一管理情況下容易導致衝突,衝突的結果是相同命令字可能定義爲不同的編碼值,或者不同的命令字定義爲相同的編碼值,兩種情況都是非常危險的事情,而同時我們又不希望有這樣的管理工作,此時就可以使用分區分段的策略來解決衝突,同時又需要當衝突的時候能夠明確的通知給使用者,而我們在合理的做法就是形成編譯錯誤,只有修改了此衝突才能夠進行下一步的任務操作,這樣能夠有效的保證衝突發生而被忽略導致災難。

namespace nameA

{

enum enum_nameA

{

ID_COM_Base = 0,

    ID_NameA_Ver1 = 100,

    ID_NameA_Ver2 = 200,

}

}

namespace nameB

{

enum enum_nameB

{

ID_COM_Base = 0,

    ID_NameB_Ver1 = 100,

    ID_NameB_Ver2 = 200,

}

 

}

 

操作實現如下:

 

switch (CMD cmd)

{

case ID_COM_Base://如果此處編譯錯誤,表示你可能存在多個特性空間混雜的情況  

case ID_NameA_Ver1:

{

    

}

case ID_NameA_Ver2:

{

    

}

}

 

switch (CMD cmd)

{

case ID_COM_Base://如果此處編譯錯誤,表示你可能存在多個特性空間混雜的情況  

case ID_NameB_Ver1:

{

    

}

case ID_NameB_Ver2:

{

    

}

}

 

這裏爲什麼要定義一個相同的ID_COM_Base呢?這是因爲希望將nameAnameB兩個空間進行隔離,如果一旦混雜,則編譯器就會提醒ID_COM_Base命名衝突,一旦發生衝突,那麼在編譯時期就知道開發人員存在命令空間混亂的情況,所以此時可以提前就進行糾正,而不會向後運行和運營時期才發現問題。

當然如果存在混雜的應用,那麼可以使用nameA::ID_COM_BasenameB::ID_COM_Base來顯示進行描述。

雖然這只是一個技巧處理,但是,能夠幫助我們下面的好處:

ü 爲了減少管理的成本,每一個接口類都有自己的ID編號。

ü 在這些ID中進行分段劃分,此爲適用於多個版本並行開發中避免衝突。

出現衝突則需要修復以後才能繼續下一步工作,能夠從技術上保證低級錯誤導致災難。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章