2022-01-30 11:06:27|已瀏覽:4741次
01、排版問題
程序是一種出版物。意味著程序員們會先閱讀,最后才輪到機器。機器的快樂就是程序能編譯,機器才不在乎程序寫的有多么漂亮,可是人們應該保持程序的美觀。有時人們會過度關心:用漂亮的打印機呆板地打印出漂亮的輸出,而這些輸出只是將所有介詞用英文文本以粗體字體凸顯出來,都是些與程序無關的細節。雖然有很多人認為程序就應該像 Algol.68 所描述的一樣(有些系統甚至要求照搬該風格編寫程序),可清晰的程序不會因為這樣的呈現而變得更清晰,只會使糟糕的程序變得更可笑。
對于清晰的程序來說,排版規范一向都是至關重要的。當然,眾所周知最有用的是縮進,但是當墨水遮蓋了意圖時,就會控制住排版。因此即便堅持使用簡單的舊打字機輸出,也該意識到愚蠢的排版。避免過度修飾,比如保持注釋的簡潔和靈活。通過程序整齊一致地說出想表達的。接著往下看。
02、變量命名
對于變量名稱,長度并不是名稱的價值所在,清晰的表達才是。不常用的全局變量可能會有一個很長的名稱,像 maxphysaddr。在循環中每一行所使用的數組索引,并不需要取一個比 i 更詳盡的名字。取 index 或者 elementnumber 會輸入更多的字母(或調用文本編輯器),并且會遮蓋住計算的細節。當變量名稱很長時,很難明白發生了什么。
03、指針的使用
C語言不同尋常,因為它允許指針指向任何事物。指針是鋒利的工具,像任何這樣的工具一樣,使用得當可以產生令人愉悅的生產力,但使用不當也可以造成極大的破壞。指針在學術界的名聲不太好,因為它太危險了,莫名其妙地就變得糟糕的不行。但我認為它是強大的符號,它可以幫助我們清楚地自我表達。
04、過程名稱
過程名稱應該表明它們是做什么的,函數名稱應該表明它們返回什么。函數通常在像 if 這樣的表達式使用,因此可讀性要好。
05、注釋
這一個微妙的問題,需要自己體會和判斷。由于一些原因,我傾向于寧可清除注釋。第一,假如代碼清晰,并且使用了規范的類型名稱和變量名稱,應該從代碼本身就可以理解。第二,編譯器不能檢查注釋,因此不能保證準確,特別是代碼修改過以后。誤導性的注釋會非常令人困惑。第三,排版問題:注釋會使代碼變得雜亂。
但有時我會寫注釋,像下文一樣僅僅只是把它們用于介紹。例如:解釋全局變量的使用和類型(我總是在龐大的程序中寫注釋);作為一個不尋常或者關鍵過程的介紹;或標記出大規模計算的一節。
06、復雜度
許多程序過于復雜,比需要有效解決的問題更加復雜。這是為什么呢?大部分是由于設計不好,但我會跳過這個問題,因為這個問題太大了。然而程序往往在微觀層面就很復雜,有關這些可以在這里解決。
▪ 規則 1:不要斷定程序會在什么地方耗費運行時間。瓶頸總是出現在令人意想不到的地方,直到證實瓶頸在哪,不要試圖再次猜測并加快運行速度。
▪ 規則 2:估量(measure) 在沒有對代碼做出估量之前不要優化速度,除非發現最耗時的那部分代碼,要不也不要去做。
▪ 規則 3:當 n 很小時(通常也很小),花哨的算法運行很慢。花哨算法有很大的常數級別復雜度。在你確定 n 總是很大之前, 不要使用花哨算法。(即使假如 n 變大,也優先使用規則 2).例如,對于常見問題,二叉樹總比伸展樹高效。
▪ 規則 4:花哨的算法比簡單的算法更容易有 bug,而且實現起來也更困難 盡量使用簡單的算法與簡單的數據結構。
以下幾乎是所有實際程序中用到的數據結構:
▪ 數組
▪ 鏈表
▪ 哈希表
▪ 二叉樹
當然也必須要有把這些數據結構靈活結合的準備,比如用哈希表實現的符號表,其中哈希表是由字符型數組組成的鏈表。
▪ 規則 5:以數據為核心 如果選擇了適當的數據結構并把一切都組織得很有條理性,算法總是不言而喻的。編程的核心是數據結構,而不是算法。(參考 Brooks p. 102)
▪ 規則 6:就是沒有規則 6。
07、數據編程
不像許多 if 語句,算法或算法的細節通常以緊湊、高效和明確的數據進行編碼。眼前的工作可以編碼,歸根到底是由于其復雜性都是由不相干的細節組合而成。分析表是典型例子,它通過一種解析固定、簡單代碼段的形式,對編程語言的語法進行編碼。有限狀態機特別適合這種處理形式,但是幾乎任何涉及到對構建數據驅動算法有益的程序,都是將某些抽象數據類型的輸入“解析”成序列,序列會由一些獨立“動作”構成。
也許這種設計最有趣的地方是表結構有時可以由另一個程序生成(經典案例是解析生成器)。有個更接地氣的例子,假如操作系統是由一組表驅動,這組表包含連接 I/O 請求到相應設備驅動的操作,那么可以通過程序“配置“系統,該程序可以讀取到某些特殊設備與可疑機器連接的描述,并打印相應的表。
數據驅動程序在初學者中不常見的原因之一是由于 Pascal 的專制。Pascal 像它的創始人一樣,堅信代碼要和數據分開。因而(至少在原始形式上)無法創建初始化的數據。與圖靈和馮諾依曼的理論背道而馳,這些理論可都是定義存儲計算機的基本原理。代碼和數據是一樣的,或至少可以算是。還能怎樣解釋編譯器的工作原理呢?(函數式語言對 I/O 也有類似的問題)
08、函數指針
Pascal 專制的另一個結果是初學者不使用函數指針。(在 Pascal 中沒有把函數作為變量) 用函數指針來處理編碼復雜度會有一些令人感興趣的地方。
指針指向的程序有一定的復雜度。這些程序必須遵守一些標準協議,像要求一組都是相同調用的程序就是其中之一。除此之外,所要實現的只是完成業務,復雜度是分散的。
有個協議的主張是既然所有使用的功能相似,那么它們的行為也必須相似。這對簡單的文檔、測試、程序擴展和甚至使程序通過網絡分布都有幫助——遠程過程調用可以通過該協議進行編碼。
我認為面相對象編程的核心是清晰使用函數指針。規定好要對數據執行的一系列操作,以及對這些操作響應的整套數據類型。將程序合攏到一起最簡單的方法是為每種類型使用一組函數指針。簡而言之,就是定義類和方法。當然,面向對象語言提供了更多更漂亮的語法、派生類型等等,但在概念上幾乎沒有提出額外的東西。
數據驅動程序與函數指針的結合,變成了一種表現令人驚訝的工作方法。根據我的經驗,這種方法經常會產生驚喜的結果。即使沒有面向對象語言,無需額外的工作也可以獲得 90% 的好處,并且能更好地管理結果。我無法再推薦出更高標準的實現方式。我所有的程序都是由這種方式組織管理,而且經過多次開發后都相安無事——遠遠優于缺少約束的方法。也許正如所說:從長遠來看,約束會帶來豐厚的回報。
注:尊重原創文章,轉載請注明出處和鏈接 http://m.dedgn.cn/news-id-19377.html 違者必究!部分文章來源于網絡由培訓無憂網編輯部人員整理發布,內容真實性請自行核實或聯系我們,了解更多相關資訊請關注c語言頻道查看更多,了解相關專業課程信息您可在線咨詢也可免費申請試課。關注官方微信了解更多:150 3333 6050