1. 程式人生 > >編寫程式——程式碼的排版

編寫程式——程式碼的排版

    程式碼排版是每個軟體工程師都要面對的問題。好的排版不僅可以讓讀程式碼的人感到賞心悅目,更重要的是可以從程式碼格式中發現程式的內在邏輯結構。這就好像文章、部落格的一樣,它們會通過分段、空白行、標點符號等各種元素來體現文章內在結構,從而提升讀者的閱讀體驗。試想,閱讀這兩句話“子曰見賢思齊靨見不賢而內自省也”與“子曰,見賢思齊靨,見不賢而內自醒也”,有多大的差異。我們的古書沒有版式和標點,有一部分原因是古書記錄在在竹木簡上,省去標點可以減少記錄的成本。有意思的是,在計算機發展的早期,那些程式設計師也會因為儲存的限制而犧牲程式碼的排版,算是殊途同歸。幸好,現在這兩個問題都已經不復存在。
其實有很多軟體工程的經典書籍都會有專門的章節來講這個問題,像《程式碼大全》、《簡潔程式碼》及各種語言的入門書籍,維基百科上關於Programming Styles的詞條甚至列出了大部分主流程式語言需要注意的風格。不過在我看來,最重要的一點是程式設計師在寫程式碼時候,一定要以幾及彼的想想當自己來閱讀這樣的程式碼時是什麼感覺。我們寫的程式碼最終不僅要釋出給計算機的編譯器、釋出給我們的客戶,還要釋出給程式碼的維護者。他們拿到程式碼,首要目的是想花更少的時間、更快的理解這份程式碼有什麼功能。說白了,程式碼的維護者就你寫的程式碼的使用者,需要給他們提供好的使用者體驗。 給閱讀程式碼的人提供好的“使用者體驗”其實是個很大的命題,比如符號(函式、變數)的命名、高質量的抽象資料結構和子程式的設計等等,這裡只說說程式碼的排版問題,不然不僅要扯地天昏地暗,還可能會扯到蛋:)。從我的定義,程式碼排版主要指的是通過使用空行、空白符,對單個原始檔中程式碼組成元素進行空間佈局——橫向空間佈局和縱向空間佈局。橫向空間佈局上比較簡單,我會遵循傳統的原則——程式碼行的字元數不超過80個字元,這個很容易理解,主要是為了避免在閱讀長程式碼時需要在編輯器中橫向來回拖動視窗。對於縱向空間佈局,這裡以C語言為例,C程式碼程式碼的組成元素包括:
  • 註釋檔案頭,File Header
  • 依賴標頭檔案,Dependency File
  • 外部變數和函式,Extern Definition / Declaration
  • 巨集定義,Macro Definition
  • 型別定義,Type Definition
  • 全域性變數和函式定義和宣告,Global Definition / Declaration
  • 私有變數和函式定義和宣告,Internal Definition / Declaration
  • 函式實現,Function Implementaion
通常我會在原始檔中按照上訴列表的順序依次佈局各個部分的內容。具體到每個單獨的部分,可遵循的有幾個原則:1)按照首次使用的順序來排放;2)
並列關係按照字母序來排放;3)按照關係的親疏排放位置。這樣主要有幾個好處,一是對程式碼的排版建立統一的約定,日後你自己或者維護你程式碼的同志看程式碼時,可以到檔案對應的位置尋找相應的內容,例如你可能想看一下巨集定義在哪裡,就一個快速索引到它是在外部變數的聲明後面,等等。其二是這樣的佈局也比較符合我們的思維習慣,通常我們首次開啟某個原始檔時,會看一下標頭檔案的Revision History,然後跳到某個函式的入口,然後按照樹的廣度優先遍歷依次看完程式碼呼叫樹。按前述,函式的實現佈局看起來像下面圖示的那樣:
這是我對於程式碼排版整體佈局的一個經驗,但程式碼排版可以討論的內容遠不止這一點。你肯定在BBS上見過很多人為了指標型別識別符號’*'是靠近型別比較好呢、還是靠著變數符號比較好呢之類的問題爭得面紅耳赤,還比如還比如…太多了。更甚的是,在實際軟體生產過程中,我們更多要面對的是你和其他人的排版美學產生衝突是,你如何在信仰與現實之間折中之類的問題