天天看點

【深度好文】代碼的保養

不隻女人要保養,代碼也是如此。面向對象程式設計,就是把面對的代碼當作對象一樣,定期對其進行保養。

目錄

一、美顔 Astyle+Source Insight

二、祛痘 cppCheck

三、返老還童 git

四、工欲善其事必先利其器

一、美顔 Astyle+Source Insight

1.1真假小龍女的問題

都說秀色可餐,同樣的角色,都是小龍女,但是效果不一樣。

【深度好文】代碼的保養

實作同樣的功能,有的代碼一目了然,像詩一樣賞心悅目;有的卻像SHI一樣,如下面的代碼,雖然功能正常,但看起來什麼感覺?

//C語言混亂大賽作品
#include <stdio.h>
main(int t,int _,char* a)
{
    return !0<t?t<3?main(-79,-13,a+main(-87,1-_, 
main(-86,0,a+1)+a)):1,t<_?main(t+1,_,a):3,main(-94,-27+t,a)&&t==2?_<13? 
main(2,_+1,"%s %d %d\n"):9:16:t<0?t<-72?main(_,t, 
"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l+,/n{n+,/+#n+,/#;#q#n+,/+k#;*+,/'r :'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){nl]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#n'wk nw' iwk{KK{nl]!/w{%'l##w#' i; :{nl]'/*{q#'ld;r'}{nlwb!/*de}'c ;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/") 
:t<-50?_==*a?putchar(a[31]):main(-65,_,a+1):main((*a=='/')+t,_,a+1) 
:0<t?main(2,2,"%s"):*a=='/'||main(0,main(-61,*a, 
"!ek;dc i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m .vpbks,fxntdCeghiry"),a+1);
}      

正如女人愛美一樣,出門必化妝,拍照必美顔;代碼也是需要美顔妝扮,除非你期望後來接手者在心中的十萬個詛咒,這TM誰寫的?尤其對嵌入式系統産品,更新維護周期長,軟體的可讀性就顯得更加重要;代碼規範對後續維護更新是大有裨益的。

1.2 代碼格式化

一般公司不缺編碼規範,缺的是執行。小項目單人完成,編碼風格随心所欲;大項目團隊完成,編碼風格各不相同。目前來說,個人隻發現go語言是編譯時強制格式化,其他語言編譯時,不檢查排版格式。對于編碼規範,不能依靠個人主觀,強推工具自動實作才能提高執行力。

不管編碼使用Keil/MDK、Qt等內建工具,或者純粹的代碼編輯工具Source Insight,一般都支援自定義運作可執行檔案,如Astyle。可以客制化新菜單,一鍵執行Astyle,将代碼一鍵格式化,排版統一、層次分明。

Astyle官網 http://astyle.sourceforge.net/  按要求下載下傳安裝,隻需要AStyle.exe即可。關于其使用和參數,可以在進入Documentation。對代碼基本風格,{}如何對齊、是否換行,switch-case如何排版,tab鍵占位寬度,運算符或變量前後的空格等等,基本上代碼排版涉及的方方面面都有參數說明。個人選擇的編碼參數是

--style=allman -S -U -t -n -K -p -s4 -j -q -Y -xW -xV fileName      

效果如下

int Foo(bool isBar)
{
    if (isBar)
    {
        bar();
        return 1;
    }
    else
    {
        return 0;
    }
}      

建議先參考文檔逐個熟悉作用,确認參數,然後內建到編輯工具,以Source Insight為例。

1、在選項或者工具下(不同Source Insight版本不同)打開“自定義指令”,添加指令和運作。

【深度好文】代碼的保養

2、選擇正确的路徑,結合前面的參數類型,最後必須加上 %f,表示對該檔案執行,

C:\AStyle.exe --style=allman -S -U -t -n -K -p -s4 -j -q -Y -xW -xV  %f
【深度好文】代碼的保養

3、将該指令插入到編輯菜單,後續在編輯欄點選Astyle,即可對目前檔案自動進行格式化排版。

1.3 進階配置

前面隻是Source Insight的基礎擴充,下面簡要說明下進階擴充宏功能,本文隻是描述下基本流程。1、配置菜單

【深度好文】代碼的保養

2、插入之後,在主菜單欄會出現“工作”的菜單,點選Insertifdef,彈出如下對話框

【深度好文】代碼的保養

3、确定之後自動在光标處插入代碼

#if defined (ABCD)

#endif /* ABCD */      

4、不止是支援插入if defined ,還包括插入檔案頭,對h檔案插入避免多次包含的宏,對函數插入注釋,以及自動添加編輯時間、作者名稱等。這些宏配置和前面一樣,至于客制化,比如函數注釋的内容、格式等,也是可以自由定義。5、配置路徑如下

【深度好文】代碼的保養

先關閉全部Source Insight工程,再打開Base.PR,編輯utils.em。如前面的宏 Insertifdef就是如下的代碼

macro InsertIfdef()
{
 sz = Ask("Enter ifdef condition:")
 if (sz != "")
  IfdefSz(sz);
}

// Wrap ifdef <sz> .. endif around the current selection
macro IfdefSz(sz)
{
 hwnd = GetCurrentWnd()
 lnFirst = GetWndSelLnFirst(hwnd)
 lnLast = GetWndSelLnLast(hwnd)
  
 hbuf = GetCurrentBuf()
 InsBufLine(hbuf, lnFirst, "#if defined (@sz@)")
 InsBufLine(hbuf, lnLast+2, "#endif /* @sz@ */")
}      

如Ask就是彈出提示語,sz擷取輸入的内容,再InsBufLine插入兩行代碼。而這些接口的使用說明,隻要打開Source Insight的幫助即可檢視。

【深度好文】代碼的保養

Ask說明:

【深度好文】代碼的保養

例如插入函數注釋的代碼如下:

szInf = Ask("你為什麼要編寫這個函數:")
 szDescription = Ask("請輸入函數的使用注意事項和算法實作:") 
 // begin assembling the title string
 sz = "/******************************************************************************"
 InsBufLine(hbuf, ln, sz)
 InsBufLine(hbuf, ln + 1, " *  Function    -  @szFunc@")
 InsBufLine(hbuf, ln + 2, " * ")
 InsBufLine(hbuf, ln + 3, " *  Purpose     -  @szInf@")
 InsBufLine(hbuf, ln + 4, " * ") 
 InsBufLine(hbuf, ln + 5, " *  Description -  @szDescription@")
 InsBufLine(hbuf, ln + 6, " * ")
 InsBufLine(hbuf, ln + 7, " * modification history")
 InsBufLine(hbuf, ln + 8, " * ----------------------------------------")
 InsBufLine(hbuf, ln + 9, " * v1.0  , @szDay@-@szMonth@-@Year@,  @szMyName@  written")
 InsBufLine(hbuf, ln + 10, " * ----------------------------------------")
 InsBufLine(hbuf, ln + 11, " ******************************************************************************/")      

最終自動插入的函數注釋顯示效果如下:

/******************************************************************************
 *  Function    -  [myFunction]
 *
 *  Purpose     -
 *
 *  Description -  [函數的功能]
 *
 *  modification history
 * ----------------------------------------
 * v1.0  , 22-11-2020,  embedded-system  written   [時間格式可自由設定]
 * ----------------------------------------
*******************************************************************************/      

6、其他宏也是這樣,可以自由配置,當然,開啟這個功能的第一步是先編輯,替換全部szMyName為自己的名字。有一點需要注意的是插入函數注釋時,光标必須在該函數第一個{内,否則無法擷取函數名,會提示錯誤。

1.4 總結

Source Insight內建Astyle自動排版,統一風格;內建宏定義,統一注釋格式、提高效率。

二、祛痘 cppCheck

2.1 祛痘除隐患

依靠美顔可以掩蓋面部瑕疵,如痘痘,但為了極緻,應該從根源祛痘,素顔就美,淡妝濃抹總相宜。代碼規範整齊,還要沒有隐患,大部分開發人員都對警告視而不見,覺得隐患沒啥大問題,

【深度好文】代碼的保養

同樣的美女,若是一臉痘痘,顔值瞬間下降。代碼也是如此,編譯警告如同痘痘,看起來不礙事,實際對代碼的品質和後期維護都是隐患,要培養習慣,凡是警告都要消滅的習慣。

另外對于編碼規範,不隻是排版布局,還有命名規範,例如宏定義使用小寫字母,就必須指出要求修改。是以,代碼必須經過祛痘,除去小隐患,嚴苛的要求,造就趨于完美的代碼。但是,依靠人工檢查效率低下,靜态掃描順便檢查命名規範的神器應運而生。

代碼的靜态檢測工具有很多,為什麼推薦cppCheck?因為它是Qt實作且開源。作為嵌入式軟體開發,Qt可以錦上添花,它本身可以多平台運作,平時使用它開發小工具,模拟驗證部分代碼,比起在真機編譯下載下傳調試快捷友善。

cppCheck官網http://cppcheck.net/,可以下載下傳執行檔案和源碼,稍微有Qt基礎的,可以下載下傳源碼,其Qt工程如下,可以根據自身要求和能力,進行二次開發。

【深度好文】代碼的保養

實作代碼自動格式化和靜态分析,可以有效規避軟體風險。基于開源的Cppcheck,內建Astyle,結合實際開發平台和編碼标準,使用Qt內建的codeCheck誕生了。

codeCheck執行的流程,先将C語言代碼自動格式化,按指定的規則排版對齊,調整代碼間空格和間距,特殊語句強制換行或添加括号等,簡單操作即可完成代碼格式統一化(也就是上一章的配置參數)。然後拆分代碼字元,建立token資料庫,按預置的規則分析代碼是否存在比對的非法代碼,并直覺顯示風險代碼位置以便跟蹤修複。codeCheck不具備編譯文法分析,是以導入的檔案必先確定編譯正常,再進行分析才有意義。

針對實際開發中的問題點,比如變量命名沖突,或者關鍵變量缺少注釋導緻維護更新困難,特别增加了個性化掃描标準。由于個人時間和水準有限,工具還存在優化改進的必要,但基本可滿足正常應用和新人培養。

即使沒有Qt基礎,直接使用開源版本,也是相當給力的,二次開發隻是錦上添花而已。

2.2 代碼掃描與靜态分析

個人二次開發後的主界面如下,和原始的cppcheck差不多,隻是多了命名規範檢查(全局變量必須g_開頭,帶注釋;宏定義、枚舉值禁止包含小寫字母等)。

【深度好文】代碼的保養

“分析”導入檔案或檔案夾後,即可啟動自動格式化并分析代碼邏輯,顯示結果如下:

【深度好文】代碼的保養

選擇“分析結果”欄,則顯示掃描出的風險代碼,标明風險類型和代碼位置,具體顯示如下圖。

【深度好文】代碼的保養
【深度好文】代碼的保養

2.3 源碼分析

非cppcheck源碼,二次開發的代碼片段。

void CheckThread::run()  //運作掃描,這裡是入口
{
 /**/
    QString file = mResult.getNextFile();
    while (!file.isEmpty() && mState == Running) 
    {
        qDebug() << "format file" << file;
        file_format(file);//添加Astyle指令
        mCppcheck.check(file.toStdString());
     /**/
     }
     /**/      
//astyle.exe v3.1  添加代碼格式化
void CheckThread::file_format(const QString file)
{
    QProcess builder;
    QStringList param;

    param<<"--style=allman"<<"-S"<<"-U"<<"-t"<<"-n"<<"-K"<<"-p"<<"-s4"<<"-j"<<"-q"\
        <<"-Y"<<"-xW"<<"-xV"<<file;

    if(file.endsWith(".c",Qt::CaseSensitive)||file.endsWith(".cpp",Qt::CaseSensitive)\
       ||file.endsWith(".h",Qt::CaseSensitive))
    {
        builder.start("codeFormat.exe",param);
        builder.waitForFinished();
    }
}      

2.4 總結

實作代碼自動格式化和靜态分析,可以有效規避軟體風險。關注微信公衆号【嵌入式系統】,可以擷取codeCheck源碼。

三、返老還童 git

3.1 月光寶盒

【深度好文】代碼的保養

愛情不可期,往事成追憶。至尊寶可以使用月光寶盒穿越時空去尋找愛情。對于女人,擁有月光寶盒,即使容顔衰老,也可以回到過去,返老還童,永葆青春。

對于程式員,一份完美的代碼,修修補補,幾經折騰終于封闆;因為儲存不善或者修改記錄丢失,那種痛苦也是一般人無法想象的。為了不會有失去才後悔莫急的痛楚,必須使用版本控制來追溯代碼的過去,程式員的月光寶盒就是Git神器。

3.2 版本控制git

不必說你有多聰明,每天拷貝一份代碼加描述備份;也不要說以往的svn等工具有多先進;這些工具在git的分布式軟體版本控制面前,都不值一提,雖然Git也有缺點,但是依然不能掩蓋它的光芒。

十年來,一直是嵌入式軟體開發,80%的時間使用windows版的git可視化操作,相比指令行,更容易掌握與使用,檢視版本記錄也更加直覺,指令行的操作方式不在本文考慮範圍。git官網https://git-scm.com/。

1、安裝TortoiseGit-2.5.0.0-64bit.msi 一路下一步,這隻是安裝了git的核心功能,要在windows下操作,需要安裝界面外殼。

2、安裝GitExtensions-2.50.02-SetupComplete.msi   或者  Git-2.15.0-64-bit.exe,這是兩種風格的界面,主體功能差不多,個人選擇的是後者。也可以兩個都安裝。

3、安裝過程中出現較多的配置,所有選項中,全部都選帶windows關鍵字的,否則用起來看不出問題,但是儲存的記錄異常。

既然是界面操作,就開啟滑鼠右鍵的快捷圖示。

【深度好文】代碼的保養

後續一些安裝選項,全部選帶windows關鍵字的。

【深度好文】代碼的保養

4、安裝完成後,滑鼠右鍵,會出現 Git GUI Here。

【深度好文】代碼的保養

5、如果是新手可安裝漢化更新檔TortoiseGit-LanguagePack-2.5.0.0-64bit-zh_CN.msi,建議不要安裝,翻譯有點搞笑(rebase-變基)。

3.3 基礎示範

1、配置

【深度好文】代碼的保養

2、建立本地版本庫,git creat repository here,預設操作,即可建立版本,會在test空檔案夾下生成.git 。 

3、在test下随便改動,如新加123.txt,送出改動。此時滑鼠右鍵

【深度好文】代碼的保養
【深度好文】代碼的保養

4、儲存本次修改後,使用Git GUI Here->Repository->Visualize master's History檢視全部版本記錄。

【深度好文】代碼的保養

5、通用配置和常用功能

【深度好文】代碼的保養

3.4 總結

Git的使用尤其是多人合作,注意以下幾點:

1、推送伺服器前先同步;

2、2個分支版本有沖突,先rebase解決;熟練操作前不要使用merge;

3、版本節點不能使用中文,修改描述可以;

4、編譯自動生成的不要送出,可以使用TortoiseGit-->Delete and add in ignore list,濾指定的檔案,即使有改動也不送出;

5、Git自帶的比較工具比較差,可以配置使用外部比較工具。

【深度好文】代碼的保養

一共三處,将Diff viewer和Merge Tool改為HA-BCompare。這個工具的比較功能強大,顯示界面清晰。

四、工欲善其事必先利其器

工欲善其事必先利其器,工具的熟練掌握、合理利用。代碼規範化,靜态掃描排除風險,修改記錄儲存完整,如此,才能保證代碼的品質。