吳松森,陳曉陽(yáng),高春陽(yáng)
(洛陽(yáng)電光設(shè)備研究所,河南 洛陽(yáng) 471000)
隨著嵌入式系統(tǒng)在航空、航天、航海等領(lǐng)域的應(yīng)用不斷拓展,軟件定義系統(tǒng)已成為一種趨勢(shì),未來(lái)嵌入式軟件必然會(huì)承擔(dān)越來(lái)越多的使命,同時(shí)也將面臨越來(lái)越多的問題。現(xiàn)有嵌入式軟件的規(guī)模急劇提升,而軟件的復(fù)雜度與軟件規(guī)模呈非線性正相關(guān),在超10萬(wàn)行的軟件規(guī)模下,已經(jīng)引起了軟件復(fù)雜度的“質(zhì)變”,為軟件開發(fā)與維護(hù)帶來(lái)巨大困難。同時(shí),為不斷適應(yīng)新的使用場(chǎng)景以及平臺(tái)能力持續(xù)提升,嵌入式軟件的需求頻繁變更,部分產(chǎn)品軟件甚至可每年變更數(shù)十次以上,在愈發(fā)龐大的軟件規(guī)模體量下,任何軟件變更都可能帶來(lái)巨大的工作量與不可預(yù)知的改動(dòng)風(fēng)險(xiǎn),從而延伸出了以下問題:(1)傳統(tǒng)的軟件開發(fā)模式已不再適用,相似功能重復(fù)性開發(fā)帶來(lái)巨大的人力開銷,導(dǎo)致軟件開發(fā)人員與軟件任務(wù)之間的矛盾更加激化;(2)在軟件復(fù)雜度不斷提升的情況下,軟件質(zhì)量隱患逐漸加大,軟件開發(fā)人員水平對(duì)軟件質(zhì)量的影響更加凸顯,軟件維護(hù)成本增加;(3)由于軟件規(guī)模增大,在沒有解決軟件內(nèi)部的復(fù)雜耦合關(guān)系之前,新增功能的影響域增大,新功能的集成、驗(yàn)證成本增加。
良好的軟件架構(gòu)可以在軟件設(shè)計(jì)之初就規(guī)范好組件間接口、組件間關(guān)系、組件與環(huán)境之間的關(guān)系,能夠有效降低系統(tǒng)復(fù)雜性所帶來(lái)的各種影響。針對(duì)復(fù)雜嵌入式系統(tǒng),如何建立一套高內(nèi)聚、松耦合、易復(fù)用、能有效適應(yīng)需求變化的軟件架構(gòu),成為本文亟待研究的問題。
復(fù)雜嵌入式系統(tǒng)軟件架構(gòu)要解決的主要問題可以概括為以下3點(diǎn):(1)復(fù)雜度分解問題;(2)面對(duì)需求變化的適應(yīng)性與靈活擴(kuò)展能力問題;(3)成熟功能的移植復(fù)用問題。針對(duì)上述問題,本文結(jié)合領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)技術(shù)、面向服務(wù)架構(gòu)、微服務(wù)架構(gòu)等進(jìn)行分析研究,致力于尋求一種解決軟件復(fù)雜度問題的有效方案。
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain-Driven Design,DDD)[1]是在2004年提出的一種開放的設(shè)計(jì)方法體系,其核心思想在于根據(jù)“領(lǐng)域”進(jìn)行復(fù)雜問題拆分,總的原則是將原來(lái)復(fù)雜的問題拆分成多個(gè)單獨(dú)的簡(jiǎn)單問題進(jìn)行求解。DDD強(qiáng)調(diào)業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)分離[2],更加關(guān)注業(yè)務(wù)復(fù)雜度分解以及業(yè)務(wù)上下文邊界的界定,對(duì)于解決復(fù)雜的軟件問題具有重要參考價(jià)值。
1.1.1 DDD分層架構(gòu)
典型的DDD分層架構(gòu)如圖1所示,該架構(gòu)遵循了“關(guān)注點(diǎn)分離”原則[3],將屬于業(yè)務(wù)邏輯的關(guān)注點(diǎn)放到領(lǐng)域?qū)?Domain Layer)中,而將支撐業(yè)務(wù)邏輯的技術(shù)實(shí)現(xiàn)放到基礎(chǔ)設(shè)施層(Infrastructure Layer)中,應(yīng)用層確定了兩者之間的邊界,通過(guò)依賴注入(Dependency Injection,DI)的方式將二者有機(jī)結(jié)合起來(lái)。
圖1 DDD分層架構(gòu)
1.1.2 六邊形架構(gòu)
由Alistair Cockburn提出的六邊形架構(gòu)如圖2所示[4],通過(guò)由內(nèi)向外“剝洋蔥式”逐級(jí)分離的方式,將核心領(lǐng)域業(yè)務(wù)放在了架構(gòu)的核心位置,應(yīng)用層作為領(lǐng)域核心與外圍適配器的轉(zhuǎn)換,由內(nèi)向外依次從“穩(wěn)定”到“易變”。該架構(gòu)通過(guò)端口適配的方法[5],讓外部易變的部分依賴于逐層穩(wěn)定的模型,間接保證核心業(yè)務(wù)代碼不受外部變化的影響,從而提升了系統(tǒng)靈活性。
圖2 典型的六邊形架構(gòu)
面向服務(wù)架構(gòu)(Service-Oriented Architecture,SOA)[6-7]將應(yīng)用程序的不同功能單元進(jìn)行拆分,通過(guò)一系列接口和統(tǒng)一的協(xié)議來(lái)進(jìn)行數(shù)據(jù)交互和互相依賴。SOA架構(gòu)的核心思想是互操作、復(fù)用、松耦合。DDD更注重業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)分離以及業(yè)務(wù)邏輯層面的解耦,SOA更注重于功能的服務(wù)化以及良好接口設(shè)計(jì),二者并不沖突,甚至可以有機(jī)結(jié)合,實(shí)現(xiàn)更好的效果。面向服務(wù)設(shè)計(jì)的思想對(duì)于實(shí)現(xiàn)功能單元界面劃分及可復(fù)用功能組件具有非常大的借鑒意義。
微服務(wù)架構(gòu)將應(yīng)用程序構(gòu)建為松耦合、可獨(dú)立部署的一組服務(wù)[8-9]。相對(duì)比SOA思想,微服務(wù)架構(gòu)對(duì)服務(wù)層進(jìn)行細(xì)粒度的拆分,所拆分的每個(gè)服務(wù)只完成某個(gè)特定的業(yè)務(wù)功能,服務(wù)的粒度很小,所以稱為微服務(wù)[10]。由于服務(wù)顆粒度細(xì)、職責(zé)單一,微服務(wù)更加有利于資源的重復(fù)利用。對(duì)于外部交聯(lián)關(guān)系復(fù)雜的嵌入式系統(tǒng),往往存在多種對(duì)外通信方式,如離散量、模擬量、FC總線、CAN總線、RS422總線等,因此非常適用借鑒微服務(wù)架構(gòu)思想,為每種通信方式實(shí)現(xiàn)一種微服務(wù),通過(guò)多種微服務(wù)組合支撐系統(tǒng)功能實(shí)現(xiàn)。
上述架構(gòu)的對(duì)比分析結(jié)果為復(fù)雜嵌入式系統(tǒng)的軟件架構(gòu)設(shè)計(jì)提供了可供借鑒的思路,具體如表1所示。
表1 軟件技術(shù)分析對(duì)比
不同利益相關(guān)角色對(duì)于軟件架構(gòu)的訴求和關(guān)注點(diǎn)各不相同。用戶更關(guān)注產(chǎn)品運(yùn)行的可靠性和易維護(hù)性;產(chǎn)品的總體設(shè)計(jì)人員要求軟件架構(gòu)能夠快速完成高質(zhì)量的軟件開發(fā),對(duì)需求有良好的適應(yīng)性,同時(shí)出現(xiàn)產(chǎn)品故障時(shí)應(yīng)能快速定位與解決;軟件需求人員更關(guān)心軟件需求與軟件架構(gòu)之間追溯關(guān)系清晰明確,能夠支持關(guān)鍵需求的覆蓋及實(shí)現(xiàn);對(duì)于軟件開發(fā)人員,軟件架構(gòu)應(yīng)該內(nèi)層次關(guān)系清晰明確,能夠支持軟件設(shè)計(jì)人員進(jìn)行軟件設(shè)計(jì),減少設(shè)計(jì)工作量;軟件測(cè)試人員則要求軟件架構(gòu)具備易讀性、可觀測(cè)性,功能、接口明確,方便測(cè)試。
結(jié)合上述設(shè)計(jì)目標(biāo),為滿足業(yè)務(wù)場(chǎng)景、利益攸關(guān)方等需求,復(fù)雜嵌入式系統(tǒng)軟件的非功能需求可定義如下。(1)開放性:架構(gòu)應(yīng)具備良好的開放性,各功能模塊松耦合、高內(nèi)聚,能夠很好地適應(yīng)變化、支持?jǐn)U展。(2)服務(wù)化:架構(gòu)應(yīng)具有良好的服務(wù)化設(shè)計(jì),能夠?yàn)樾鹿δ芗商峁┓€(wěn)定的服務(wù)化接口,支持新功能快速集成。(3)通用化:架構(gòu)中的基礎(chǔ)設(shè)施、服務(wù)化組件、應(yīng)用層組件等應(yīng)具有一定的通用化設(shè)計(jì),支持跨產(chǎn)品移植復(fù)用。
綜合上述分析,要實(shí)現(xiàn)復(fù)雜嵌入式系統(tǒng)下通用軟件架構(gòu),本文擬采用領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)思想,結(jié)合領(lǐng)域?qū)<覙I(yè)務(wù)經(jīng)驗(yàn)以及面向?qū)ο蟮募夹g(shù)手段完成軟件的服務(wù)化實(shí)現(xiàn)。具體設(shè)計(jì)思想可以概括如下。
(1)分治思想。分而治之思想是領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)思想中一項(xiàng)核心設(shè)計(jì)思想,就是把復(fù)雜問題分解為若干簡(jiǎn)單問題來(lái)簡(jiǎn)化。采用分治思想,會(huì)使每個(gè)小功能模塊更加容易開發(fā)且不易出錯(cuò),同時(shí)能夠支持多人分布開發(fā),提升開發(fā)效率。主要原則如下:采用分層設(shè)計(jì),使不同業(yè)務(wù)關(guān)注點(diǎn)分離;遵循“單一職責(zé)”原則,應(yīng)按照模塊、類、函數(shù)等逐層分解,最小原子程序只完成一個(gè)功能;經(jīng)分割后的兩個(gè)功能模塊之間的依賴關(guān)系應(yīng)簡(jiǎn)單、穩(wěn)定、弱相關(guān);對(duì)于難以劃分歸屬關(guān)系的功能,優(yōu)先從適應(yīng)變化方面考慮。
(2)適應(yīng)變化。在嵌入式業(yè)務(wù)領(lǐng)域,一個(gè)最大的特點(diǎn)就是“變化”,因此,通用軟件架構(gòu)必須能夠適應(yīng)變化。主要原則如下:新增功能帶來(lái)的變化應(yīng)不影響原有軟件功能,最好不涉及任何原有軟件代碼更改;任何功能模塊對(duì)新增需求應(yīng)具有良好的擴(kuò)展性,最好只增加代碼,不更改代碼;任何需求變更的影響域應(yīng)相對(duì)集中,最好一個(gè)需求變更應(yīng)只影響一個(gè)功能模塊,不影響其他功能模塊。
基于上述設(shè)計(jì)思路,結(jié)合復(fù)雜嵌入式系統(tǒng)特點(diǎn),本文采用分層設(shè)計(jì)[11-13]將系統(tǒng)軟件架構(gòu)分解為應(yīng)用層、服務(wù)層、資源層,同時(shí)整體架構(gòu)依賴于基礎(chǔ)設(shè)施實(shí)現(xiàn)系統(tǒng)功能,軟件架構(gòu)如圖3所示。
圖3 軟件架構(gòu)
資源層主要用于部署與運(yùn)行平臺(tái)相關(guān)的資源組件,包括操作系統(tǒng)、運(yùn)行時(shí)庫(kù)、離散量驅(qū)動(dòng)、總線驅(qū)動(dòng)、文件系統(tǒng)驅(qū)動(dòng)等,通過(guò)完成驅(qū)動(dòng)集成與封裝,為應(yīng)用層、服務(wù)層提供穩(wěn)定的資源訪問接口。一方面,資源層對(duì)上訪問接口的統(tǒng)一封裝有利于更換硬件平臺(tái)時(shí)不影響應(yīng)用層及服務(wù)層軟件,另一方面,根據(jù)測(cè)試先行的設(shè)計(jì)理念,嵌入式軟件在開發(fā)時(shí)需持續(xù)開展測(cè)試,資源層可兼顧全數(shù)字仿真環(huán)境下的測(cè)試激勵(lì)注入,有利于擺脫硬件平臺(tái)對(duì)核心邏輯測(cè)試的約束,更好地完成持續(xù)集成、持續(xù)測(cè)試。
服務(wù)層主要用于部署服務(wù)組件,向下通過(guò)資源層屏蔽與底層操作系統(tǒng)之間的耦合,向上通過(guò)服務(wù)接口向應(yīng)用組件提供功能服務(wù),是架構(gòu)中的核心組成部分,包括領(lǐng)域服務(wù)和基礎(chǔ)服務(wù)兩種。(1)領(lǐng)域服務(wù)組件與特定應(yīng)用領(lǐng)域相關(guān),通過(guò)對(duì)系統(tǒng)中特定領(lǐng)域核心邏輯的抽象,確定領(lǐng)域內(nèi)、外部功能剖面及統(tǒng)一的服務(wù)接口,通過(guò)可重用化設(shè)計(jì)方法提取共性,具備一定的跨平臺(tái)移植的能力。領(lǐng)域服務(wù)組件可調(diào)用基礎(chǔ)服務(wù),包括但不限于軟件版本服務(wù)、故障處理服務(wù)、健康管理服務(wù)等。(2)基礎(chǔ)服務(wù)組件要用于為其他模塊提供基礎(chǔ)服務(wù),包括但不限于以下服務(wù)??偩€服務(wù):用于對(duì)外提供FC總線、CAN總線、RS422總線等總線消息隊(duì)列的統(tǒng)一管理、消息重發(fā)機(jī)制、消息發(fā)送間隔控制機(jī)制等服務(wù)。離散量服務(wù):用于對(duì)外提供離散量信號(hào)的抖動(dòng)濾波、多路決策等功能。模擬量服務(wù):用于對(duì)外提供模擬量信號(hào)的濾波、平滑等功能;定時(shí)器服務(wù):用于對(duì)外提供定時(shí)器、時(shí)間獲取、時(shí)間間隔控制等功能;日志服務(wù):用于對(duì)外提供系統(tǒng)運(yùn)行過(guò)程中信息存儲(chǔ)與記錄功能。
應(yīng)用層主要用于部署與具體外部接口相關(guān)業(yè)務(wù)邏輯相關(guān)的應(yīng)用組件,完成系統(tǒng)的綜合處理與控制功能,向上實(shí)現(xiàn)外部接口與服務(wù)層之間的適配轉(zhuǎn)換,向下調(diào)用統(tǒng)一的服務(wù)接口,而不關(guān)心具體底層服務(wù)類接口的實(shí)現(xiàn)。相對(duì)于傳統(tǒng)的分層架構(gòu),本架構(gòu)內(nèi)對(duì)應(yīng)用層進(jìn)行了功能弱化,主要負(fù)責(zé)外部接口與核心業(yè)務(wù)邏輯(服務(wù)層)之間的適配。
基礎(chǔ)設(shè)施主要用于部署支持軟件框架運(yùn)行的基礎(chǔ)工具,包括各組件管理調(diào)度機(jī)制、服務(wù)管理調(diào)度機(jī)制、事件總線管理機(jī)制、通用算法支持庫(kù)等,提供不同組件和服務(wù)的注冊(cè)、初始化以及運(yùn)行調(diào)用,完成快速集成,同時(shí)通過(guò)事件總線管理機(jī)制來(lái)解耦各軟件模塊,為整個(gè)軟件架構(gòu)提供底層的通用算法。基礎(chǔ)設(shè)施層主要用于實(shí)現(xiàn)軟件框架的質(zhì)量特性,包括易讀性、維護(hù)性、擴(kuò)展性等。
業(yè)務(wù)邏輯與技術(shù)實(shí)現(xiàn)分離的設(shè)計(jì)方法可以使軟件設(shè)計(jì)人員更加關(guān)注業(yè)務(wù)邏輯的解耦,對(duì)于實(shí)現(xiàn)軟件復(fù)雜度分解及適應(yīng)需求變化非常有借鑒意義。技術(shù)實(shí)現(xiàn)是指實(shí)現(xiàn)一項(xiàng)業(yè)務(wù)功能的具體方法,比如:處理其他設(shè)備發(fā)送的消息,可以直接調(diào)用總線接收接口主動(dòng)獲取數(shù)據(jù),也可以通過(guò)訂閱-分發(fā)的方式被動(dòng)獲取數(shù)據(jù)。通過(guò)抽象應(yīng)用層技術(shù)實(shí)現(xiàn)的接口,依靠依賴注入的方法脫離具體實(shí)現(xiàn)細(xì)節(jié),應(yīng)用層的核心業(yè)務(wù)就會(huì)大大提升穩(wěn)定性,在更換平臺(tái)或者需求發(fā)生變化時(shí)不會(huì)由于其他層的耦合特性從而導(dǎo)致核心代碼的修改。
事件總線機(jī)制[14]是對(duì)觀察者模式的一種技術(shù)實(shí)現(xiàn),通過(guò)訂閱-分發(fā)方式來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)以及事件的集中處理與分發(fā),各應(yīng)用組件通過(guò)訂閱接口對(duì)所關(guān)注的事件進(jìn)行注冊(cè)。當(dāng)事件處理中心監(jiān)測(cè)到事件發(fā)生時(shí),向各訂閱方進(jìn)行事件的分發(fā),從而能夠允許不同組件之間進(jìn)行彼此通信而無(wú)需進(jìn)行強(qiáng)依賴,從而達(dá)到降低耦合度的效果。除了系統(tǒng)外部接口觸發(fā)的事件外,系統(tǒng)內(nèi)可以根據(jù)領(lǐng)域業(yè)務(wù)分解來(lái)抽象定義出若干內(nèi)部事件,依托該機(jī)制實(shí)現(xiàn)各組件間的信息交互。
在進(jìn)行軟件架構(gòu)設(shè)計(jì)時(shí),需要同時(shí)兼顧規(guī)范性和靈活性,而規(guī)范性與靈活性本身又存在著互相制約和互斥的關(guān)系。面向?qū)ο笤O(shè)計(jì)原則能夠幫助設(shè)計(jì)者在進(jìn)行軟件架構(gòu)規(guī)范性設(shè)計(jì)時(shí),盡可能地提升軟件重用性、靈活性和擴(kuò)展性。常用的面向?qū)ο笤O(shè)計(jì)原則包括單一職責(zé)原則、開閉原則、里式代換原則、依賴倒轉(zhuǎn)原則、接口隔離原則、合成復(fù)用原則、迪米特法則[15]。
結(jié)合嵌入式系統(tǒng)的應(yīng)用發(fā)展趨勢(shì),針對(duì)嵌入式系統(tǒng)復(fù)雜度不斷提升帶來(lái)的一系列問題,本文結(jié)合領(lǐng)域驅(qū)動(dòng)及服務(wù)化設(shè)計(jì)思想,提出了一種高內(nèi)聚、松耦合、易擴(kuò)展、可移植的通用軟件架構(gòu)設(shè)計(jì)方案,有助于實(shí)現(xiàn)系統(tǒng)軟件模塊解耦、可快速適應(yīng)不同開發(fā)平臺(tái)、有助于分布式開發(fā)和獨(dú)立部署。該軟件架構(gòu)已在多個(gè)項(xiàng)目與嵌入式設(shè)備上得到了充分驗(yàn)證。實(shí)踐結(jié)果表明該軟件架構(gòu)體系有較好的應(yīng)用前景,可以有效解決系統(tǒng)復(fù)雜性的問題,同時(shí)能夠有效適應(yīng)于需求頻繁變化的業(yè)務(wù)場(chǎng)景,在不影響原有代碼的基礎(chǔ)上快速完成新功能的增加或修改。