1. 背景
C++ 是 Google 大部分開源專案的主要程式撰寫語言之一。正如每個 C++ 開發者都知道的,C++ 有很多強大的特性,但這種強大不可避免的導致它走向複雜,使程式碼更容易產生 bug,難以閱讀和維護。
本指南的目的是通過詳細闡述 C++ 注意事項來駕馭其複雜性。這些規則在保證程式碼易於管理的同時,也能高效使用 C++ 的語言特性。
風格,亦被稱作可讀性,也就是指導 C++ 程式撰寫的約定。使用術語「風格」有些用詞不當,因為這些習慣遠不止程式碼文件格式化這麼簡單。
大部份 Google 主導的開源專案均符合本指南的規定。
注意:本指南並非 C++ 教程,我們假定讀者已經對 C++ 非常熟悉。
1.1. 風格指南的目標
為什麼要有這份文件?
我們相信這份指南應該可以達成幾項核心目標。以下是通用於所有規則的幾項基礎 原因。把這些想法放到前面,我們希望大家可以就這些問題進行討論,也可以讓不斷成長的開發者社群了解:為什麼要有這些規則?這些規則為什麼要這麼訂?如果你能了解每一條規則訂立的目的為何,那麼你應該能清楚了解在什麼情況下可以不遵守某條規則(有些規則是可以的),或是如果想修改某些規則的話,需要考慮那些地方、需要有哪些配套措施。
眼前這份指南的目標如下:
- 風格規則必須夠份量
一條規則所帶來的效益必須夠大,才能要求所有的工程師將之牢記在心。衡量效益的標準是相對於「沒有這條規則的話,一般專案的程式碼會變成什麼樣子」而言。因此,若是有條規則可以用來排除某項非常糟糕的寫法,但如果沒什麼人會這麼做,那麼這條規則的效益就不高。這項原則主要用來解釋為什麼我們「不定某些規則」,而不是「要定某些規則」。舉例來說,
goto
語法抵觸了下列多項原則,但因為已經很少人用它了,所以這份文件中沒有特別討論goto
的條文。- 為程式碼的閱讀者(而非撰寫者)考量
我們的程式碼(以及大部份使用到的元件)一般來說都會持續使用、維護好一段時間。因此,接觸這些程式碼的人,大部份的時間會花在閱讀程式碼上,而不是撰寫。我們刻意地選擇讓一般軟體工程式在閱讀、維讀和除錯時能最舒服的規則,而不是最方便撰寫的規則。「為閱讀者留下線索」是這項原則中特別通用的一項要點:當某段程式碼(例如:指標控制權的轉移)會發生令人意外或不尋常的行為時,在發生點留下一些文字上的提示,是非常重要的(
std::unique_ptr
示範了如何在呼叫端明確告知控制權將要轉移)。- 和現有的程式碼保持一致
在整份程式碼庫中使用一致的風格,有助我們專注於其他(更重要的)問題上。保持一致性也有助於自動化:用來將程式碼格式化或是調整
#include
的工具程式,只有在程式碼維持工具程式預期格式的情況下,才能確保運作無誤。在許多情況下,「保持一致」性的規則,就只是「隨便挑一種格式,不要再吵了」的結果。在這些關鍵點提供彈性所能帶來的好處,遠不及人們爭執所消耗的成本。- 如果合適的話,和其他 C++ 社群習慣保持一致
和其他使用 C++ 的組織保持一致所能帶來的好處,跟在我們的程式碼庫保持一致的好處相同。如果 C++ 標準中的某個功能已經解決問題,或是某種寫法已經廣為人知並接納,那我們就該使用。然而,有時候標準功能或是寫法是有缺陷的,或是在設計時沒有考慮我們程式碼庫的特殊需求。在那些情況下(後詳述),可能會限制或禁止使用標準功能。某些情況下,我們會比較傾向使用自製或第三方的函式庫,而非 C++ 標準所定義的版本。可能是因為 C++ 標準的版本沒有特別出色,或是將現有的程式碼轉成使用標準界面的好處不大。
- 避免產生意料之外或危險的結果
C++ 中有許多功能,可能會造成令人意外的結果,或是具有潛在的危險性。這些功能遠比一般人想像的要多。有些風格規範限制是在避免程式員掉入類似的陷阱中。這些限制的豁免條件通常非常高,因為繞過這些規則通常等於直接為執行正確性帶來風險。
- 避免讓一般程度的 C++ 程式員覺得高深或是難以維護
由於 C++ 的語法非常複雜,有些功能可能不是大家都很熟悉。若是某段程式碼被應用的範圍很廣,某種程度上允許使用較高深的語言功能。這是因為這些複雜的實作所能帶來的好處被應用的次數放大;而把這程式碼套用在程式碼庫的其他部份時,不需要再一次花時間把它搞懂。若有任何疑慮,這類規則是否可以豁免,可以和專案領導人討論。這個原則對我們的程式碼庫來說格外重要,因為我們的專案成員隨時都會變動,程式碼的負責人也會變動:就算現在和這段程式碼有關的所有成員清楚了解每一個細節,不代表幾年後還是一樣。
- 謹記我們的規模
當你面對數十億行的程式碼、數千名參與其中的工程師時,任何一名工程師的錯誤或是便宜行事,都可能造成許多人的困擾。舉例來說,維持全域命名空間不被污染是非常重要的:在數十億行的程式碼庫中,如果每個人都東西往全域命名空間裡丟,那麼命名衝突幾乎是無法避免、也是難以解決的。
- 必要時,為最佳化讓步
有時候,為了執行效能,最佳化是適當且必要的,即使因此而違反本文件中的某些原則也在所不惜。
這份文件旨在提供最全面的指引,以及合理的限制。一如往常,我們會以常識和好習慣優先。為了達到此目的,我們綜合了整個 Google C++ 使用社群已經建立的慣例。不是只有你個人的喜好,也不是只有你們團隊的。當你面對巧妙或不尋常的語言技巧時,請保持多疑及謹慎的態度面對:沒有明令禁止的事情,不代表亮了綠燈。請自行判斷。如果你不確定,請不吝多與專案領導人討論。