用c++開發一款商業產品,需要哪些規范

最近開始接手項目組的開發管理工作,項目組開發的產品一期功能基本開發完成,進入內部測試及小渠道發布階段,然而產品的穩定性還存在很大問題。

先做一下背景介紹,項目組開發的是一款面向C端的互聯剛產品,運行操作系統為windows。整個項目使用c++開發,總體代碼量大概在數十萬行。

c++是一門很復雜的語言,有很多強大的特性,然而當用其開發一款商業產品時,這些特性可能會帶來麻煩。所以當設計c++的使用規范時,更多的是對其做減法。

本文的規范針對VC++開發環境,開發工具為Visual Studio。

文件系統目錄規范

一款完整的商業產品開發通常會涉及到很多模塊,這其中包括可執行程序(.exe),項目組開發的庫(靜態庫或動態庫),第三方的庫(靜態庫或動態庫),測試程序,這么多的模塊和代碼,需要一個良好組織的目錄結夠。
這里假設項目名稱為XXProject

  • XXProject
    • XXProject.sln
    • Bin
      • Debug
      • Release
    • TestBin
    • Debug
    • Release
    • Src
    • Document

其中Bin存放需要發布的可執行程序,TestBin存放測試程序的可執行文件,Src存放項目的工程文件和源代碼,Document存放項目相關的開發文檔(如項目說明,代碼規范等)。

接下來假設項目包括如下工程:XXMain(發布的主程序),XXUpdate(升級程序),XXSdk(自己開發的基礎庫),XXThird(第三方庫), XXTest(測試程序)

  • Src
    • XXMain
    • XXMain.vcxproy
    • code文件
    • XXUpdate
    • XXUpdate.vcxproy
    • code文件
    • XXTest
    • XXTest.vcxproy
    • code文件
    • XXSdk
    • XXSdk.vcxproy
    • code文件
    • ThirdLib
    • XXThird
    • Lib
    • Debug
    • Release
    • Include
      Lib庫用來存放靜態庫,動態庫的.a文件,Include用來存放公共頭文件,ThirdLib用來存放第三方庫。

解決方案目錄規范

解決方案目錄是VS開發工具提供的邏輯上組織項目的方式,與物理文件系統并不存在對應關系。
仍然假設項目包含上述項目和模塊。

  • Solution (解決方案)
    • Application (解決方案文件夾)
    • XXMain (工程)
    • XXUpdate (工程)
    • Test (解決方案文件夾)
    • XXTest (工程)
    • Library (解決方案文件夾)
    • XXSdk
    • ThirdLibrary(解決方案文件夾)
    • XXThird
    • Public (解決方案文件夾)
    • 公共頭文件

代碼編寫規范

1:禁用全局變量

全局變量會帶來晦澀的依賴問題

2:禁用goto指令

goto指令的代碼難以閱讀和維護

3:禁用異常機制

c++的異常機制有很多缺陷且復雜

4:用struct封裝數據,使用class定義對象

C++中class和struct幾乎沒有區別,在規范中進行語義的區分

5:struct和class必須顯示包含構造函數
6:除非特殊情況,總是將析構函數定義為虛函數

方便繼承時的資源釋放

7:不要在構造函數中執行復雜操作,推薦加入init函數用于初始化操作

構造函數沒有返回值,難以反饋錯誤

8:不要在構造函數中調用虛函數

構造函數中的虛函數不會重定向到子類。

9:慎用繼承

相比對象組合,繼承帶來更強的依賴,推薦使用接口繼承而不是對象繼承

10:禁用多重繼承(接口繼承除外)

多重繼承通常代表不好的設計

11:慎用運算符重載

運算符重載會混淆代碼的語義,應只在不會造成混淆時使用

12:將成員設置為私有并提供訪問函數

封裝是降低代碼耦合的有力武器

13:將同一訪問權限的成員定義在一起

可以按照public,protect,private順序進行組織

14:避免出現大而全的類

當一個類的代碼超過1000行,應有所警惕,超過2000行,則應考慮拆分(行數不包括注釋)

15:頭文件應包含它所需要的頭文件

這樣可以保證cpp文件引入該頭文件后不需要包含其它頭文件

16:合理的組織引入的頭文件,不要重復引入,不要引入不必要的頭文件

可以以系統頭文件,第三方庫頭文件,項目組庫頭文件,本程序頭文件來組合,不同類型頭文件之間用空格隔開

17:頭文件使用#define宏來避免多重包含

pragma once 指令只有VC編譯器能識別

18:允許合理的使用友元特性

19:使用引用傳遞對象類型參數, 對于不需要改變的參數加入const修飾符

引用傳遞可以避免對象拷貝

20:函數應該進參在前,出參在后

21:使用明確的返回值指示函數的運行結果,而不是用返回的內容來指示結果

推薦: int GetDeviceName(string& deviceName);
不推薦: string GetDeviceName()

22:聲明基本類型變量后立即賦值

正確 int nCount = 0; bool bSuc = false; 錯誤 int nCount; bool bsuc;

23:使用內聯,枚舉,常量來代替宏

宏的使用有很多弊端,應盡量避免

24:使用singleton模式代替靜態類

相比靜態類,singleton模式可以更好地控制初始化時機。

25:使用share_ptr來管理指針

指針和管理在復雜項目中十分困難,使用智能指針是不二選擇

26:使用weak_ptr來處理循環引用
27:明確對象或資源的生存周期

明確對象的生存周期通常代表著良好的設計

28:合理的使用縮進,空格

最重要的是保持風格的統一,自動生成的代碼可能會打破這種統一,應該靈活設計規則

29:合理使用typedef縮減類型的長度,合理使用auto

使用stl時經常會導致過長的類型,合理使用auto可以有效減少代碼長度

命名規則

由于是在VC環境下開發,沿用微軟的命名駝峰命名法

選擇哪種命名方式實際上不是很重要,最重要的是保持統一

  • 代碼文件: DeviceMgr.h, DeviceMgr.cpp
  • 解決方案目錄: NetLibrary
  • 工程篩選器: DataModel
  • 類:CDeviceMgr
  • 結構體: DeviceInfo
  • 變量: listDevice
  • 類成員: m_deviceName
  • 函數: GetName; GetDeviceName;
  • 代表bool含義的變量: 都以b開頭,如:bOk, bSafe
  • 代表整數含義的變量: i表示符號整數,n表示無符號整數
  • 避免無意義的變量名和縮寫: 如 x,dn(deviceName)等

注釋規則

  • 文件注釋:注明文件作者,聯系方式,文件代碼作用,重大修改記錄等
  • 類注釋:說明類的作用,使用限制等等
  • 函數注釋: 盡量依靠意義明確的函數命名而不是依靠注釋,說明函數的使用限制,對于意義不明確的參數加以說明
  • 變量注釋:盡量依靠意義明確的變量命名而不是依靠注釋,特殊情況。
  • 實現注釋: 對于使用了非常規技巧,或復雜算法,或很復雜的業務邏輯部分要加入注釋說明

原則: 注釋應風格統一,簡短而意義明確,最終目的是有效幫助其它人閱讀和理解代碼的目的

日志

日志的打印十分重要,是產品發生問題時重要的參考依據

  • 日志的打印要盡量詳盡,合理劃分日志等級,一般為Fatal, ERROR, WARNING, DEBUG, INFO
  • 統一使用unicode(utf-16)編碼來輸出日志
  • 提供異步打印日志的接口
  • 提供定期清理日志的機制
  • 在發布版中將日志等級設置為ERROR或更高,提供配置文件供調整日志等級

一些其它規則

  • 避免大而全的類(代碼控制在1000行以內)
  • 避免過長的函數(代碼控制在200行以內)
  • 避免深層的嵌套(不要超過3層)
  • 使用do-while-break技巧來避免重復寫釋放資源的代碼
  • 盡量使用RALL技巧來釋放資源
  • 當函數或代碼廢棄時,應與標注,最好將其注釋掉并定期清理

線程和鎖

復雜的項目肯定會涉及到多線程開發,而開發多線程程序是十分困難的。據我們統計,項目組產品有70%左右的崩潰和bug和線程有關。

將線程模塊獨立出來,交給項目最有經驗的開發人員管理和維護,對外暴露抽象接口,屏蔽線程的概念。
強制使用RALL技術來使用鎖

未盡
本文并沒有涉及到C++規范的所有方面,歡迎討論和補充

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,269評論 25 708
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,923評論 18 139
  • After our more-than-10-hour flight, we successfully lande...
    doooodles閱讀 271評論 4 1
  • 老生常談的一個話題,一個想當年的丑聞,給青島抹黑的一個片段。 但是,既然出了這樣的負面消息,雖然時間過去那么久了,...
    煩人的昵稱閱讀 259評論 0 0
  • 鄙人姓瀟,名柒泩,[化]字嘛……很不巧我也不知道,自幼習武,琴棋書畫,吹啦彈唱,樣樣精通……停停停!不扯了不扯了,...
    畫涼V泩閱讀 236評論 1 0