這里分享一些關于C語言程序設計方面的心得吧,一點淺見,見笑見笑。
C語言也可以實現面向對象設計
面向對象是一種方法,雖然C語言不是面向對象語言也可以做到面向對象設計。首先來看看對象主要包含什么:
- 屬性集合
- 方法集合
- 方法里能訪問對象上下文
我們先看看屬性,C語言里的結構體就能實現這一點,一個結構體定義一些字段,這些字段的集合是不是就能看做是屬性集合了。
typedef struct Person_st
{
char name[20];
int age;
}Person_t
然后再來看看2,我們認為按約定定義好一些方法,說這個就是對象的方法就行,面向對象不是非得說同過"."或"->"調用才是對象方法吧。比如:
PersionSetName();
PersionSetAge();
這里先不考慮函數里面實現的問題,我們可以約定這么定義對象的方法『對象名+方法名』。當然你想要的『->』調用也是可以的。
typedef struct Person_st
{
char name[20];
int age;
void (*setName)();
void (*setAge)();
}Person_t
Person persion;
person->setName();
person->setAge();
通過函數指針來實現,事實上Linux內核中就是這么做的。
最后再來看3,如何訪問對象上下文的問題,在C++或其他面向對象語言中,直接在方法內通過this來訪問對象是天經地義的事,但是在C語言由于本身不支持就需要我們費些功夫來實現了。
方式1
typedef struct Person_st
{
char name[20];
int age;
}Person_t
void PersonSetName(Person_t *p, const char *name);
void PersonSetAge(Person_t *p, int age);
方式2
typedef struct Person_st
{
char name[20];
int age;
void (*setName)(Person_t *p, const char *name);
void (*setAge)(Person_t *p, int age);
}Person_t
我們主動把對象傳進給函數。這里我們就能在C語言上進行面向對象的程序設計了。至于方式1和方式2哪個好用,我個人喜歡用方式1,一個是不需要初始化函數指針,再者就是結構體占用的內存更小。
模塊化設計
其實程序設計和任務分解一樣,你把一個大的功能不斷細分,把一個大模塊分解成小模塊,最終無數個小模塊組成一個完整的程序。每次面對的都是一個個小功能,一者是當前需要面對的情況簡單了,一者就是需要思考的點少了,不會出現無從下手的情況。有很多將程序設計方面的書這里就不多細說了。
非阻塞系統設計
另外說一下自己關于程序設計的一點感悟吧,非阻塞系統設計。
這里先說接口,一般接口分為兩種,一種是阻塞的,等到所有數據處理完成再返回,一種是非阻塞的,調用接口時只是相當于一個觸發信號,等處理完成一般通過回調函數返回。
這里分析一下兩種方式,第一種接口,設計簡單,使用也比較簡單,都是線性思維的,但是帶來的影響就是整個系統會阻塞,不說單片機阻塞了就相當于把整個系統阻塞了,就算是用多線程也會帶來線程同步的問題,而線程同步是最容易出問題也是出了問題最不好查的地方。
第二種,所有的接口都是非阻塞的,需要等待獲取結果的通過回調函數來返回。不好的地方就是這時候思維不是線性的,先調用接口然后再在回調返回的地方再處理結果。好處就是你不會因為處理一項事物而阻塞了其他事物的執行,系統的響應實時性是高的。
特別是在多線程系統中,假設所有的邏輯都是非阻塞的也就沒必要再開線程了,也就根本不需要考慮線程間同步的問題。當然這里是需要一點小技巧的,因為系統里總有耗時的任務,原則上是只把耗時的任務交給線程處理,在處理完成有結果的時候把處理結果回調時又切回去主線程,對于使用接口的人來說完全不需要考慮線程同步的問題,只需要處理好業務邏輯就行了,對于開發效率的提升是非常明顯的。有興趣的可以看看Node.js的事件驅動,非阻塞IO模型。Node.js的接口就完全是異步的,而且居然連能創建線程的接口都沒有。
最小暴露原則
最小暴露原則說的就是,僅在頭文件中暴露外部需要使用的類型、宏、函數和全局變量,所有不需要給外部使用的都不放在對外公開的頭文件中,比如我定義一個模塊會是這樣的:
Person.c
Person.h
PersonInternal.h
所有不想對外暴露的接口,僅對內暴露的接口都定義在Inter.h頭文件中。
- 私有實現
對象中如果有些字段覺得沒必要暴露出來的可以選擇私有實現,如下定義一個PersonPri_t類型,但是在頭文件里面只有聲明,實現定義在.c文件中。
typedef struct PersonPri_st PersonPri_t;
typedef struct Person_st
{
char name[20];
int age;
void (*setName)();
void (*setAge)();
PersonPri_t *pri;
}Person_t