趙昶宇
(天津津航計算技術研究所,天津300308)
導致軟件開發復雜化的因素有很多,比如越來越高的軟件安全性和可靠性要求,其中最關鍵的因素是問題領域本身。為了降低軟件復雜度,必須首先建立一個好的領域模型。該模型必須抓住領域的實質內容,并提供支持給相關軟件開發人員。
為了降低軟件耦合程度,簡化軟件設計,在軟件的研制流程中,基于領域驅動的建模需要相關領域專家和軟件開發人員結合領域專家的專業知識和軟件開發人員的專業技能,建立準確柔性的領域模型,以更好響應需求變更,并縮短軟件開發周期。對軟件開發團隊來說,多輪軟件重構將會建立準確的深層領域模型,不僅能夠極大地提高軟件的復用率,并且能夠在保證軟件質量的前提下提高軟件開發團隊的研制能力,使軟件具有較好的可擴展性。
近年來,基于領域驅動的設計思想已成為面向對象設計領域的新思潮。領域驅動的核心思想是通過消化大量知識,最終建立一個具備深層次領域知識和關鍵概念的模型。在領域驅動設計過程中,領域專家負責運用領域知識,軟件開發人員負責運用專業技能對領域進行建模,最終建立領域深層含義的模型。該模型不但能夠發現領域專家的關注點,還可以將其轉變為有效可行的設計。在基于領域模型進行建模時,需關注以下幾點:實現復雜巧妙的領域模型是需要花費很大心思和氣力的;在領域專家和開發人員的密切合作下,只有通過不斷重構才能構建深層次的領域模型;只有精通設計技巧才能實現并有效運用模型。
組合導航軟件是應用于組合導航系統內的實時嵌入式軟件,采集慣性器件信息,進行相應補償,依據指令完成對準,利用相關基準信息進行組合導航,對外提供速度、位置、姿態角和加速度等導航控制參數。
采用標準的分層架構模式,給導航軟件劃分層次,如表1所示。

表1 導航軟件的分層設計
在組合導航軟件的每一層內,通過優化設計,其實高內聚于他的下層,而與它的上層具有松耦合性。領域層負責保存所有與領域相關的代碼,該部分的代碼與用戶表示層、應用層以及基礎設施層的代碼是分開的。為了使領域模型具有豐富的含義和清晰的結構,在研究領域對象時需要重點關注如何表達領域模型,這樣才能夠獲取到領域知識,更易于維護彼此獨立的軟件層。
組合導航軟件各個層間的關系是松耦合的,且相鄰兩層之間是單向的依賴關系。上層元素通過調用下層元素的公共接口課直接使用或者操作下層的元素。而下層元素需要通過軟件架構模式(Observers模式或回調模式)與上層元素進行通信,用于實現上下層之間的連接。如果連接方式能夠保持領域層的獨立性,并且在設計領域對象時不考慮可能與其交互的用戶界面,則這種連接方式就是有效的。
基礎設施層(如底層通訊類CCommunicate)不會發起對領域層的操作,它處于領域層之下,不包含其所服務的領域中的知識,這樣應用層的元素就可以請求發送數據了,這樣的解耦使程序的功能更加清晰。消息發送接口可以按不同通訊形式發送出去(RS232、RS422、網口、1553b等)。這種方式最主要的好處是簡化了應用層,使其只專注于自己負責的事情:知道何時該發送信息,而不用關心如何發送。開發人員可以更加專注于核心領域問題的建模,這樣可以大大提高效率和軟件質量。
為提高系統精度,現在的組合導航系統中基本都包含卡爾曼濾波算法,以完成對準和組合功能。但由于系統特性差異,每個濾波器的實現有所不同。以往的做法中,每次研制新的導航軟件時,卡爾曼濾波器都會因濾波參數不同、基準信息頻率不同、濾波周期不同而將濾波算法重新設計實現,消耗資源大、更改時間長并且可靠性低。以下原因促使在濾波器算法設計中使用STRATEGY模式:①如果將組合和對準模塊中分別加入各自需要的卡爾曼濾波算法,會使得程序很大并且難以維護,尤其當需要支持多種卡爾曼算法時,問題會更嚴重;②軟件設計者往往希望在不同的時間使用不同的算法,但由于系統中軟件均為嵌入式軟件,空間資源有限,設計者不希望不使用的算法占用寶貴的空間;③如果卡爾曼濾波器成為程序中難以分割的成分(耦合度很高),增加新的卡爾曼濾波算法或改變現有算法將十分困難。
鑒于此,與深諳濾波算法的相關專家深入討論,在分析之前實現的多個濾波算法的基礎上,針對卡爾曼濾波器領域對象進行深入分析,發現每個濾波器的數據抽象部分基本一致,算法大體相同,僅濾波器初始化、計算系統矩陣、觀測量獲取等幾個行為有區別,因此采用STRATEGY設計模式來實現這種算法的不同變體。
利用STRATEGY模式定義一系列的算法,把變化部分單獨封裝起來。該模式使得算法可獨立于調用者而變化。將濾波器定義為kalman模板類,將各卡爾曼濾波器變化的行為部分抽象為基類(Mode),按照每個濾波器的特點定義子類。ⅠnitialValue、GetA、GetZ、GetH函數分別為參數初始化、計算系統矩陣、觀測量獲取等行為實現。用表示變化部分的mode類在濾波器對象構造時依據濾波特性進行模板匹配。
通過對濾波模型的多次重構得到了目前的模型,不僅可在研發過程中變更濾波需求,也能夠滿足新研項目對濾波器的需求,該濾波模型越來越接近柔性設計。利用該濾波模型的新研項目的濾波設計實現已經變得非常簡單和可靠。
在組合導航系統中,要依據系統當前狀態(如粗對準、精對準、組合導航)進行不同的行為動作,以往一般用大量嵌套switch/case語句分成互斥的幾個區域,完成不同狀態的規定動作。這樣的代碼不夠清晰,而且難以修改和擴展。state模式提供了一個更好的方式來組織與特定狀態相關的代碼。決定狀態轉移的邏輯不在單個的if或switch語句中,而是分布在state子類中。將每一個狀態轉換和動作封裝帶一個類中,使與特定狀態相關的行為局部化,并且使狀態轉換顯式化。把著眼點從執行狀態提高到整個對象的狀態,這樣使代碼結構化并且意圖更加清晰。
這一模式的關鍵思想是引入SysState的狀態抽象類,表達系統的運行狀態。SysState類為表示不同狀態的子類聲明了公共接口。SysState的子類實現與特定狀態相關的行為。工作狀態切換時需運行當前狀態的GoOut和下一狀態的ComeⅠn,完成狀態的切換,切換時的一次性動作都可以放入相應函數。將在該狀態下需要執行的動作放在Run函數。SysState類圖如圖1所示。

圖1 SysState類圖
有些與領域相關的操作從本質上講是活動或動作,而不是事物。但由于建模一般針對對象,因此很多時候會把它們劃歸到對象范疇,一個常見的錯誤設計是沒有為這類行為找到適合的對象,而是轉為過程化的編程。如果勉強將一個操作放到不符合對象定義的對象中,會產生概念上的混淆,而且會變得很難理解或重構。此類抽象除了所掌握的操作之外在領域內沒有其他意義。
若領域中某個重要的過程或轉換操作不屬于其他實體職責時,此時應在領域模型中增加一個SERVⅠCE操作。SERVⅠCE是一個獨立的接口操作,它一般以活動命名,強調與其他對象之間的關系,它只用于定義能為客戶做什么。在組合慣導系統中,在組合導航濾波算法中一般都會將接收到的衛星信息與慣性信息比較后進行有效性判斷,這個操作依賴衛星對象和慣性解算對象的信息,判斷的結果提供給組合導航濾波對象。將這個判斷行為單獨定義成類,從而實現了分離特定職責的效果,避免與其他對象耦合,有利于保持接口的簡單性。
利用領域模型建模可以讓軟件開發人員表達豐富、準確具有柔性的軟件功能需求,基于此功能需求實現的軟件能夠真正滿足用戶需求,是軟件設計的關鍵所在。結合設計模式的使用有助于準確建立模型,提高了軟件靈活性和可擴展性,大大降低了升級和移植的復雜度,降低了項目開發的風險,在保證軟件質量的前提下極大提升了軟件的研發速度