www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號(hào)精選 > 嵌入式云IOT技術(shù)圈
[導(dǎo)讀]單一職責(zé) 單一職責(zé)原則:通常的定義是只專注于做一件事和僅有一個(gè)引起它變化的原因。對(duì)于接口、實(shí)現(xiàn)、函數(shù)級(jí)別往往我們比較容易關(guān)注單一職責(zé),大家談的也比較多,但對(duì)于返回值、參數(shù)可能不會(huì)有太多的人關(guān)注。但往往就是這些不符合單一職責(zé)原則的設(shè)計(jì)可能導(dǎo)致









單一職責(zé)

單一職責(zé)原則:通常的定義是只專注于做一件事和僅有一個(gè)引起它變化的原因。對(duì)于接口、實(shí)現(xiàn)、函數(shù)級(jí)別往往我們比較容易關(guān)注單一職責(zé),大家談的也比較多,但對(duì)于返回值、參數(shù)可能不會(huì)有太多的人關(guān)注。但往往就是這些不符合單一職責(zé)原則的設(shè)計(jì)可能導(dǎo)致一些很難發(fā)現(xiàn)的BUG??纯聪旅孢@段代碼:

pBuf = (byte*)realloc( pBuf, size);
if( pbBuf != NULL )
{
TODO...
}

可能很多人一眼看上去并沒有什么問題,先讓我們看看這個(gè)庫函數(shù)的定義:

函數(shù)簡(jiǎn)介

  • 原型
extern void *realloc(void *mem_address, unsigned int newsize);

語法:指針名=(數(shù)據(jù)類型*)realloc(要改變內(nèi)存大小的指針名,新的大?。?。

  • 功能

    先判斷當(dāng)前的指針是否有足夠的連續(xù)空間,如果有,擴(kuò)大mem_address指向的地址,并且將mem_address返回,如果空間不夠,先按照newsize指定的大小分配空間,將原有數(shù)據(jù)從頭到尾拷貝到新分配的內(nèi)存區(qū)域,而后釋放原來mem_address所指內(nèi)存區(qū)域,同時(shí)返回新分配的內(nèi)存區(qū)域的首地址。即重新分配存儲(chǔ)器塊的地址。

  • 返回值

    如果重新分配成功則返回指向被分配內(nèi)存的指針,否則返回空指針NULL。正常情況下pBuf是新空間的地址沒有任何問題,但我們考慮下如果分配失敗了呢,pBuf會(huì)被賦值成NULL,pBuf原指向的地址空間就沒有指針指向了,造成了內(nèi)存泄露。這種問題往往很難定位。熟悉realloc機(jī)制的人可能對(duì)這個(gè)問題很不屑,認(rèn)為高手不會(huì)犯這些錯(cuò)誤。但我們可以想下有沒有辦法設(shè)計(jì)一個(gè)好的接口讓菜鳥也寫出不會(huì)出錯(cuò)的代碼呢。假設(shè)這個(gè)庫函數(shù)的接口是這樣的呢:

函數(shù)簡(jiǎn)介


  • 原型 

        extern flag realloc(void **ppMem_address, unsigned int newsize);

  • 語法

    返回值 =(數(shù)據(jù)類型*)realloc(要改變內(nèi)存大小的指針名,新的大?。?/p>

  • 返回值

    如果重新分配成功則返回指True(ppMem_address保存新分配空間地址),否則返回False(ppMem_address保存老空間地址)。

相信任何一個(gè)使用這個(gè)接口的人都會(huì)寫出下面的代碼:

if( True == realloc( &pBuf, size))
{
TODO...
}
else
{
    TODO...
}

為什么有人會(huì)犯pBuf = (byte*)realloc( pBuf, size);這種錯(cuò)誤?因?yàn)樗魂P(guān)注了realloc返回值是一個(gè)地址,沒有關(guān)注該返回值還有錯(cuò)誤識(shí)別的功能,換句話來說這個(gè)庫函數(shù)的返回值不具備單一職責(zé),導(dǎo)致了可能的錯(cuò)誤使用。如果使用改進(jìn)后的接口,因?yàn)榉祷刂抵挥幸粋€(gè)判斷分配成功與否的功能,相信沒有人還會(huì)用錯(cuò)。

我們?cè)僮屑?xì)看看我們新的接口,總覺得似乎有什么地方還是不對(duì),看到void **ppMem_address可能要想一下明白,這個(gè)參數(shù)既是入?yún)⒂质浅鰠?,它承?dān)了原始地址的輸入和新地址的輸出,這不又違反了單一職責(zé)嗎?好吧我們?cè)俑倪M(jìn)一下:

函數(shù)簡(jiǎn)介

  • 原型 
    extern flag realloc(void *pIn_Mem_address,void **ppOut_Mem_address, unsigned int newsize);
  • 語法 返回值 =(數(shù)據(jù)類型*)realloc(要改變內(nèi)存大小的指針名,新的內(nèi)存指針名,新的大小)。
  • 返回值 如果重新分配成功則返回指True,否則返回False。

現(xiàn)在這個(gè)接口就算一個(gè)初次看到的人也應(yīng)該大概知道什么意思,相信也不會(huì)寫出什么帶BUG的代碼,因?yàn)楹瘮?shù)的參數(shù)、返回值都具有單一的功能,通過返回值來判斷分配成功與否,通過出參來獲取地址。一切看起來都很清晰。

在C庫中還有很多類似的函數(shù),如果當(dāng)初的設(shè)計(jì)人員能多考慮單一職責(zé),也許現(xiàn)在的系統(tǒng)中就會(huì)少了很多隱藏的BUG,接口永遠(yuǎn)是給別人使用的,一定要把使用者當(dāng)成傻瓜,也許才能設(shè)計(jì)出好的接口。

面向?qū)ο髾C(jī)制的實(shí)現(xiàn)

為什么要用C來模擬面向?qū)ο蟮臋C(jī)制,在實(shí)際的工作中我們往往在感慨一些面向?qū)ο蟮慕?jīng)典設(shè)計(jì)模式由于C語言的限制無法使用,其實(shí)通過簡(jiǎn)單的模擬面向?qū)ο蟮男袨椋贑語言中也可以使用這些模式。

1:類的構(gòu)建

類描述了所創(chuàng)建的對(duì)象共同的屬性和方法。我們?cè)谝粋€(gè)源文件中通過把數(shù)據(jù)和操作進(jìn)行適當(dāng)?shù)慕M織來完成類的模擬。

/*類的數(shù)據(jù)*/
typedef struct SQUARE_S SQUARE_T;
struct SQUARE_S
{
void (*draw)(void*);
int sideLen;
};
/*類的方法*/
static void draw(void* pObj)
{
SQUARE_T* pSqr = (SQUARE_T*)pObj;
printf("Draw Square len is %d\n",pSqr->sideLen);
}

如上所示,一個(gè)正方形的類我們用一個(gè)結(jié)構(gòu)體SQUARE_T來表示正方形的屬性,draw是其中的一個(gè)方法。

2:類的封裝性

類的封裝一般要求對(duì)細(xì)節(jié)的隱藏并且提供指定的方法供調(diào)用者使用,在SQUARE這個(gè)類中,sideLen是圖形的細(xì)節(jié),只需要提供一個(gè)draw接口給調(diào)用者。因此在提供給外部調(diào)用的接口頭文件中構(gòu)建如下的接口。

typedef struct SHAPE_S SHAPE;
struct SHAPE_S
{
void (*draw)(void*);
};

通過定義不同的數(shù)據(jù)結(jié)構(gòu)來達(dá)到數(shù)據(jù)隱藏的目的,如下圖所示,對(duì)外接口中只能看到draw,內(nèi)部實(shí)現(xiàn)中可以看到draw和sideLen。

3:多態(tài)的模擬

多態(tài)無疑是面向?qū)ο笳Z言的很重要的一個(gè)機(jī)制,很多面向?qū)ο蟮脑O(shè)計(jì)模式都是以多態(tài)為基礎(chǔ),C語言并不支持多態(tài),導(dǎo)致很多設(shè)計(jì)模式都無法直接使用。

一個(gè)典型的多態(tài)例子,通過聲明一個(gè)SHAPE接口,根據(jù)實(shí)例化對(duì)象類型的不同,pShape在運(yùn)行時(shí)動(dòng)態(tài)的表現(xiàn)不同的行為。

SHAPE* pShape = NULL; //一個(gè)形狀接口
pShape = (SHAPE*)Ins(SQUARE,2); //實(shí)例化為一個(gè)正方形
pShape->draw(pShape); //pShape表現(xiàn)為正方形的行為

多態(tài)機(jī)制的實(shí)現(xiàn)依賴函數(shù)指針,在每個(gè)類的構(gòu)造函數(shù)中把相關(guān)接口用具體的函數(shù)地址填充,這樣在實(shí)例化一個(gè)對(duì)象的時(shí)候我們才綁定了其具體的操作,也就是所謂的動(dòng)態(tài)綁定。

/*每個(gè)類的構(gòu)造函數(shù)*/
static void* Constructor(void* pObj,va_list* pData)
{
    SQUARE_T* pSquare = (SQUARE_T*)pObj;
    pSquare->draw = draw; //具體行為的填充
    pSquare->sideLen = va_arg(*pData,int);
    return pObj;
}

4:對(duì)象的創(chuàng)建

有了類,我們需要實(shí)例化為可以運(yùn)行的對(duì)象,實(shí)例化主要的工作是分配內(nèi)存、動(dòng)態(tài)綁定、數(shù)據(jù)初始化等工作。

void* Ins(const void* pClass,...)
{
CLASS* pCls = NULL;
void* pObj = NULL;
va_list vaList = NULL;
pCls = (CLASS* )pClass;
pObj = malloc(pCls->classSize);
memset(pObj,0,pCls->classSize);
va_start(vaList,pClass);
pObj = pCls->Constructor(pObj,&vaList);
return pObj;
}

接口隔離

定義為客戶端不應(yīng)該依賴它不需用的接口,在C語言中我們可以把頭文件看成一個(gè)模塊的接口,根據(jù)接口隔離原則也就是說這個(gè)頭文件中只能包含外部需要的接口,但在實(shí)際的項(xiàng)目中往往頭文件都不符合接口隔離原則。

1:內(nèi)、外部接口的隔離

頭文件中通常包含了模塊內(nèi)部接口(內(nèi)部類型定義、內(nèi)部接口聲明)和外部接口(外部接口聲明)

假設(shè)moudle模塊對(duì)外提供一個(gè)fun1接口,模塊內(nèi)部實(shí)現(xiàn)需要定義一個(gè)結(jié)構(gòu)類型,一般的實(shí)現(xiàn)如下:

/*moudle.h*/
typedef struct str_s str_t;
struct str_s
{
int a;
int b;
};
void fun1();

/*moudle.c*/
#include "moudle.h"
void fun1()
{
str_t s = {0};
TODO...
}

客戶端在使用接口的時(shí)候需要包含moudle.h文件,而該接口并不符合接口的隔離,其內(nèi)部包含了客戶并不需要的一些定義。為了解決這個(gè)問題我們可以通過定義不同的頭文件來隔離接口,moudle.h定義外部的接口,moudle.inc定義內(nèi)部接口

/*moudle.h*/
void fun1();
/*moudle.inc*/
typedef struct str_s str_t;
struct str_s
{
int a;
int b;
};
/*moudle.c*/
#include "moudle.inc"
void fun1()
{
str_t s = {0};
TODO...
};

moudle.h包含外部模塊需要的接口,外部模塊包含moudle.h,moudle.inc包含內(nèi)部模塊需要的接口,在模塊內(nèi)部包含moudle.inc。通過查看模塊的.inc和.h文件,我們就可以清晰的理解模塊對(duì)外和對(duì)內(nèi)提供了什么接口。

2:避免萬能頭文件的使用

在實(shí)際項(xiàng)目中我們經(jīng)??梢钥吹揭恍╊^文件包含了所有模塊的接口聲明,客戶端只需要包含這個(gè)頭文件就可以使用任何接口了。

/*global.h*/
#inlcude "moudle1.h"
#inlcude "moudle2.h"
#inlcude "moudle3.h"
....
#inlcude "moudlen.h"

可能帶來如下問題:

會(huì)顯著的增加編譯時(shí)間,如果項(xiàng)目大,可能大部分的編譯時(shí)間都花在展開頭文件(筆者一個(gè)項(xiàng)目測(cè)試80%左右的時(shí)間)。

不利于代碼的框架的理解,客戶端無法從包含的頭文件中清晰的看到依賴什么外部模塊。

3:如果沒有隔離接口可能會(huì)導(dǎo)致一些誤操作:

一個(gè)數(shù)據(jù)獲取模塊提供兩個(gè)接口分別從網(wǎng)絡(luò)和本地緩存獲取數(shù)據(jù),后臺(tái)管理模塊使用網(wǎng)絡(luò)接口定時(shí)獲取數(shù)據(jù)更新緩存,前臺(tái)模塊使用緩存接口快速獲取數(shù)據(jù)顯示,由于沒有對(duì)接口隔離,后期的維護(hù)人員可能并不清楚開始的設(shè)計(jì),在前臺(tái)模塊中直接使用網(wǎng)絡(luò)接口來獲取數(shù)據(jù)顯示,導(dǎo)致界面延遲嚴(yán)重。如果一開始就把接口分離,給前臺(tái)模塊提供本地緩存接口,給后臺(tái)模塊提供網(wǎng)絡(luò)接口,就不會(huì)導(dǎo)致問題的出現(xiàn)。

往期精彩

嵌入式系統(tǒng)軟件架構(gòu)設(shè)計(jì)(長(zhǎng)篇深度好文)

分享一個(gè)非常有用且簡(jiǎn)單C語言測(cè)試框架

分享一個(gè)自己量產(chǎn)項(xiàng)目上的集成測(cè)試軟件MTTEST

使您的軟件運(yùn)行起來: 防止緩沖區(qū)溢出(C語言精華帖)

若覺得本次分享的文章對(duì)您有幫助,隨手點(diǎn)[在看]并轉(zhuǎn)發(fā)分享,也是對(duì)我的支持。


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉