原文地址:C語言的設計模式-介面隔離
介面隔離:(更好的可參考:《C語言介面與實現》一書)
定義為用戶端不應該依賴它不需用的介面,在C語言中我們可以把標頭檔看成一個模組的介面,根據介面隔離原則也就是說這個標頭檔中只能包含外部需要的介面,但在實際的項目中往往標頭檔都不符合介面隔離原則。
1:內、外部介面的隔離:標頭檔中通常包含了模組內部介面(內部類型定義、內部介面聲明)和外部介面(外部介面聲明)
假設moudle模組對外提供一個fun1介面,模組內部實現需要定義一個結構類型,一般的實現如下:
/*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...}
用戶端在使用介面的時候需要包含moudle.h檔案,而該介面並不符合介面的隔離,其內部包含了客戶並不需要的一些定義。為瞭解決這個問題我們可以通過定義不同的標頭檔來隔離介面,moudle.h定義外部的介面,moudle.inc定義內部介面
/*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包含內部模組需要的介面,在模組內部包含moudle.inc。通過查看模組的.inc和.h檔案,我們就可以清晰的理解模組對外和對內提供了什麼介面。
2:避免萬能標頭檔的使用,在實際項目中我們經常可以看到一些標頭檔包含了所有模組的介面聲明,用戶端只需要包含這個標頭檔就可以使用任何介面了。
/*global.h*/#inlcude "moudle1.h"#inlcude "moudle2.h"#inlcude "moudle3.h"....#inlcude "moudlen.h"
可能帶來如下問題:
會顯著的增加編譯時間,如果項目大,可能大部分的編譯時間都花在展開標頭檔(筆者一個項目測試80%左右的時間)。
不利於代碼的架構的理解,用戶端無法從包含的標頭檔中清晰的看到依賴什麼外部模組。
3:如果沒有隔離介面可能會導致一些誤操作:(不好說)
一個資料擷取模組提供兩個介面分別從網路和本機快取擷取資料,後台管理模組使用網路介面定時擷取資料更新緩衝,前台模組使用緩衝介面快速擷取資料顯示,由於沒有對介面隔離,後期的維護人員可能並不清楚開始的設計,在前台模組中直接使用網路介面來擷取資料顯示,導致介面延遲嚴重。如果一開始就把介面分離,給前台模組提供本機快取介面,給後台模組提供網路介面,就不會導致問題的出現。