程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C >> 關於C >> C語言對模塊化支持的欠缺

C語言對模塊化支持的欠缺

編輯:關於C

     模塊化是最高原則之一(在 《Unix 編程藝術》一書中, Unix 哲學第一條即:模塊原則),我們就當考慮如何簡潔明快的使用 C 語言實現模塊化。

  除開 C/C++ ,在其它現在流行的開發語言中,缺少標准化的模塊管理機制是很難想象的。但這也是 C 語言本身的設計哲學決定的:把盡可能多的可能性留給程序員。根據實際的系統,實際的需要去定制自己需要的東西。

  對於巨型的系統(比如 Windows 這樣的操作系統),一般會考慮使用一種二進制級的模塊化方案。由模塊自己提供元信息,或是使用統一的管理方案(比如注冊表)。稍小一點的系統(我們通常開發接觸到的),則會考慮輕量一些的源碼級方案。

  首先要考慮的往往是模塊的依賴關系和初始化過程。

  依賴關系可以放由鏈接器或加載器來解決。尤其在使用 C 語言時,簡單的靜態庫或動態庫,都不太會引起大的麻煩。

  C++ 則不然,C++ 的某些特性(比如模板類靜態成員的構造)必須對早期只供 C 語言使用的鏈接器做一些增強。即使是精心編寫的 C++ 庫,也有可能出現一些意外的 bug 。這些 bug 往往需要對編譯,鏈接,加載過程很深刻的理解,才能查出來。注:我並不想以此來反對使用 C++ 做開發。

  我們需要著重管理的,是模塊的初始化過程。

  對於打包在一起的一個庫(例如 glibc ,或是 msvcrt ),會在加載時有初始化入口,以及卸載時有結束代碼。我想說的不是這個,而是我們自己內部拆分的更小的模塊的相互依賴關系。

  誰先初始化,誰後初始化,這是一個問題。

  在 C++ 的語言級解決方案中,使用的是單件模塊。要麼由鏈接器決定以怎樣的次序來生成初始化代碼,這,通常會因為依賴關系和實際構造次序不同而導致 bug (注:我在某幾本 C++ 書中都見過,待核實。自己好久不寫 C++ 也沒有實際的錯誤例子);要麼使用惰性初始化方案。這個惰性初始化也不是萬能的,並且有些額外的開銷。(多線程環境中尤其需要注意)

  我使用 C 語言做初期設計的時候,采用的是一種足夠簡單的方法。就是,以編碼規范來規定,每個模塊必須存在一個初始化函數,有規范的名字。比如 foo 模塊的初始化入口叫

  

C 語言對模塊化支持的欠缺

  規定:凡使用特定模塊,必須調用模塊初始化函數。

  為了避免模塊重復初始化,初始化函數並不直接調用,而是間接的。類似這樣:

  

C 語言對模塊化支持的欠缺

  mod_using 負責調用初始化函數,並保證不重復調用,也可以檢查循環依賴。

  在這裡,我們還約定了初始化成功於否的返回值。(在我們的系統中,返回 0 表示正確,1 表示失敗)然後定義了一個宏來做這個使用。

  

C 語言對模塊化支持的欠缺

  注:我個人反對濫用宏。也盡可能的避免它。這裡使用宏,經過了慎重的考慮。我希望可以有一個代碼掃描器去判斷我是否漏掉了模塊初始化(可能我使用了一個模塊,但忘記初始化它)。宏可以幫助代碼掃描分析器更容易實現。而且,使用宏更像是對語言做的輕微且必要的擴展。

  這樣,我的系統中模塊模塊的實現代碼最後,都有一個 init 函數,裡面只是簡單的調用了 USING 來引用別的模塊。例如:

  

C 語言對模塊化支持的欠缺

  至於模塊的卸載,大部分需求下是不需要的。今天在這裡就不論證這一點了。

*
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved