程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C語言的面向對象式重構

C語言的面向對象式重構

編輯:C++入門知識

重構Refactoring)就是在不改變軟件現有功能的基礎上,通過調整程序代碼改善軟件的質量、性能,使其程序的設計模式和架構更趨合理,提高軟件的擴展性和維護性。

在越來越多的方便實用的語言曾不出窮的今天,c語言作為編程語言的常青樹,在用戶數方面仍然占據著老大的地位。當然,這與C語言的使用環境有很大關系,諸多的嵌入式和底層代碼仍然離不開這個經典的語言。

最近工作有了個空,如何使自己寫的C代碼容易閱讀,便於維護,成為近期我思考的主要問題。

於是,我找到了Martin Fowler寫的《重構》。這本書從Martin的經驗出發,結合代碼中出現的各種“臭味”,提出了重構的思路、指導思想和重構步驟,從而使得代碼不斷的得到進化,從而使得代碼越來越優美,越來越適應於變化,越來越便於維護。這本書雖然是針對Java語言寫的,但是大量的重構思路都是語言無關的,我們在任何語言中都可能遇到Martin大師描述的問題,並能夠利用Martin的解決思路來改正問題。現在,就把我看這本書的一些想法、思路記錄下來,也算是一個讀書筆記吧。

一、函數的改進

過程化語言直接面對的是要解決問題的系統責任,也就是系統的功能域。要實現什麼樣的功能,采用什麼樣的流程來解決,這些內容的實現都是由函數來完成的。因此,函數的重新構建成為C語言重構的最重要的一環。

1、重新命名函數

代碼首先是為人寫的,其次才是為機器寫的。函數的名稱應該准確表達出它的用途。當我們維護代碼時,通過名稱猜出這個函數的用途可以節省大量的時間。想想自己的一些經歷,通過費力的閱讀代碼才能明白,哦,它原來是干這個的!如果有個好的名稱該多好,看看名字,就能大概得到這個函數的用途,有了這個大概情況,再去閱讀代碼,是那麼的輕松、愉快。

有些人會想,我寫的是C程序,不是Java語言。C語言要求的是簡潔的名稱,而不是Java那樣,恨不能名字比實現的代碼還長。我覺得,簡潔不代表含糊不清。我們都有默許的規范,read就是代表讀,取一個名字叫rfile(),我就會猜它是讀文件;要是叫sfile(),誰知道它是什麼?

2、提煉函數

過長的函數當中,多半會有很多繁雜的過程包含在裡面。當我們需要不斷的上下翻頁來了解一個函數的功能時,很快就會不可耐煩,並且喪失信心。因此要想讓函數變得容易讓人看懂,就得盡量讓函數簡練。這就得把函數功能細化,不斷的提煉函數。每個函數都有其基本的功能,使得函數復用的機會很大,復雜函數就是這些小函數的組合,這樣復雜函數讀起來就像一系列注釋,通俗易懂。

3、提煉判斷條件

有時候在判斷條件當中,會遇到一個很長的表達式表示一個條件分支,這個表達式有時不光包含了“與”、“或”、“非”,還有查詢函數,大於小於等等。要看懂這麼一個表達式,首先要做的是查清楚括號的對應關系,然後查清楚各種運算符的運算優先級,最後在去考慮這個表達式代表的意思。

為了擺脫這種“與非”困境,我們要做的是把這個判斷條件提煉出來,或者賦值給一個臨時變量,或者徹底提煉成一個函數,變量或者函數的名字明確代表了判斷條件的意思,例如isEmpty等等。這樣在判斷語句中,就可以一眼看出來這個分支是怎麼一回事了。如果真要考慮效率問題,可以把提煉出來的函數作為inline函數。總之,要寫出給人類看的代碼,這個工作是很值得使用的。

4、簡化函數參數

使用C語言編程,缺少強大的自動補齊工具尤其是喜歡vi的人,雖然下面有補齊的插件,但是很少使用,也不大適應),如果函數的參數太多,根本記不住應該加的參數,編寫代碼時要不斷的去翻看,降低了效率,尤其在多個人合作編程時,這種情況會尤為明顯。但是這在c語言中有時候是很難避免的事情,總不能為了數值傳遞設置大量的全局變量吧。

我的辦法是設置結構體,把意思相近的參數合並成一個整體,然後為這個結構體設置賦值函數。這樣在一定程度上簡化了主要函數的參數個數,便於記憶。

二、改進代碼總體結構

1、解除全局變量的噩夢

在c語言編程中不可避免的要使用全局變量。傳遞數值、進行條件判斷等等時,全局變量給我們帶來了極大的方便,但同時也帶來了噩夢。有時,全局變量根本不是自己預想的數值,而是被哪個莫名的代碼悄悄修改了,要在那麼多代碼中查找這個作祟者簡直痛苦不堪。

好的做法是把全局變量設置成static,只能在本文件中看到,然後編寫訪問/設置函數來控制變量的訪問入口。查找函數總比查找一個小小的賦值語句簡單的多,起碼還有斷點可用。退一步講,如果使用多線程或者多進程沒有斷點可用,那麼好的做法是使用宏定義編寫訪問控制點,在宏定義中可以加入打印,把這個語句在的文件和函數都打印出來,我就不信,找不到它,哈哈哈。

2、避免函數傳遞中的隱形bug

c語言的參數傳遞其實就是傳遞的一塊內存,在函數執行時,在這塊內存中,根據參數類型取得一塊塊相應大小的數據。這樣就產生了隱形的bug。比方說,在沒有記住函數參數類型的情況下,傳遞了一個結構體給它,結果該函數只是幾個int類型的參數,這時編譯器也不會報錯給你,更恐怖的是代碼照樣可以運行,如果沒有測試充分,沒准代碼還能正確運行。

這樣一個隱形的bug會把你搞的很慘。要把它干掉,最簡單的辦法就是加入函數聲明。靈活便利的c編譯器,在函數調用上,沒有強制要求加入函數聲明,而函數聲明尤其在調用另外文件的函數時,很重要。如果調用與聲明的類型不一致,編譯器會報錯。這樣這個隱形bug就不會在騷擾你了。所以,不要圖省事,為了以後的和諧生活,聲明你要調用的每一個函數吧。

3、調整函數位置

在多文件程序當中,函數的位置很重要,要根據每個文件完成的功能調整函數的位置,不能亂放。亂放的現象在那些臨時加的被調用函數身上表現的非常突出我經常就干這事)。亂放導致的後果就是,後面維護代碼時,根據文件名去找相關的函數,根本沒有,結果一搜發現它在一個內容完全不相干的文件中。為了不打亂思路,臨時放就放吧,但是這個功能完了,一定要把這個函數重構到它應該在位置上。

對於重構來講,想到的暫時就是這些,其實有一些是要開始編寫時就要注意的。這也應了這麼一句話:重構本來就應該是融入到日常的代碼編寫中。最高境界就是手中無重構,心中也無重構。

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