用於記錄工作中出現的問題和編程時需要注意的重點,保證代碼質量和編程效率
代碼質量控制
- 編寫程序時注意編程注意項,保證代碼格式 / 性能 等方面的質量
- 程序編寫完成后需要自測所有改動,並在 JIRA 上詳細備注變更內容;
還要使用 valgrind 工具檢查內存泄漏 / 內存越界,確認功能是正常的 - 自測完成后,與開發前代碼對比,嚴格檢查兩遍沖突后方可提交代碼
編程注意項
-
在提交代碼時,需要嚴格檢查兩遍沖突,防止修改到功能不相關的代碼
以后的代碼提交前應與開發前的代碼多次對比,保證不修改到功能不相關的代碼 -
對於判斷邏輯,能提前判斷則盡量提前做,可減少后面程序執行的代碼,提交效率
-
不要為了方便復制(任何)代碼
-
當在一個條件語句中增加邏輯時,需要考慮到這部分邏輯是否會被觸發,如果不觸發會不會影響功能
同樣的,在增加新的邏輯時,也要判斷這部分邏輯是否需要執行(可能僅在某些條件下才需要觸發) -
代碼中處理異常 / 記錄日志的部分,需要能從異常獲取 / 日志打印中的信息迅速定位到問題,從這個角度來選擇日志的級別以及異常處理的 throw / catch 的位置
一般外部調用的接口都需要記錄調用耗費的時間,可以通過日志排查接口長時間沒有響應 / 返回慢導致的問題
凡是影響到 (執行到這個分支) 輸出日志的內容,盡量都在日志中輸出,確認是哪類原因導致這個結果的產生 -
每次增加配置后,需要增加從內存中 dump 出當前程序配置內容的代碼,用於遠程排查問題時可以獲取相關模塊的配置
-
對於 static 類型的變量/函數,都需要考慮到線程安全
特別是 Env 中的變量 -
生成 / 使用指針時,必須判斷其是否有效,否則易引發段錯誤造成程序崩潰
-
永遠不要相信用戶的輸入對於不是自己產生的數據(用戶輸入)做處理/解析,必須考慮到異常的情況,做全面的判斷
-
消耗內存/cpu的操作應該盡量放在循環/函數外實現
例如解析郵件頭、格式/字符集轉換等操作,盡量減少內存/cpu 消耗以及函數調用 -
代碼需要注意兼容性
新的功能不能影響到舊的代碼,另外在自測過程中需要過舊功能的單元測試,保證兼容性 -
在處理計算的表達式時,需要注意溢出以及除數為 0 的問題
比如這一行代碼,當 nCosLimt 接近 int 上限時,在右邊的表達式中乘上 rate 后將溢出上限變成負數,再除 100 后得到的值仍是負數,與預期的結果相反
// 檢查郵件數量是否超過 cos 上限
static_cast<int>(MBoxHdr.getTotalMsgCount()) >= nCosLimit *
static_cast<int>(nMailCntQuotaWarningRate) / 100)
另外當被除數是一個變量時,需要注意該變量是否可能為 0
代碼&功能優化
代碼優化
當完成一個需求時,需要做以下檢查,判斷是否還有優化的空間
-
當一個函數中存在多塊不相關的邏輯時,將較為簡單的邏輯放在函數前面,復雜的放在后面,能提前的判斷提前
如果該函數有多個出口,那么先執行復雜的邏輯可能會影響性能,且如果中間拋出異常造成跳轉,則原應該執行的簡單邏輯無法執行了 -
重復的代碼需要判斷是否能合並 / 抽象
對於基本相同的邏輯(80%-90% 相同)則需要思考是否能封裝成一個函數,通過參數等判斷執行狀態
對於涉及到相對獨立的變量&數據結構的邏輯,可以抽象成類,根據不同的構造參數來判斷行為
功能&模塊優化
某個模塊/功能的優化流程
- 梳理當前模塊/功能的相關邏輯
- 分析現有模型的優缺點,哪些實現是不合理的,哪里有優化空間,主要是哪部分處理影響性能
- 針對分析的結果來做優化,設計新的實現
其他
- 在文檔的編寫方面,需要遵從最小化原則
即只增加與該 需求/問題 相關的 描述/日志/配置,便於他人理解和維護;
且增加的日志需要能支撐(解釋)所描述的步驟,輸出的內容需要清晰,要根據不同的情況選擇合適的日志級別
- 遇到不熟悉的系統日志,需要對其中字段逐個排查
通過對比正常的日志來確定是哪個點出現問題
- 一個系統安全運行應該有專門的用戶來執行
比如 tomcat 有專門的 user:tomcat,coremail 用戶有專門的 coremail 用戶
需要將執行程序的用戶與 root 用戶分離,當 coremail 用戶被攻破時,將不會擁有 root 用戶的權限;更進一步的話,再增加 cmadm 用戶將系統的程序寫權限限定為 cmadm,正常使用給 coremail 用戶可讀可執行權限,以及修改配置/日志的寫權限
小技巧
- 在 catch 中再次 throw,可以將截獲的異常重新拋出try
{
try
{
...
}
catch(TException & te)
{
if(condition)
throw; // 會跳至外層的 catch 處理
}
}
catch(TException & te)
{
...
}
調試
- 當不清楚問題出在哪部分代碼時,可以注釋掉部分修改的代碼以縮小問題范圍