前言
相對(duì)來(lái)講,對(duì)于一個(gè)programmer來(lái)講,更多的時(shí)間是花在代碼閱讀而不是寫(xiě)代碼上,因此改進(jìn)這方面的技巧和工具能夠?qū)rogrammer的工作效率能起到很大的提升。相對(duì)而言,談?wù)摴ぞ呤窍鄬?duì)簡(jiǎn)單的,因而作為代碼閱讀這一系列文章的頭一篇,我先在此討論一下我總結(jié)和使用的工具,希望能對(duì)別人有所幫助。
正則表達(dá)式
因?yàn)橄旅鎯尚」?jié)介紹的工具的使用都會(huì)涉及到正則表達(dá)式,而且我覺(jué)得任何一個(gè)好的programmer都應(yīng)該了解和掌握正則表達(dá)式。這里我不會(huì)具體講任何正則表達(dá)式的使用,只會(huì)提一些比較general的概念和一些比較有用的鏈接
Regular_expression,讀完這一篇,你會(huì)了解到什么叫做PCRE和各種其他的標(biāo)準(zhǔn),工作中有時(shí)會(huì)遇到寫(xiě)的或者找的正則不能正常工作,這個(gè)時(shí)候你就得考慮是否是因?yàn)檎Z(yǔ)言、環(huán)境、工具支持的正則表達(dá)式標(biāo)準(zhǔn)是否支持你所用的標(biāo)準(zhǔn),比如說(shuō)BSD授權(quán)和GNU授權(quán)的grep對(duì)正則表達(dá)式的支持就不一樣,同樣你也會(huì)知道literal和non-literal、escape以及單引號(hào)和雙引號(hào),拿不同語(yǔ)言對(duì)于string的支持來(lái)講,groovy支持單引號(hào)的字符串,而java卻不支持單引號(hào)字符串,因而它們對(duì)于這些情況時(shí)的做法就不一樣。
搜索工具
-
grep /ack/ ag/pt/ sift /ripgrep
我把這些歸為一類,因?yàn)檫@些工具使用起來(lái)大同小異,大多都支持前面提到的PCRE,雖然有些工具在速度上存在優(yōu)勢(shì),但是對(duì)于AOSP這種規(guī)模的代碼庫(kù)來(lái)講還是性能不足。
sift的作者寫(xiě)了一篇關(guān)于幾個(gè)工具之間的性能對(duì)比,感興趣的可以去看一看,具體選擇看個(gè)人,比如說(shuō)根據(jù)個(gè)人熟悉編程語(yǔ)言不同來(lái)選擇,因?yàn)槟軌蛞欢ǔ潭鹊淖远x還是一種優(yōu)勢(shì)。 -
這是由google工程師開(kāi)源的一款工具,特別適合大規(guī)模的代碼庫(kù)搜索,具體介紹和使用可以看github中的介紹。我在這講一下我個(gè)人遇到的問(wèn)題和解決方案。因?yàn)楣ぷ鞯脑颍?jīng)常需要閱讀
AOSP源碼,codesearch是基于索引的,但是目前來(lái)講并不支持多個(gè)索引,默認(rèn)會(huì)索引執(zhí)行cindex命令目錄下的所有文件,并且把索引文件.csearchindex存放在HOME目錄下。-
當(dāng)我完全不清楚搜索內(nèi)容在哪一塊的代碼中,基于整個(gè)
AOSP代碼庫(kù)的搜索會(huì)很方便,而且這個(gè)時(shí)候codesearch的速度優(yōu)勢(shì)就體現(xiàn)出來(lái)了,下面是我拿codesearch和ag做的一次對(duì)比,當(dāng)然拿基于索引的搜索和不基于索引的搜索相比是很不公平的,我這只想體現(xiàn)codesearch的優(yōu)勢(shì)所在和應(yīng)用場(chǎng)景。$ time codesearch is_first_stage
real 0m1.645s
user 0m0.430s
sys 0m0.135s$ time ag is_first_stage
real 4m0.311s
user 0m8.858s
sys 1m13.302s 另一方面基于索引整個(gè)代碼庫(kù)的搜索會(huì)導(dǎo)致很多時(shí)候會(huì)出現(xiàn)一大堆搜索結(jié)果,而且codesearch默認(rèn)會(huì)將多個(gè)代碼庫(kù)的索引合并到
$HOME/.csearchindex中,那如何生成和使用不同的索引呢?以下是我的解決方案,下面先貼兩個(gè)bash腳本的代碼:
-
_cindex,在任意目錄下執(zhí)行_cindex則會(huì)index當(dāng)前目錄下的所有代碼
#! /usr/bin/env bash
CSEARCH_WORKSPACE=~/.codesearch_cache
if [[ ! -d "$CSEARCH_WORKSPACE" ]];then
mkdir -p "$CSEARCH_WROKSPACE"
fi
CURRENT_DIR="${PWD//\//_}";
export CSEARCHINDEX="$CSEARCH_WORKSPACE/$CURRENT_DIR.csearchindex";
cindex $PWD;
_csearch,會(huì)根據(jù)當(dāng)前執(zhí)行命令的目錄來(lái)判斷需要使用的索引
#! /usr/bin/env bash
CSEARCH_WORKSPACE=~/.codesearch_cache;
CURRENT_DIR="${PWD//\//_}";
export CSEARCHINDEX="$CSEARCH_WORKSPACE/$CURRENT_DIR.csearchindex";
if [[ -f "$CSEARCHINDEX" ]];then
pattern='('
pattern+='no such file or directory' # cindex在代碼更新后重新index的話,增量更新索引但是不會(huì)刪除失效的記錄,所以這里通過(guò)grep -v來(lái)過(guò)濾一下結(jié)果
pattern+=')'
csearch -n "$@" |& grep -i -v "$pattern"
else
echo "please do _cindex first"
fi
- zoekt Google工程師出品的另一個(gè)代碼搜索工具,支持web交互,但是目前最大的問(wèn)題是創(chuàng)建index的速度太慢,有待觀察。
更強(qiáng)大的工具
上個(gè)小結(jié)提到的多個(gè)工具只能做基于文本的搜索,然而對(duì)于代碼而言,要是能夠基于這些語(yǔ)言的關(guān)鍵字進(jìn)行更多處理那就更好了,幸運(yùn)的是我們有了下面的工具。
各種IDE,例如idea,IDE不僅能夠支持關(guān)鍵字,而且能夠在詞法和語(yǔ)法層面進(jìn)行處理,因而對(duì)于代碼的定位更加準(zhǔn)確,很多時(shí)候?qū)S玫腎DE是最好的代碼閱讀工具,但就我個(gè)人的經(jīng)驗(yàn)而言,IDE對(duì)于涉及多種編程語(yǔ)言的混合項(xiàng)目的支持就不太好。
vim+cscope+gnuglobal+ctags,這種方式相較第一種工具而言對(duì)語(yǔ)言的支持就比較粗糙,更多的是只停留在關(guān)鍵字的程度,另外就是學(xué)習(xí)門檻比較高,甚至需要修改一些vim的插件來(lái)滿足自己的需求,這方面涉及的東西和知識(shí)面比較多,不方便細(xì)講,下面就提一個(gè)我自己的dotfiles,里面有些我在配置過(guò)程中遇到的問(wèn)題和解決方案。
補(bǔ)充說(shuō)明
這里我要推薦一本書(shū),也就是code reading,也是讀完這本書(shū)使我有了寫(xiě)關(guān)于代碼閱讀文章的想法。
google-tags,前google工程師的Piaw Na參與編寫(xiě)的源碼索引工具的開(kāi)源版本,他在他的一篇博客中提到了這個(gè)工具,該開(kāi)源版本已經(jīng)很長(zhǎng)時(shí)間沒(méi)有維護(hù),這里提一下以備后用。