Simulink模型指標分析與模型重構的最佳實踐 - 軟體模型質量保證重要環節

MES模賽思發表於2022-05-20

在基於模型的開發中,優質的模型架構是生成優質程式碼的必要前提。靜態模型分析對於模型的質量保證有著至關重要的作用,同時建模規範已在業內有著廣泛而成熟的應用。然而建模規範並非模型設計原則合規性的唯一考量標準,仍有許多方面,需要根據具體的模型屬性加以改善。模型結構質量作為反映建模質量的重要方面,可透過一系列模型指標( Model metrics )對模型結構質量進行綜合分析。本文我們將向您展示模型指標的概念、原理、方法、模型指標應用和模型重構的最佳實踐,並向您展示這些操作具體如何提高模型結構質量。

 

什麼是結構質量 首先來看模型質量的概念。在基於模型的開發( M BD )中主要考慮模型軟體質量保證問題。 ISO26262 中關於軟體產品開發的參考階段給出相應設計原則、軟體設計和驗證的規範要求。按照 ISO 26262 中軟體開發的 V 模型(如 1 ),各階段涉及不同的主題活動,從安全需求到軟體架構設計、軟體單元設計和實現,以及軟體單元驗證、軟體整合和驗證,到嵌入式軟體系統的驗證。這個開發過程分為兩個階段:在 V 模型的 左側,按照軟體需求,我們設計 構建 模型;在 V 模型的 右側,在相應階段驗證我們的模型或軟體是否按預期的需求和架構設計工作。與此同時,此 V 模型 同步 涉及 質量保證活動的各個階段。一方面我們關注模型的結構質量,另外一方面考慮模型的功能質量。結構質量方面我們 關注模型 結構質量相關屬性或設計的適用性,分析模型結構相應於設計的適用性,考慮設計能否適用於實現軟體的需求。功能質量方面我們注重功能質量,驗證軟體的功能是否 符合模型設計,並能夠按照需求 正確執行。

1 軟體開發與軟體質量活動流程

那究竟什麼是結構質量呢? 首先讓我們來談談模型的結構屬性。結構屬性反映軟體設計在多大程度上適用於需求?設計屬性的符合程度如何?根據 ISO26262 關於質量保證的典型設計特徵和特性描述,設計或實現的目標要達到的目標包括一致性、簡單性、可理解性和可讀性、模組化和封裝性、修改的適用性、設計的魯棒性、可驗證性、可測試性和可維護性。 因此,典型設計特徵首先從軟體架構看要實現軟體單元介面的一致性。其次,設計要容易理解和審查。例如,設計的模組化程度如何?設計的修改方便嗎?設計是否足夠穩健?是否應用了行業最佳實踐或正規化進行建模?這樣的設計方便測試嗎?這樣的設計後期方便維護嗎?

為了實現這些屬性,參考 ISO26262- 6 在軟體設計和實現的設計原則建議,事實上對應標準中的三個表格,這三個表格專注於設計建議和結構質量條款,分別是表一,表三和表六,包括建模和編碼指南應該涵蓋的主題,軟體架構設計的原則,軟體單元設計和實現的設計原則。這些原則主要透過靜態分析和在基於模型的開發中應用建模指南來實現。與此同時,我們可以從軟體架構設計原則中得到一些具體的操作建議,比如軟體設計原則中提到的低複雜度執行,限制 元件大小 ,元件的強內聚性,元件間的鬆散耦合等等。對於這些建議的實施,首先我們需要詳細瞭解相關的模型屬性,而對於這一點,模型指標可以為我們提供關於模型屬性的詳細資訊。

 

結構質量相關模型指標

既然模型指標可以表示軟體模型的相關質量屬性,讓我們先了解一下模型指標具體包含哪些指標,如何反映模型的結構質量。

通常,指標是軟體模型具有某些屬性的程度的度量(對於模型度量也是如此)。因此,我們透過度量來評估模型的某些屬性,然後將這些屬性對映到某些具體的數值,幫助我們建立對該屬性客觀的認識和理解。模型指標的示例包括模型的複雜度、元件大小、模型的非內聚度、功能元件的比例、介面大小以及克隆組的使用等等。

  接下來,我們來詳細地介紹這些具體的模型指標,並對各項模型指標給出合理的解釋,各模型指標的影響因素,以及從這些模型指標如何反映結構質量。另外,針對各項指標給出行業最佳實踐做法。

 

模型複雜度

首先介紹複雜度。當談到複雜度時,我們首先談到的是可讀性的複雜度,這是對子系統級別建模應用風格的理解。因此,我們先來看子系統的區域性複雜度。讓我們從一個典型的子系統 2 開始。

2 子系統的區域性複雜度

在此處可以看到,示例的子系統由一些輸入埠和輸出埠和另外兩個子系統組成。在當前結構層,我們只關注兩個子系統模組,而忽略關注子系統中包含的內容。即當前子系統具有輸入埠和輸出埠以及兩個模組。這裡要理解結構層次的概念,主要是因為在結構層面,我們需要了解訊號流的來源、走向和訊號的目標,以及它們之間是如何相互連線的,也就是我們在這裡看到的當前層的結構佈局。因此,為了從結構上理解這種區域性複雜度,我們不需要知道設計中做了怎樣的計算,我們暫忽略裡面的內容,只考慮這些典型的模組。在當前模型層級評估這個系統的區域性複雜度,可以計算得出一個具體數字,考慮可見的所有這些元素在內,我們得出好比這裡給出的 33 的一個數字,以此來表徵子系統的區域性複雜度。

那麼為什麼要計算區域性複雜度呢?事實上我們希望確保在特定的模型層只關注某些模型相關的重要特徵資訊,應用適當的層次結構,使模型表示的內容更容易閱讀和理解,即增強模型的可讀性。同時關於模型表達的所有其他資訊,我們在當前層級省略並把它放在模型結構的不同層級。合理的複雜度的子系統佈局可提升結構質量,提高模型軟體的簡單性、可讀性,減少審查和維護方面的工作。現在,如果這個數字表示不能告訴我們關於複雜度的更多的資訊,不用擔心,讓我們來看下面的示例如 3

3 複雜度 : 低複雜度 vs高 複雜度

3 左側部分,像這樣的一個小規模的子系統,基本上只包含簡單的幾步計算,如果我們應用相同的區域性複雜度計算方法計算得到一個數字,顯示其複雜度數值為 6 0 。相比之下,對於 3 右側 一個更大的子系統,我們看到它具有更多的計算。因此,我們第一印象 右側 這個子系統更復雜。現在的問題是,它究竟有多複雜?能否給出某種數字來比較它比這個數字大多少或複雜多少?因此,應用區域性複雜度的運算,我們得到其複雜度數值為 600 。好的,那我們說這個右側大的子系統大約比這裡的這個小的子系統複雜十倍。

那麼 接下來 我們研究一下這個具有相當高複雜度的大型子系統(參看 3 右和 4 ),一般來說 6 00 顯示其複雜度 不是很高,但也是中高範圍。對於這樣的一個子系統,如何提高可讀性?整體看,我們會發現這裡包含某種平行計算,有些訊號流不是很明確。我們可以嘗試將區域性複雜度限制在某閾值內, 600 已經有點過大了。於是我們檢視此處的子系統並進行模型重構。

容易看到 模型 基本上分為了上下兩個部分。我們在本層結構中上下部分分別建立一個子系統使部分計算包含在下面的模型層,重構後的區域性(參看 5 )複雜度顯著減小為 4 0 ,更重要的是重新佈局的子系統,對於理解訊號流、資料流和計算更為清晰簡單,增強了可理解性和可維護性。 

4 複雜系統的佈局與複雜度(區域性複雜度 ~ 600

5 複雜系統重構後的佈局與複雜度(區域性複雜度 ~ 40

 

透過計算區域性複雜度,我們可以檢視模型元件的大小,或者子系統的複雜程度。從子系統重新開始,現在我們擴充套件到更大範圍研究模型系統或子系統的全域性複雜度,以瞭解模型系統的實現規模。因此,對於同樣的模型系統或子系統如 6 , 子系統由輸入埠 , 輸出埠和兩個子系統模組。但現在我們考慮子系統中的所有內容,子系統內部所有實現,如一些計算或更深層級的子系統中包含的內容,如 6 在模型瀏覽器中我們所看到的那樣。現在對模型子系統中包括的所有內容計算所有子系統的複雜度並加和,得到系統的全域性複雜度為 352 。這個模型複雜度的計算考慮了我們在這裡看到的所有內容。因此,我們看到當前結構層的全域性複雜度不僅包括區域性複雜度 33 ,還包括其下各子系統層次結構貢獻的區域性複雜度。

6 全域性複雜度

那麼為什麼要統計全域性複雜度呢?原因在於透過全域性複雜度的指標度量確保我們的單元或元件的不至於變得過於複雜。即確保單元和元件的可讀性。同時我們還希望保持單元元件可度量,特別是對於審查和測試工作。因此,我們實際上可以將這個數字與審查和測試的工作量聯絡起來,這意味著數字越大,需要審查和測試的工作量就越大。

因此,全域性 複雜度大小 等同於工作量多少,這正體現了對結構質量的影響。保持單元的小規模的同時提高可讀性,模組化和可測試性,提升實施效率。如果對於某項功能需求,我們可以兩種不同的方式實現它們,並且在功能上它們都可以完全正常地工作。但是當你計算它們的總實現的全域性複雜度大小時,發現它們之間有很大的差異,然後你就知道全域性複雜度較小的一個實際上是更高效的實現。因此 全域性複雜度不一定 對功能質量產生影響,但它會對結構質量產生影響,表示我們的建模效率如何。

那麼,全域性複雜度在建模實踐中怎樣幫助我們改善和提高建模效率呢?我們以 Mat lab/Simulink 中的一個典型示例模型為例 加以說明。首先根據全域性複雜度的指標,可以衡量並限制模型元件的整體大小,降低模型元件的複雜程度。其次,提供可測試性指標。例如透過採用庫或模型引用( 7 )的方式,將檔案分拆成單獨的模型元件,提高元件的模組化和可測試性。最後,提供模組化指標。合理劃分模組,達到模組複用或者單獨測試的目的。模組化的設計與您的軟體架構設計保持一致,關聯重點需求和測試。模組化帶來靈活地載入和編譯,在不同的工程模型中重用,而不必在全域性範圍內重複的評審和測試某種結構型別的元件。

7 複雜模型系統的重構 - / 模型引用

 

 

模型指標非相干度

前面我們已經討論複雜度的概念,如何瞭解元件的大小和複雜度。現在,我們進一步瞭解此元件本身的協同工作情況,如計算或計算之間是否彼此關聯。為此,我們研究元件內不同組成部分的關聯程度, Matlab/Simulink/Stateflow 中我們使用內聚度 1 和非相干度來表示。中心思想是子系統中的每個模組直接或間接地影響子系統中的其他模組,並且本身直接或間接地受到子系統中其他模組的影響。因此,對於每個模組 b ,計算受模組 b 影響或影響模組 b 的所有模組的數量,包括模組 b 本身,即透過 b 的路徑上的模組總數(簡記為 bop )。高內聚的子系統的 bop 接近子系統的總模組計數;低內聚的子系統的 bop b )與總模組計數相比會很低。例如 8 中的模組,我們可以找到模組旁邊標註每個模組的 bop 值。

8 子系統中透過每個模組的路徑上的模組數示例

 

然後,彙總子系統中所有塊的 bop 值,進行規範化,獲得子系統的內聚值。因此,具有模組 Bs 的子系統 S 的內聚度的計算公式為:

內聚度:  

進一步,我們定義非相干度為:

非相干度:

對於 8 中的子系統,內聚度和非相干度值代入相應計算公式得到:

內聚度:

非相干度:

子系統中的進行模組計算或結構的設計時,我們希望相關功能組合在一起,分組到一個子系統中。但是我們不希望對彼此不關聯的功能進行分組,以此來提高可理解性。如果所有模組都只致力於一個功能或計算,那麼就更容易理解。因此,我們希望確定並行元件的任何部分,或單獨的元件,進而進行模型重構,實現模組化和封裝性,提升可測試性和可維護性典型的質量指標。

那麼,非相干度如何幫助我們重構操作呢?我們可以將非相干度解讀為子系統中分離元件的粗略估計。例如 9 參與計算部分的所有模組都在一條路徑上,這是最簡單的情形,經過計算其非相干度為 1 10 類似前面的示例,如果子系統中有某種拆分路徑,我們得到的非相干度是一個分數,在本例中是 1.3 。而如果在 11 這裡進行平行計算會發生什麼呢?此時多了一組單獨並行的元件,實際上增加了不相干的元件數量,計算得到非相干度為 2 。由此看出,非相干度的數值的整數位可以讓您大致瞭解子系統中有多少並行或分離的元件。

Incoherence = 1.0

9 非相干度示例 1

Incoherence = 1.3

10 非相干度示例 2

Incoherence = 2.0

11 非相干度示例 3

 

讓我們來看一個複雜的例子如 12 。我們現在可以使用 非相干度 來識別具有高複雜度和高度不相干的子系統。如 12 子系統的區域性複雜度已經大到 1 104 ,導致可讀性和可測試性方面非常大的困難。根據模型的非相干度指標值約為 5 ,表明大約可劃分為 4 -5 個獨立的元件。因此,我們對模型進行重構,可將模型重構為 4 個更大的分離元件。當然根據需要劃分為 5 個也是完全可以的。像這樣重構後,得到類似 13 的新結構,形成新的結構層,使整個模型更容易理解。首先,清晰地顯示哪些輸入訊號對應於整個子系統單元的哪部分功能或運算,對相應功能訊號的評估很重要。其次我們還可發現,非相干度大致保持不變,但是區域性複雜度數值顯著降低,提高了該層級模型的可理解性,當前模型層引入了結構層而不是功能和結構的混合。

Incoherence » 5, Local Complexity 1104

12 高複雜度和高度不相干的子系統示例

Incoherence » 4, Local Complexity 194

13 基於非相干度 Simulink 模型指標的模型重構

 

模型指標非相干度值除了幫助我們進行粗略的分離元件的估計,還能幫助我們避免隱式資料流的設計。我們來看看 14 這個例子。子系統由很多單獨的圖表組成,主要訊號資料流被 goto/from 模組隱藏,很難理解訊號的屬性和流向。統計顯示子系統具有非常高的區域性複雜度,可讀性差。但是同時我們又注意到,非相干度數值只有 3 ,意味著 goto /from 模組的使用在觀感上分隔了功能元件,但 實際上它們可以簡化為三個主要的功能組。而重構後的模型 15 表明,到結構層的子系統及資料訊號流等方面得到更清晰的呈現,同時也顯著降低了區域性複雜度。

Incoherence » 3, Local Complexity 1673

14 具有隱式資料流和高度不相干子系統的示例

Incoherence » 3, Local Complexity 111

15 基於非相干度 Stateflow 模型指標的模型重構

 

結構和功能元素

如何理解實現結構和功能的分離?如 16 Sim ulink 子系統為例,我們把輸入埠和輸出埠稱為中性塊,因為在大多數情況下都必須存在。在子系統內部,沒有任何計算在這裡進行,只有兩個子系統。我們稱這樣只包含子結構模組的子系統為結構子系統。

16 : Simulink 演示模型 fuelsys 中的結構子系統示例

再如 17 這樣的子系統,除了輸入和輸出埠,其餘的模組都也是數學、邏輯或位運算或函式等功能性運算。我們稱這樣只包含功能運算模組的子系統為功能子系統。

17 Simulink 演示模型 fuelsys 中的 功能子系統示例

如何識別模型的功能和結構水平?為此,我們引入子系統級別上 功能模組佔比這一模型指標, 指標 功能模組佔比 表示子系統中的功能模組與功能模組和結構模組之和的百分比。因此,度量值為 0% 意味著子系統除了中性塊外,僅包含結構模組,子系統是 0% 的功能和 100% 的結構。指標值為 100% 表示純功能子系統,中間值表示相應的混合子系統。

參看 1 中以對功能模組和結構模組的統計和 指標 功能模組佔比 指標 功能模組佔比 100% 表示純功能子系統 , - 表示純結構子系統; 還有可能是不中 1 00% 分數,但是,在建模實踐中,我們強烈建議避免這些混合,這種混合子系統下同一子系統層上具有結構模組和功能計算模組,可能會影響可讀性、可理解性,尤其是可測試性。因此,最好儘量讓這些數字變大或儘可能小,而不是趨於中間傎。

1 模型指標:功能模組佔比

按照 I SO26262 架構設計的原則的 建議,建立子系統的適當層次結構。但什麼是適當的呢?您可以在此處將適當定義為結構和功能層之間的專用差異化設計。將結構和功能元素分開,形成訊號處理和結構、功能的層次結構架構設計的一致性,提高可讀性,模組化,可測試性和修改的適用性等方面的結構質量。

這裡我們給出推薦的模型架構設計 的最佳實踐 。在軟體開發過程的軟體架構部分粗略地定義模型軟體架構,同時根據以上我們談到的相應的模型指標進行模型系統的設計和重構來確保模型系統或子系統符合行業最佳實踐和初始的軟體架構設計。在詳細設計階段,我們仍然需要注意避免在同一子系統中混合結構和功能模組元素,確保最終得到簡易美觀分層合理的模型結構。如形成類似 18 所示的適當分層的模型結構,由 SimuLink 根層作為頂層的系統結構佈局,其下層如圖中模型層 1 透過各級子系統實現 訊號分配和軟體架構層,然後其下層 模型層 K 的子系統作為軟體架構設計的結構實現。然後,從某層如 模型層 m 開始,作為軟體架構的結構層,或者實際功能計算的實現層,直到功能計算的最後一層。即在分層結構中,將結構子系統層保持到最後一層。建模過程中透過合理使用庫連結或模型引用簡化系統複雜度,最終形成簡單易讀、易測試、易維護的模型架構。

18 模型分層設計的最佳實踐

 

無效介面與介面大小

現在,在談論子系統的層和結構以及模型分層架構時,我們當然還需要了解子系統之間和進入子系統的訊號流和子系統的介面。

按照 I SO26262 關於軟體設計的原則建議 ,介面大小應限制在合理範圍,防止介面過大而導致系統變得難以理解。考慮介面大小限制時,一方面考慮子系統介面總數的限制和訊號的匯流排化處理,另一方面我們需要更加註重的是介面訊號的有效供給。也就是說,輸入子系統的訊號務必與子系統中的功能需求相關的有效輸入,防止實質上無用訊號的輸入。為了更好的理解,讓我們看下面 19 的例子。五個基本輸入訊號進入包含多級子系統和模型引用的子系統中。值得注意的是五個基本訊號實際上只使用了兩個,即訊號 a 和訊號 b 用於積運算 ,而其他訊號 c ,d, signal1 是不必要的輸入,因為它們事實上沒有被後續用於某功能或運算過程。

19 未使用 基礎 訊號示例

但在某些情況下,如果我們不瞭解實際的訊號流,如我們難以檢視子系統的模型或瞭解所有模型引用的細節,則很難理解這些訊號是否被實際使用。此外,典型的用例如 20 中,我們常常把整個匯流排饋送到子系統中,但是子系統中本身的功能實現只需求其中部分數量的訊號,旁路訊號實際上並未被子系統所使用 所以我們希望限制介面的大小,確保單元和元件是可重用性的同時,還要避免出現虛擬耦合。為此我們通常採用強制實施顯式訊號流,以此提高模型的可讀性、模組化、可測試性、可維護性和修改的適用性。

20 未使用 旁路訊號示例

對於介面大小方面的限制和訊號的處理,有什麼最佳實踐操作呢?首先我們要注意單純的限定輸入輸出埠為具體的數值是不合理的。另外,作為 介面操作的最佳實踐如 21 ,我們可以將需求的訊號按功能需求分類分組到匯流排中,最好明確為子系統所需有效訊號的基礎上,使這些訊號流顯式表示,如圖 1 8 中的訊號分組與提取過程 。因此,我們在子系統外部提取或修改必要的匯流排訊號, 在訊號 選擇器上選擇我們實際要使用的訊號,並且在結構層上明確顯示子系統必需的訊號流。

21 介面操作的最佳實踐

克隆元件

現在假設我們已經有了一個很好的模型設計,結構質量各指標都已得到充分最佳化,我想把某個功能或演算法複用到其他地方,這時我們的操作可能是對模組、元件或子系統複製貼上。當系統中多處形成類似結構,如包含相同屬性的子系統部件組,我們也稱其為克隆組。關於子系統克隆與克隆組的操作,假設模型中存在一個小子系統,包含一系列運算模組,一些常量,呈現一定佈局。作為複用元件,我們複製貼上它到模型另外一個地方,並進行了一些佈局和引數的修改,如 22 所示。可以預見,如果我們重複進行類似操作,模型的複雜度會快速增長,相應也會帶來測試和審查的工作量。因此,為了簡化設計, 降低模型系統的複雜度 ,可以把具有克隆組的模型作為單獨的模型引用。如果某些子系統需要頻繁多次在模型中使用,我們可以將其轉換為庫檔案。轉換為模型引用或模型庫的方式,有助於減少模型的複雜度,減少模型測試和維護的工作量,最終也會減少程式碼量。

22 子系統克隆

因此,找到大量克隆和克隆組,並用庫引用替換它們,是針對克隆元件的最佳實踐。以便顯著降低全域性複雜度,這意味著大小和工作量。對一個不同型別大量模組構成的複雜模型系統, 通常各 模型模組分組分散開發,容易出現模型的複製貼上和克隆組的情況,模型系統呈現相對較高的全域性複雜度。以某專案在克隆組及複雜度方面的研究統計結果 2 為例( 23 ),系統中包含了大量的克隆元件和重複的子系統。對克隆組及克隆子系統的最佳化,可實現 1 0% 左右的複雜度縮減 一般來講,對於大型工程, 1 0% 複雜度降低意味著 10% 的評審測試工作的減少,意味著大量的人工和成本的節省。

23 控制系統的克隆組檢測結果統計

當我們研究一個典型的專案開發週期與模型全域性複雜度之間的關聯,從專案開始到功能完成再到缺陷修復到最後專案結束,我們可以看到全域性複雜度在開始時增加很快,後期逐漸飽和,特別是在缺陷修復階段。但是,如果我們應用模型指標分析並定期進行模型重構,那麼模型的總體大小和複雜度會顯著降低。也就是說,在整個模型開發週期內進行指標分析,克隆組檢測並定期進行模型重構,可有效地降低全域性複雜度,提高結構質量。

 

模型指標分析與模型重構的最佳實踐

上面我們羅列了模型相關眾多的結構性指標,如何獲得具體的相應指標精確數值,為模型的設計和重構提供參考。為此,我們可以藉助模型檢查工具,比如市場上比較受歡迎的模型檢查工具 M ES Model Examiner M ES Model Examiner 不僅是一個模型規則檢查工具,而且可以精確統計模型結構質量指標,例如全域性 / 區域性複雜度,分層深度和介面大小,克隆組,非相干度等指標等等作為檢查實現,並將這些結構質量指標顯示在專門檢視( 24 )中。如圖中顯示有各子系統的區域性複雜度,如顯示紅色的區域性複雜度 806 ,它高於預設設定的區域性複雜度為 750 的上限,於是模型對區域性複雜度規則一致性檢查的結果給出失敗的結果。

24 MES Model Examiner 模型指標檢視

對於複雜模型系統的重構問題,也可以藉助工具簡化建模和重構的操作。比如 M ES 的專用模型重構工具 MES Model R efactor 透過自動化連續建模步驟使特定功能目的的建模變得簡單快速,達到模型元件的快速重構。

  綜上所述,對模型結構屬性相關質量如模型子系統的複雜度 ( 區域性 / 全域性)、元件大小、非相干度、功能元件的佔比、介面大小和克隆組的統計等結構質量的分析, 在開發過程中中應用模型指標並定期重構的最佳實踐,有助於在模型軟體開發階段增強模型的可讀性、可理解性、可維護性和可測試性,有效降低軟體複雜度,實施模型元件和功能建模的設計和驗證原則,提高模型的結構質量,從而總體上提高模型軟體系統的質量。



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69983059/viewspace-2895597/,如需轉載,請註明出處,否則將追究法律責任。

相關文章