趙昶宇
(天津津航計算技術(shù)研究所,天津300308)
導(dǎo)致軟件開發(fā)復(fù)雜化的因素有很多,比如越來越高的軟件安全性和可靠性要求,其中最關(guān)鍵的因素是問題領(lǐng)域本身。為了降低軟件復(fù)雜度,必須首先建立一個好的領(lǐng)域模型。該模型必須抓住領(lǐng)域的實質(zhì)內(nèi)容,并提供支持給相關(guān)軟件開發(fā)人員。
為了降低軟件耦合程度,簡化軟件設(shè)計,在軟件的研制流程中,基于領(lǐng)域驅(qū)動的建模需要相關(guān)領(lǐng)域?qū)<液蛙浖_發(fā)人員結(jié)合領(lǐng)域?qū)<业膶I(yè)知識和軟件開發(fā)人員的專業(yè)技能,建立準(zhǔn)確柔性的領(lǐng)域模型,以更好響應(yīng)需求變更,并縮短軟件開發(fā)周期。對軟件開發(fā)團(tuán)隊來說,多輪軟件重構(gòu)將會建立準(zhǔn)確的深層領(lǐng)域模型,不僅能夠極大地提高軟件的復(fù)用率,并且能夠在保證軟件質(zhì)量的前提下提高軟件開發(fā)團(tuán)隊的研制能力,使軟件具有較好的可擴(kuò)展性。
近年來,基于領(lǐng)域驅(qū)動的設(shè)計思想已成為面向?qū)ο笤O(shè)計領(lǐng)域的新思潮。領(lǐng)域驅(qū)動的核心思想是通過消化大量知識,最終建立一個具備深層次領(lǐng)域知識和關(guān)鍵概念的模型。在領(lǐng)域驅(qū)動設(shè)計過程中,領(lǐng)域?qū)<邑?fù)責(zé)運用領(lǐng)域知識,軟件開發(fā)人員負(fù)責(zé)運用專業(yè)技能對領(lǐng)域進(jìn)行建模,最終建立領(lǐng)域深層含義的模型。該模型不但能夠發(fā)現(xiàn)領(lǐng)域?qū)<业年P(guān)注點,還可以將其轉(zhuǎn)變?yōu)橛行Э尚械脑O(shè)計。在基于領(lǐng)域模型進(jìn)行建模時,需關(guān)注以下幾點:實現(xiàn)復(fù)雜巧妙的領(lǐng)域模型是需要花費很大心思和氣力的;在領(lǐng)域?qū)<液烷_發(fā)人員的密切合作下,只有通過不斷重構(gòu)才能構(gòu)建深層次的領(lǐng)域模型;只有精通設(shè)計技巧才能實現(xiàn)并有效運用模型。
組合導(dǎo)航軟件是應(yīng)用于組合導(dǎo)航系統(tǒng)內(nèi)的實時嵌入式軟件,采集慣性器件信息,進(jìn)行相應(yīng)補(bǔ)償,依據(jù)指令完成對準(zhǔn),利用相關(guān)基準(zhǔn)信息進(jìn)行組合導(dǎo)航,對外提供速度、位置、姿態(tài)角和加速度等導(dǎo)航控制參數(shù)。
采用標(biāo)準(zhǔn)的分層架構(gòu)模式,給導(dǎo)航軟件劃分層次,如表1所示。
表1 導(dǎo)航軟件的分層設(shè)計
在組合導(dǎo)航軟件的每一層內(nèi),通過優(yōu)化設(shè)計,其實高內(nèi)聚于他的下層,而與它的上層具有松耦合性。領(lǐng)域?qū)迂?fù)責(zé)保存所有與領(lǐng)域相關(guān)的代碼,該部分的代碼與用戶表示層、應(yīng)用層以及基礎(chǔ)設(shè)施層的代碼是分開的。為了使領(lǐng)域模型具有豐富的含義和清晰的結(jié)構(gòu),在研究領(lǐng)域?qū)ο髸r需要重點關(guān)注如何表達(dá)領(lǐng)域模型,這樣才能夠獲取到領(lǐng)域知識,更易于維護(hù)彼此獨立的軟件層。
組合導(dǎo)航軟件各個層間的關(guān)系是松耦合的,且相鄰兩層之間是單向的依賴關(guān)系。上層元素通過調(diào)用下層元素的公共接口課直接使用或者操作下層的元素。而下層元素需要通過軟件架構(gòu)模式(Observers模式或回調(diào)模式)與上層元素進(jìn)行通信,用于實現(xiàn)上下層之間的連接。如果連接方式能夠保持領(lǐng)域?qū)拥莫毩⑿裕⑶以谠O(shè)計領(lǐng)域?qū)ο髸r不考慮可能與其交互的用戶界面,則這種連接方式就是有效的。
基礎(chǔ)設(shè)施層(如底層通訊類CCommunicate)不會發(fā)起對領(lǐng)域?qū)拥牟僮?,它處于領(lǐng)域?qū)又?,不包含其所服?wù)的領(lǐng)域中的知識,這樣應(yīng)用層的元素就可以請求發(fā)送數(shù)據(jù)了,這樣的解耦使程序的功能更加清晰。消息發(fā)送接口可以按不同通訊形式發(fā)送出去(RS232、RS422、網(wǎng)口、1553b等)。這種方式最主要的好處是簡化了應(yīng)用層,使其只專注于自己負(fù)責(zé)的事情:知道何時該發(fā)送信息,而不用關(guān)心如何發(fā)送。開發(fā)人員可以更加專注于核心領(lǐng)域問題的建模,這樣可以大大提高效率和軟件質(zhì)量。
為提高系統(tǒng)精度,現(xiàn)在的組合導(dǎo)航系統(tǒng)中基本都包含卡爾曼濾波算法,以完成對準(zhǔn)和組合功能。但由于系統(tǒng)特性差異,每個濾波器的實現(xiàn)有所不同。以往的做法中,每次研制新的導(dǎo)航軟件時,卡爾曼濾波器都會因濾波參數(shù)不同、基準(zhǔn)信息頻率不同、濾波周期不同而將濾波算法重新設(shè)計實現(xiàn),消耗資源大、更改時間長并且可靠性低。以下原因促使在濾波器算法設(shè)計中使用STRATEGY模式:①如果將組合和對準(zhǔn)模塊中分別加入各自需要的卡爾曼濾波算法,會使得程序很大并且難以維護(hù),尤其當(dāng)需要支持多種卡爾曼算法時,問題會更嚴(yán)重;②軟件設(shè)計者往往希望在不同的時間使用不同的算法,但由于系統(tǒng)中軟件均為嵌入式軟件,空間資源有限,設(shè)計者不希望不使用的算法占用寶貴的空間;③如果卡爾曼濾波器成為程序中難以分割的成分(耦合度很高),增加新的卡爾曼濾波算法或改變現(xiàn)有算法將十分困難。
鑒于此,與深諳濾波算法的相關(guān)專家深入討論,在分析之前實現(xiàn)的多個濾波算法的基礎(chǔ)上,針對卡爾曼濾波器領(lǐng)域?qū)ο筮M(jìn)行深入分析,發(fā)現(xiàn)每個濾波器的數(shù)據(jù)抽象部分基本一致,算法大體相同,僅濾波器初始化、計算系統(tǒng)矩陣、觀測量獲取等幾個行為有區(qū)別,因此采用STRATEGY設(shè)計模式來實現(xiàn)這種算法的不同變體。
利用STRATEGY模式定義一系列的算法,把變化部分單獨封裝起來。該模式使得算法可獨立于調(diào)用者而變化。將濾波器定義為kalman模板類,將各卡爾曼濾波器變化的行為部分抽象為基類(Mode),按照每個濾波器的特點定義子類。ⅠnitialValue、GetA、GetZ、GetH函數(shù)分別為參數(shù)初始化、計算系統(tǒng)矩陣、觀測量獲取等行為實現(xiàn)。用表示變化部分的mode類在濾波器對象構(gòu)造時依據(jù)濾波特性進(jìn)行模板匹配。
通過對濾波模型的多次重構(gòu)得到了目前的模型,不僅可在研發(fā)過程中變更濾波需求,也能夠滿足新研項目對濾波器的需求,該濾波模型越來越接近柔性設(shè)計。利用該濾波模型的新研項目的濾波設(shè)計實現(xiàn)已經(jīng)變得非常簡單和可靠。
在組合導(dǎo)航系統(tǒng)中,要依據(jù)系統(tǒng)當(dāng)前狀態(tài)(如粗對準(zhǔn)、精對準(zhǔn)、組合導(dǎo)航)進(jìn)行不同的行為動作,以往一般用大量嵌套switch/case語句分成互斥的幾個區(qū)域,完成不同狀態(tài)的規(guī)定動作。這樣的代碼不夠清晰,而且難以修改和擴(kuò)展。state模式提供了一個更好的方式來組織與特定狀態(tài)相關(guān)的代碼。決定狀態(tài)轉(zhuǎn)移的邏輯不在單個的if或switch語句中,而是分布在state子類中。將每一個狀態(tài)轉(zhuǎn)換和動作封裝帶一個類中,使與特定狀態(tài)相關(guān)的行為局部化,并且使?fàn)顟B(tài)轉(zhuǎn)換顯式化。把著眼點從執(zhí)行狀態(tài)提高到整個對象的狀態(tài),這樣使代碼結(jié)構(gòu)化并且意圖更加清晰。
這一模式的關(guān)鍵思想是引入SysState的狀態(tài)抽象類,表達(dá)系統(tǒng)的運行狀態(tài)。SysState類為表示不同狀態(tài)的子類聲明了公共接口。SysState的子類實現(xiàn)與特定狀態(tài)相關(guān)的行為。工作狀態(tài)切換時需運行當(dāng)前狀態(tài)的GoOut和下一狀態(tài)的ComeⅠn,完成狀態(tài)的切換,切換時的一次性動作都可以放入相應(yīng)函數(shù)。將在該狀態(tài)下需要執(zhí)行的動作放在Run函數(shù)。SysState類圖如圖1所示。
圖1 SysState類圖
有些與領(lǐng)域相關(guān)的操作從本質(zhì)上講是活動或動作,而不是事物。但由于建模一般針對對象,因此很多時候會把它們劃歸到對象范疇,一個常見的錯誤設(shè)計是沒有為這類行為找到適合的對象,而是轉(zhuǎn)為過程化的編程。如果勉強(qiáng)將一個操作放到不符合對象定義的對象中,會產(chǎn)生概念上的混淆,而且會變得很難理解或重構(gòu)。此類抽象除了所掌握的操作之外在領(lǐng)域內(nèi)沒有其他意義。
若領(lǐng)域中某個重要的過程或轉(zhuǎn)換操作不屬于其他實體職責(zé)時,此時應(yīng)在領(lǐng)域模型中增加一個SERVⅠCE操作。SERVⅠCE是一個獨立的接口操作,它一般以活動命名,強(qiáng)調(diào)與其他對象之間的關(guān)系,它只用于定義能為客戶做什么。在組合慣導(dǎo)系統(tǒng)中,在組合導(dǎo)航濾波算法中一般都會將接收到的衛(wèi)星信息與慣性信息比較后進(jìn)行有效性判斷,這個操作依賴衛(wèi)星對象和慣性解算對象的信息,判斷的結(jié)果提供給組合導(dǎo)航濾波對象。將這個判斷行為單獨定義成類,從而實現(xiàn)了分離特定職責(zé)的效果,避免與其他對象耦合,有利于保持接口的簡單性。
利用領(lǐng)域模型建??梢宰屲浖_發(fā)人員表達(dá)豐富、準(zhǔn)確具有柔性的軟件功能需求,基于此功能需求實現(xiàn)的軟件能夠真正滿足用戶需求,是軟件設(shè)計的關(guān)鍵所在。結(jié)合設(shè)計模式的使用有助于準(zhǔn)確建立模型,提高了軟件靈活性和可擴(kuò)展性,大大降低了升級和移植的復(fù)雜度,降低了項目開發(fā)的風(fēng)險,在保證軟件質(zhì)量的前提下極大提升了軟件的研發(fā)速度