• 正文
    • 1、MVC框架
    • 2、狀態(tài)模式
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

嵌入式軟件設(shè)計之美-以實際項目應(yīng)用MVC框架與狀態(tài)模式(上)

01/05 13:57 來源:嵌入式應(yīng)用研究院
407
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

筆者在職場工作多年,維護過屎山級別的項目代碼,也參與過大大小小的軟件開發(fā)。我逐漸明白了寫代碼最重要的并不是炫技,而是讓其他維護這個項目的人能夠更快的上手去拓展項目的功能,以便能夠更好的傳承下去。

在實際的嵌入式應(yīng)用開發(fā)過程中,我們常常能夠聽到軟件系統(tǒng)的分層設(shè)計,根據(jù)不同的產(chǎn)品軟件設(shè)計,它們可能擁有應(yīng)用層、系統(tǒng)層、驅(qū)動層等等。在我看來,這些層的描述太大,但是它不得不存在;因為它能夠從宏觀上讓每個了解它的人知道它到底有什么東西,大部分情況下給人感覺是:哇,好牛逼!?然后,就沒有然后了。

實際上,真正能夠體現(xiàn)設(shè)計的牛逼并不是簡單的描述幾個層就可以了,真正的設(shè)計,它至少擁有兩個面的維度,即數(shù)據(jù)平面、控制平面。當(dāng)然,如果我們分得更細(xì)一點,它可以是數(shù)據(jù)平面、控制平面和管理平面。至于怎么定義每個平面的作用,早在1979年,就已經(jīng)有一位叫做Trygve Reenskaug的大佬為我們設(shè)計好了所謂的MVC框架。直到如今,MVC框架廣泛應(yīng)用于現(xiàn)代應(yīng)用軟件設(shè)計中,也是嵌入式應(yīng)用軟件設(shè)計中最常用的設(shè)計模式之一。那么,什么是MVC框架呢?

1、MVC框架

MVC框架,是軟件系統(tǒng)模塊化設(shè)計的一種方法,它給軟件系統(tǒng)劃分為三個大的部分,分別是Model(模型)、View(視圖)、Controller(控制器)

Model模型

模型就是負(fù)責(zé)具體功能、業(yè)務(wù)邏輯實現(xiàn)的,它通常是一個產(chǎn)品內(nèi)部的一些業(yè)務(wù)邏輯組成;例如,接下來我們要做的一個項目里有一個MQ-2傳感器,MQ-2傳感器的氣體檢測流程可以認(rèn)為是一個模型。

View視圖

視圖就是負(fù)責(zé)展示、響應(yīng)其它模塊處理結(jié)果的。例如,有一款設(shè)備擁有一個LCD屏幕,然后上面移植了一個GUI系統(tǒng),它用于顯示當(dāng)前MQ-2傳感器的數(shù)據(jù),那么這個GUI系統(tǒng)就是一個視圖。當(dāng)MQ-2傳感器檢測到的閾值超出我們所設(shè)定的閾值時,蜂鳴器或者LED報警了,那么蜂鳴器、LED也可以認(rèn)為是一個視圖。當(dāng)然,視圖不局限于以上這些內(nèi)容,視圖也可以是IOT前端、也可以是一個Shell終端,甚至可以是一個進程或者線程。

Controller控制器

控制器就是用來接收用戶輸入的。通常,一個設(shè)備上可能有按鍵、觸摸屏、鼠標(biāo)等輸入設(shè)備,那么當(dāng)用戶控制輸入設(shè)備時,根據(jù)產(chǎn)品內(nèi)部的業(yè)務(wù)邏輯,界面可能會發(fā)生跳轉(zhuǎn)(視圖),用戶看不到的另一面會啟動應(yīng)用業(yè)務(wù)邏輯(模型),然后設(shè)備內(nèi)部的業(yè)務(wù)邏輯處理完畢后,又會通知界面,例如彈窗或者僅僅是界面上控件數(shù)據(jù)更新(視圖)。

有了MVC架構(gòu)以后,我們可以為我們接下來的項目做以下軟件模塊的劃分了,先預(yù)告一下,我們要做一個簡單的氣體檢測裝置,它會延用我們之前分享過的內(nèi)容進一步規(guī)范化:

表驅(qū)動+狀態(tài)機法AD傳感器驅(qū)動檢測框架

讓傳感器數(shù)據(jù)更直觀之LCD曲線顯示

基于小熊派氣體傳感器MQ-2綜合實踐

Model

傳感器數(shù)據(jù)獲取、傳感器流程檢測。

View

LCD GUI(或者騰訊云、騰訊連連小程序)顯示,顯示傳感器數(shù)據(jù)、檢測狀態(tài)等

Controller

開發(fā)板上的按鍵、IOT終端下發(fā)命令(或騰訊連連小程序下發(fā)命令)

那么,這三個模塊怎么來通信呢?一般情況下,可以有兩種方式,一種是通過消息傳遞,另外一種是通過回調(diào)函數(shù)傳遞(類似事件回調(diào)觸發(fā)機制)。很顯然,我們的項目會考慮上RTOS,那么,通過消息隊列來傳輸數(shù)據(jù)就再好不過了!這樣的話,我們每個模塊之間的通信一旦設(shè)計好了,那么未來需要做的事情僅僅只需要關(guān)心:

消息發(fā)送端:數(shù)據(jù)怎么傳,要傳什么數(shù)據(jù)
接收消息端:數(shù)據(jù)怎么接,接完之后要做什么

解決了發(fā)送、接收數(shù)據(jù)的問題以后,第二步就是要設(shè)計傳感器的檢測流程了,它也是我們MVC架構(gòu)中模型部分最重要的內(nèi)容了,它是整個項目的核心業(yè)務(wù)。對于傳感器設(shè)備檢測來說,無非就是幾種分析狀態(tài):

    • 傳感器設(shè)備處于空閑狀態(tài)
    • 傳感器設(shè)備處于校準(zhǔn)狀態(tài)
    • 傳感器設(shè)備處于檢測中狀態(tài)
    • 傳感器設(shè)備處于獲取檢測結(jié)果狀態(tài)

從一種狀態(tài)切換到另一種狀態(tài),那么一定是由某個事件觸發(fā)的,進而產(chǎn)生一定的動作,然后完成狀態(tài)的遷移,我們將這種稱為狀態(tài)機。在設(shè)計模式中,狀態(tài)機稱為狀態(tài)模式,狀態(tài)模式也是嵌入式軟件應(yīng)用設(shè)計中最常用的模式。

2、狀態(tài)模式

狀態(tài)模式是設(shè)計模式中行為型模式的一種,它允許對象在內(nèi)部狀態(tài)發(fā)生改變時改變它的行為。對于小白來說,狀態(tài)模式的概念講述是比較抽象的,那么,我可以舉一個接下來要做的氣體檢測儀項目來加深大家對狀態(tài)模式的理解,以下是這個項目的簡單的狀態(tài)遷移圖:

在狀態(tài)機的基本概念里,它的基本組成要素主要由現(xiàn)態(tài)、條件、動作、次態(tài)。我們能看到,檢測儀主要有四個狀態(tài),分別是IDLE、CALI、DETECT、RESULT,每個狀態(tài)其實都是由相應(yīng)的條件來進行觸發(fā)產(chǎn)生動作進而產(chǎn)生下一個狀態(tài)的。從以上的狀態(tài)遷移圖里,我們能很清晰地將每個狀態(tài)的遷移過程描述出來:

1.對于IDLE來說,主要有:
IDLE→START→CALI

解析:當(dāng)檢測儀狀態(tài)為IDLE時,檢測儀的操作者需要發(fā)起一個START事件來讓檢測儀的狀態(tài)由IDLE進入到CALI狀態(tài)中。這樣的操作場景通常是檢測儀的操作者按下一個開始檢測的按鈕,檢測儀由空閑狀態(tài)轉(zhuǎn)為基準(zhǔn)采集狀態(tài),此時檢測儀可能會開啟各類傳感器,在此期間,各項傳感器指標(biāo)需要與當(dāng)前環(huán)境進行融合,使各項傳感器指標(biāo)處于穩(wěn)定狀態(tài),這樣才有利于后續(xù)檢測結(jié)果精確。

2.對于CALI來說,主要有:
CALI→NEXT→DETECT
CALI→STOP→IDLE

解析:當(dāng)檢測儀狀態(tài)處于CALI時,如果此時條件滿足,則需要發(fā)起一個NEXT事件讓檢測儀狀態(tài)由CALI進入DETECT中。這個NEXT事件可以是CALI過程穩(wěn)定后自動觸發(fā)的,也可以是由用戶手動觸發(fā)的,這個需要根據(jù)產(chǎn)品需求進行定義。如果此時條件不滿足則維持現(xiàn)態(tài)CALI,當(dāng)檢測儀的操作者發(fā)起STOP事件時,通常是按下了某個返回或者退出的按鍵,則此時檢測的狀態(tài)由CALI遷移到了IDLE態(tài)。

3.對于DETECT來說,主要有:
DETECT→NEXT→RESULT
DETECT→PREV→CALI
DETECT→STOP→IDLE

解析:當(dāng)檢測儀狀態(tài)處于DETECT時,此時內(nèi)部會進行一系列的動作,那么它得有結(jié)果呀,結(jié)果就是由NEXT事件來產(chǎn)生的,這樣的應(yīng)用場景通常是傳感器各項技術(shù)指標(biāo)整合的檢測算法運算結(jié)果與檢測儀所設(shè)定的閾值進行比較后自行觸發(fā)的,最終將由DETECT狀態(tài)遷移到了RESULT。當(dāng)然,如果當(dāng)前處于DETECT狀態(tài),而DETECT狀態(tài)的過程存在偏差,此時檢測儀操作者可以通過某個按鍵,觸發(fā)PERV事件,將DETECT狀態(tài)遷移到上個狀態(tài)CALI;當(dāng)然,檢測儀操作者也可以直接選擇停止檢測,他只需要發(fā)起一個STOP事件(通常是一個返回按鍵)即可讓檢測儀的狀態(tài)由DETECT遷移到IDLE狀態(tài)。

4.對于RESULT來說,主要有:
RESULT→PREV→DETECT
RESULT→STOP→IDLE

解析:當(dāng)檢測儀狀態(tài)處于RESULT時,一般情況下檢測儀要么是通過聲光報警,要么是直接在LCD上進行展示,要么是都有。檢測儀的操作者可以繼續(xù)檢測,那么他只需要發(fā)起一個PREV事件就能讓檢測儀的狀態(tài)由RESULT遷移到DETECT,設(shè)備又能夠繼續(xù)進行檢測了,這就是所謂的快檢模式。當(dāng)然,檢測儀操作者也可以發(fā)起一個STOP事件,讓檢測儀回到IDLE狀態(tài)。

對以上狀態(tài)遷移過程熟悉后,我們第二步要做的事情就是設(shè)計符合我們業(yè)務(wù)場景的枚舉以及結(jié)構(gòu)體。首先是傳感器的狀態(tài),有IDLE、CALI、DETECT、RESULT,用枚舉來體現(xiàn)就是:

//傳感器狀態(tài)
enum?SensorState_t
{
????IDLE?=?0,
????CALI,
????DETECT,
????RESULT
};

每種狀態(tài)是由特定的事件進行觸發(fā),那么傳感器的事件主要有:

//傳感器事件
enum?SensorEvent_t
{
????START?=?0,
????STOP,
????NEXT,
};

有了狀態(tài)和事件之后,我們需要使用一個結(jié)構(gòu)體來抽象從現(xiàn)態(tài)->事件->次態(tài)這個過程,那么我們可以這么來設(shè)計:

struct?SensorStateItem_t
{
????enum?SensorState_t?CurState;
????enum?SensorEvent_t?Event;
????enum?SensorState_t?NextSate;
};

因此,我們能夠根據(jù)我們所描述的狀態(tài)規(guī)劃出一張表,而這張表就清晰的描述出現(xiàn)態(tài)->事件->次態(tài)的這幾個過程了:

struct?SensorStateItem_t?SensorStateTable[]?=?
{
????{IDLE,???START,?CALI},??????//IDLE->START->CALI
????{CALI,???NEXT,??DETECT},????//CALI->NEXT->DETECT
????{CALI,???STOP,??IDLE},??????//CALI->STOP->IDLE
????{DETECT,?NEXT,??RESULT},????//DETECT->NEXT->RESULT
????{DETECT,?PREV,??CALI},??????//DETECT->PREV->CALI
????{DETECT,?STOP,??IDLE},??????//DETECT->STOP->IDLE
????{RESULT,?PREV,??DETECT},????//RESULT->PREV->DETECT
????{RESULT,?STOP,??IDLE},??????//RESULT->STOP->IDLE
};

有了業(yè)務(wù)模型以后,接下來就是編寫代碼邏輯了!預(yù)知詳情,且看下回分享!今天的分享到此為止,如果對您有幫助,歡迎一鍵三連!

參考資料

[1]https://www.runoob.com/design-pattern/mvc-pattern.html

[2]https://refactoringguru.cn/design-patterns/state

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

本科畢業(yè)于華南理工大學(xué),現(xiàn)美國卡羅爾工商管理碩士研究生在讀,曾就職于世界名企偉易達(dá)、聯(lián)發(fā)科技等,多年嵌入式產(chǎn)品開發(fā)經(jīng)驗,在智能玩具、安防產(chǎn)品、平板電腦、手機開發(fā)有豐富的實戰(zhàn)開發(fā)經(jīng)驗,現(xiàn)任深圳市云之手科技有限公司副總經(jīng)理、研發(fā)總工程師。