軟體中的質量屬性(二)
現在我們接著上一次的話題來看看其它的質量屬性。
互操作性 (Interoperability)
互操作性指的是系統內或者系統之間不同的元件可以有效地進行資訊交換,通常是以服務(Service)的形式來進行的。互操作性的關鍵因素包括通訊協議,介面定義,資料格式的定義等等,而標準化是實現互操作性的重要手段。
實現互操作性的主要挑戰有以下這些方面:
-
系統內部或者和已有的舊系統(legacy system)之間的資料定義不一致
-
系統的邊界模糊,模組之間耦合嚴重,導致資料冗餘
-
缺乏標準,或者各方對標準的實現和認識不一致
我現在所在的商務智慧團隊的總架構師(Chief Architect)就一直在部門間推動對資料文件統一格式標準的定義和實現。這本身對於我們產品內部的互操作性是非常有必要的,然而BI的團隊分佈在各個大洲(主要是德國,法國,加拿大,中國和印度),每個部門對各自產品優先順序的認識不一致,在加上對舊系統相容性的要求,這項工作的進展非常非常的緩慢。BI的各個產品仍然很難互操作。
我之前開發過通訊網管,當時做的產品是統一網管平臺,就是把各個廠商(華為,中興,朗訊等等)的電信裝置統一的管理起來。當時已經有了相當成熟的電信網管理標準(TMF,ISO等標準)和技術標準(Q3,Corba)。然而理解的不同,廠商對標準的實現千奇百怪,所以實際上需要給每一個廠商定製不同的介面介面卡。我當時就在負責一些這樣的介面開發。
面向服務的架構(SOA)曾經是一個非常熱門的詞彙,現在似乎不怎麼提起了。我司當年曾經大張旗鼓的宣傳SOA。其實這樣的架構能夠解決的一個主要的問題就在能夠把企業內部各種已有系統通過暴露標準服務介面的方式有效的協調起來。
為了實現互操作性,我們一般需要
-
定義標準的資料格式和語義
-
定義標準的服務介面,並使用基於服務的架構
-
設計高內聚,低耦合的模組以獲得最大的靈活性和可重用性
可維護性 (Maintainability)
可維護性有兩個不同的角度,一個是指從軟體使用者和運維人員的角度,另一個是從軟體開發人員的角度。
從使用者和運維人員的角度,軟體的可維護性是指軟體是不是容易安裝,升級,打補丁,有了問題是不是容易修復,能不能很容易的獲得支援。
從開發人員的角度,軟體的可維護性是指軟體的架構是不是清楚簡單,程式碼是不是容易閱讀,有了問題是不是容易定位錯誤的原因,有沒有可以提供幫助的文件,等等。
軟體系統可維護性的主要問題有:
-
模組之間緊耦合導致無法或很難對單獨的模組進行修改,替換和升級
-
在高層直接使用底層協議和介面,導致無法替換物理裝置實體
-
沒有有效的分層和責任的劃分,導致一個腫大的模組以及巨大的程式碼出現在同一個檔案甚至函式中。
-
沒有幫助和設計文件
-
為了相容舊系統而不得不同時存在兩個以上的複雜的程式碼棧甚至技術不同的實現
知道了問題,改進的建議是非常明顯的,我要討論的是一個關於程式碼可讀性的有趣話題。
很多人都認為,程式碼是寫給人看的,它碰巧也能被計算機讀懂。所以我們應該像寫文學作品那樣寫程式碼。碰巧我也非常的贊同這樣的觀點。然而,最近的一篇文章提到另一種觀點,程式碼不是文學作品,我們不是閱讀而是評審。這篇文章也許能夠幫助你改善程式碼評審。不管程式碼是不是文學作品,寫出容易閱讀的程式碼對於提高軟體的可維護性的好處是不言而喻的。
效能(Performance)
效能也許是軟體開發中最被重視的質量屬性,也是最特殊的一個,從它的英文名字中不以(-ility)為字尾,我們可以看到他的特殊性。我們通常以系統執行某操作所需要的響應時間(latency)或者在某單位時間所能完成的任務的數量(throughput)來定義效能指標。
效能和其它的質量屬性的相關性很高,有一些會對效能產生正面影響,有一些則是負面的。
記得我當年參加一個關於C++效能優化的培訓,有一道演算法,要求大家試著用最快的方式實現。因為C++中的指標操作按陣列索引訪問要快,於是當時最快的一個解決方案是用了一大推複雜指標訪問來實現演算法。然而這樣的程式碼很難維護,而且容易出錯。所以為提高效能就犧牲了可維護性。
一般而言,計算機提供了許多的資源,包括CPU,記憶體,硬碟等等,提高效能的核心就是充分利用這些資源。要保證對資源的使用是正確和有效的。通常提高效能的考慮包括:
-
利用快取(空間換時間)
-
設計高效的資源共享,多執行緒,多程序,鎖
-
非同步
-
減少模組見得資訊傳遞
-
使介面設計傳遞最小所需的資訊
-
增加系統的可伸縮性,是系統能夠有效的部署在分散式的資源上
另外我們還需要考慮另一個性能,就是程式設計師實現功能的效能。隨著軟體的發展,現在的程式設計師可以更高效的實現功能需求。一方面程式語言和方法在不斷進步,另一方面大量的可重複使用的元件,服務,開源的庫使得想在實現同樣的功能的時間和需要的開發人員的數量比以前極大的縮小了。whatsapp以區區55人的團隊開發出價值190億美元,擁有4.5億使用者的軟體產品,這在以前是難以想象的。所以軟體架構設計者應該把軟體的開發效率看成是更重要的效能指標。
可重用性 (Reusability)
老闆一般都非常重視可重用性,因為如果把軟體程式碼看成產品,那麼如果該產品如果只能用一次就扔掉,那他顯然是很不開心的,因為這是一筆很糟糕的投入。在我的軟體開發生涯這麼多年以來,我體驗的軟體的可重用性都不是很高,也許是我大多在大型的軟體企業服務有關。大企業的特點就是團隊非常多,產品非常豐富,老闆經常更換。每一個新的老闆上臺後,面臨一大堆功能技術各異的系統都非常的不happy,於是整合在所難免,如何重用已有的系統來實現一個新的,大一統的新產品成了重中之重。然而這並不比找到宇宙中的終極大一統理論更簡單。最終的整合結果往往並不能有效的重用已有的系統,當老闆因為各種原因離開時,我們會發現,對新的老闆來說,整合的任務變得更加艱鉅了,因為,又有一個新的系統需要整合了。
提高可重用性的一個最主要的原則就是避免重複,“Don't repeat yourself!”我想大家應該非常熟悉了,這裡就不多說了。
在成熟度不高的開發團隊中(很不幸,我們大多數人都處在這樣的團隊中),對程式碼的重用很難,其實只有人才是最可靠的可重用元件,人離開了,所有的可重用性也就跟著離開了。
伸縮性(Scalability)
伸縮性要求軟體系統能夠跟著所需處理的工作量相應的伸縮。例如如果計算機是多CPU多核心的,軟體是否能夠相應的利用到這些計算資源。另一個方面就是軟體是不是能夠部署到分散式的網路,有效的利用網路中的每一個節點的資源。
有兩個方向的伸縮,垂直和水平。
在垂直方向的伸縮(scale up)是指提高單節點的處理能力,比如提高CPU主頻和核心數,增大記憶體,增大磁碟容量等等。SAP的HANA就是一個典型的垂直方向的伸縮。
在水平方向的伸縮(scale out)通常是指通過併發和分佈的方式來增加節點以提高處理能力。Hadoop就是一個很好地水平伸縮的例子。
設計高伸縮性的軟體時,我們可以考慮
-
避免有狀態的服務或元件
-
使用配置檔案決定元件的的部署和關係
-
考慮支援資料的分割槽
-
避免統一層的責任跨越不同的物理實體
在雲時代,軟體的伸縮性越發重要。
可測試性(Testability)
可測試性顧名思義就是指軟體是否容易測試。
什麼樣的軟體是不可測試的呢?舉個例子來說,我們曾經開發過一個數據視覺化的元件,就是把資料以圖表的形式展現出來。有一種資料視覺化的型別使用力導向的演算法(force-directed)把資料以網路拓撲圖的形式展現出來,該演算法使用一些隨機的引數來模擬節點的初始位置,並通過迭代計算生成最終layout的結果。也就是說每次的layout結果都是不一樣的。測試團隊對這樣的演算法很不滿意,他們認為這樣的實現是無法測試的,因為當時我們的測試主要以比對圖形為基礎,也就是生成一個正確的圖形為基準,每次測試都會把輸出的圖形和基準圖形進行比較,如果不一致則認為出錯或者要修改基準。隨機演算法雖然從功能上講並沒有錯誤,但是在這樣的測試方法下是無法滿足可測試性的要求的。最後,開發團隊修改了演算法,使得每次的初始位置未固定位置來解決這個問題。
David Catlett提出了一個SOCK模型可以有效地幫助我們瞭解可測試性的要素
-
Simple
程式碼越簡單越容易測試。 -
Observable
軟體系統應該是可觀測,無法觀測也就無法衡量 -
Control
軟體系統應該是可以控制的,儘可能多的把控制權暴露給測試模組。 -
Knowledge
測試人員或者模組需要更多地理解被測試模組,理解的越多也就越容易測試(白盒測試)
軟體質量屬性的每一個方面都有很多的內容,我們只能淺嘗而止,而且仍然有許多重要的質量屬性我們還沒有涉及到,有時間的話,我們以後再說。