糟糕的、差勁的,以及不該來當程序員的程序員

fmms 13年前發布 | 9K 次閱讀 程序員

缺乏根據代碼推導的能力

根據代碼推導意味著能夠跟蹤執行路徑(“在腦子里運行程序”),并且明白代碼的目標是什么。

癥狀表現

  1. 存在“莫名代碼”,或是對程序目標毫無成效,但卻在拼命維護的代碼(比如,初始化了卻從未使用的變量,調用了和目標無關的函數,產生了未被使用的輸出等等)
  2. 將等效函數多次執行(例如:多次調用 save ()函數,“只是為了確定真的保存了”)
  3. 通過撰寫多余代碼覆蓋掉出錯代碼的結果,來修復缺陷
  4. “車轱轆話代碼”(yoyo code),即將一個值轉換成一種不同的表示,然后又把它轉換成原始的樣子。(例如:將一個十進制數轉換成一個字符串,又轉回一個十進制數,或用空白填充一個字符串,又對它做空白修剪操作)
  5. “推土機式代碼”(bulldozer code),表面上看是把代碼塊打散成若干子程序的重構動作,但是這些打散后的若干子程序卻完全不可能在另一種環境中復用(因為它們之間有很高的耦合,不能分開使用)

補救措施

為了克服這方面的不足,程序可以采用 IDE 自帶的調試器作為輔助,如果該調試器提供了單行步進能力的話。例如,在 Visual Studio 中,就可以在出問題的代碼區塊的開頭設置一個斷點,并通過按“F11”鍵單行步進,并檢查變量值的前后變化——直到你理解代碼是要做什么事為止。如果目標環境中沒有調試器這種功能特性,那就找一個有這種特性的來練手。

我們的目標是達到這么一個狀態,你可以不再需要調試器就可以在腦子里來跟蹤代碼走向,并且你有了足夠的耐心來根據程序狀態來思考代碼在做什么。回報是識別冗余和無用代碼的能力,以及從已有代碼中發現缺陷,并且不必從頭重新實現一遍整套算法。

未能透徹理解語言的程序設計模型

面向對象的程序設計是一個語言模型的例子,其他的還有函數式或聲明式程序它們中的每一個都與面向過程的或是命令式的程序設計有著顯著的不同,正如面向過程的程序設計與匯編或是基于 GOTO 的程序設計有著顯著的不同一樣。還有一些語言,它們從屬于一種主要的程序設計模型(比如面向對象的程序設計),但是同時也引入了一些它們提供的改進,比如列表解析、泛型、鴨型型別(譯注:即用相同的接口和大部分輸出響應來模擬某種型別,實際上有所不同的型別,用語取自諺語“如果它叫喚時像只鴨子、吃食時像只鴨子、連跛腳都像只鴨子,那它就是只鴨子”)等等。

癥狀表現

  1. 不擇手段地使用各種語法來打破當前使用的模型,爾后采用命令式/過程式風格來書寫余下的程序
  2. (面向對象)試圖調用未實例化類中的非靜態函數和變量,并且難以理解為何通不過編譯(譯注:即分不清類和對象)
  3. (面向對象)寫一大堆“xxxxxManager”類,里面包含所有操作類的方法,但這些類卻沒有自己的方法。(譯注:即仍然把類看作 struct,未能掌握用類自己的方法——C++中叫做成員函數——來操作類數據的新模型)
  4. (關系型)將數據庫當作一個對象存儲,在客戶代碼中完成所有的連接和關系模塑
  5. (函數式)為相同的算法創建多個函數版本來操作不同型別和操作數,而非將高層抽象的函數傳遞給一個泛化的實現
  6. (函數式)手動緩存確定性函數(譯注:即對于同樣輸入返回同樣結果的函數)的返回結果,即使平臺會自動完成這件事(例如 SQL 和 Haskell)
  7. (純函數式)使用從別人程序里復制-粘貼的代碼來處理與I/O和單子
  8. (聲明式)采用命令式代碼逐個地設置變量的值,而不使用數據綁定

補救措施

如果你的技能缺乏是無效教學或研究的產物,那么另一個老師就是編譯器本身。要學習一種新的程序設計模型,在效果方面無與倫比的方法就是啟動一個新工程并將自己投入在應用那些全新結構上,別管它們是什么,也別管看上去傻不傻。你還需要練習使用你熟悉的一切來解釋該模型的特性,用語不妨粗糙一些,然后不斷重復地構造你的新詞匯表,直到你同樣掌握了新特性的精妙之處為止。例如:

  • 第1階段:“面向對象就是帶有方法的記錄型別”(譯注:記錄即C-style struct)
  • 第2階段:“面向對象中的方法,就是在一個小程序里運行的函數,這個小程序帶有自己專屬的全局變量”
  • 第3階段:“這些全局變量被稱為域,其中有些帶有私有訪問層級,在這個小程序之外是看不到它們的”
  • 第4階段:“為元素搞私有和公有訪問層級的名堂,這個思想是要隱藏實現細節,并且只暴露一個干凈的接口,即所謂封裝”
  • 第5階段:“封裝意味著我的業務邏輯不必被實現細節所污染”

第5個階段看起來對所有語言都適用,因為它們的確是想要程序員理解到這一步,這樣他們就可以表述程序的目的,而不會將它埋藏在如何實現的具體做法中。再舉函數式程序設計作為另一例:

  • 第1階段:“函數式程序設計就是把確定性函數鏈接在一起”
  • 第2階段:“當所有的函數都成了確定性的,它們在要求輸入結果之前不必被執行,并且只須需要多少結果就執行多少部分即可。即所- 謂緩式評估求值和部分評估求值”
  • 第3階段:“為了支持緩式評估求值和部分評估求值,編譯器要求我以對單個參數做變換的形式撰寫函數,有時變換的結果是另一個函數。即所謂柯里化”
  • 第4階段:“當所有的函數都完成了柯里化后,編譯器就可以運用一個約束求解器來決定最佳執行計劃了”
  • 第5階段:“通過讓一個約束求解器來決定機器細節,我撰寫程序時就可以只描述我想要什么結果,而非怎樣得到結果了”

 本文由用戶 fmms 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!