|
這兩天,在微博上表達(dá)了一下Code Review的重要性。因?yàn)榉戳税⒗飪?nèi)部的Review Board上的記錄,從上面發(fā)現(xiàn)Code Review做得好的是一些比較偏技術(shù)的團(tuán)隊(duì),而偏業(yè)務(wù)的技術(shù)團(tuán)隊(duì)基本上沒有看到Code Review的記錄。當(dāng)然,這并不能說(shuō)沒有記錄他們就沒有做Code Review,于是,我就問了一下以前在業(yè)務(wù)團(tuán)隊(duì)做過(guò)的同事有沒有Code Review,他告訴我不但沒有Code Review,而且他認(rèn)為Code Review沒用,因?yàn)椋?/span>
1)工期壓得太緊,時(shí)間連coding都不夠,以上線為目的。
2)需求老變,代碼的生命周期太短。所以,寫好的代碼沒有任何意義,爛就爛吧,反正與績(jī)效無(wú)關(guān)。
我心里非常不認(rèn)同這樣的觀點(diǎn),我覺得我是程序員,我是工程師,就像醫(yī)生一樣,不是把病人醫(yī)好就好了,還要對(duì)病人的長(zhǎng)期健康負(fù)責(zé)。對(duì)于常見病,要很快地醫(yī)好病人很簡(jiǎn)單,下猛藥,大量使用抗生素,好得飛快。但大家都知道,這明顯是“飲鴆止渴”、“竭澤而漁”的做法。醫(yī)生需要有責(zé)任心和醫(yī)德,我也覺得程序員工程師也要有相應(yīng)的責(zé)任心和相應(yīng)的修養(yǎng)。東西交給我我必需要負(fù)責(zé),我覺得這種負(fù)責(zé)和修養(yǎng)不是”做出來(lái)“就了事了,而是要到“做漂亮”這個(gè)級(jí)別,這就是“山寨”和“工業(yè)”的差別。而只以“做出來(lái)”為目的標(biāo)準(zhǔn),我只能以為,這樣的做法只不過(guò)是“按部就班”的堆砌代碼罷了,和勞動(dòng)密集型的“裝配生產(chǎn)線”和“砌磚頭”沒有什么差別,在這種環(huán)境里呆著還不如離開。
老實(shí)說(shuō),因?yàn)槿ツ晡以跇I(yè)務(wù)團(tuán)隊(duì)的時(shí)候,我的團(tuán)隊(duì)也沒有做Code Review,原因是多樣的。其中一個(gè)重要原因是,我剛來(lái)阿里,所以,需要做的是在適應(yīng)阿里的文化,任何公司都有自己的風(fēng)格和特點(diǎn),任何公司的做法都有他的理由和成因,對(duì)于我這樣的一個(gè)初來(lái)者,首要的是要適應(yīng)和觀察,不要對(duì)團(tuán)隊(duì)做太多的改動(dòng),跟從、理解和信任是融入的關(guān)鍵。(注:在建北京團(tuán)隊(duì)和不要專職的測(cè)試人員上我都受到了一些阻力),所以跟著團(tuán)隊(duì)走沒有玩Code Review。干了一年后,覺得我妥協(xié)了很多我以前所堅(jiān)持的東西,覺得自己的標(biāo)準(zhǔn)在降低,想一想后背拔涼拔涼的,所以我決定堅(jiān)持,而且還要堅(jiān)持高標(biāo)準(zhǔn)。
對(duì)于Code Review很重要的這個(gè)觀點(diǎn),在微博上拋出來(lái)后,被一些阿里的工程師,架構(gòu)師/專家,甚至資深架構(gòu)師批評(píng),我在和他們回復(fù)和討論的過(guò)程中,居然發(fā)現(xiàn)有個(gè)“因?yàn)閷?duì)方用戶的設(shè)置”我無(wú)法回復(fù)了(我被拉黑了,還有一些直接就是冷諷和罵人了,微博中我就直接刪除了)。這些批評(píng)我的阿里工程師/架構(gòu)師的觀點(diǎn)總結(jié)一下如下:(順便說(shuō)一下,阿里內(nèi)還是有很多團(tuán)隊(duì)堅(jiān)持做Code Review的)
1)到業(yè)務(wù)團(tuán)隊(duì)體會(huì)一下,倒逼工期的項(xiàng)目有多少?訂好交付日期后再要求提前1個(gè)月的有多少?現(xiàn)在是做到已經(jīng)不容易,更不談做得漂亮!。
2)Code Review是一種教條,意義不大,有測(cè)試,只要不出錯(cuò),就可以了。
3)目標(biāo)都是改進(jìn)質(zhì)量,有限的投入總希望能有最大的產(chǎn)出,不同沉湎改進(jìn)質(zhì)量的方式不一樣,業(yè)務(wù)應(yīng)用開發(fā)忙的跟狗一樣,而且業(yè)務(wù)邏輯變化快,通用性差,Code Review的成本要比底層高。
4)現(xiàn)在的主要矛盾是倒排出來(lái)的工期和不靠譜的程序員之間的矛盾,我認(rèn)為Code Review不是解決這個(gè)問題的銀彈。不從實(shí)際情況出發(fā)光打正義的嘴炮實(shí)在太過(guò)于自慰了 。
我們可以看到,上面觀點(diǎn)其實(shí)和Code Review沒有太多關(guān)系,其實(shí)是在抱怨另外的問題。這些觀點(diǎn)其實(shí)是技術(shù)團(tuán)隊(duì)和業(yè)務(wù)團(tuán)隊(duì)的矛盾,但不知道為什么強(qiáng)加給了我的“Code Review很重要”的這個(gè)觀點(diǎn),然后這些觀點(diǎn)反過(guò)來(lái)沖擊“Code Reivew”,并說(shuō)“Code Review無(wú)用”。這種討論問題的方式在很常見,你說(shuō)A,我說(shuō)B,本來(lái)A、B是兩件事,但就是要混為一談,然后似是而非的用B來(lái)證明你的A觀點(diǎn)是錯(cuò)的。(也許,這些工程師/架構(gòu)師心存怨氣,需要一個(gè)發(fā)泄的通道)
我覺得,很多時(shí)候,人思考問題思考不清楚,很大一部分原因是因?yàn)榘押芏鄦栴}混為一談,連我自己有些時(shí)候都會(huì)這樣。引以為戒。
即然被混為一談,那我就來(lái)拆分一下,也是下面這三個(gè)問題:
- Code Review有沒有用的問題。
- Code Review做不起來(lái)的問題。
- 業(yè)務(wù)變化快,速度快的問題,技術(shù)疲于跟命。
Code Review
你Google一下Code Reivew這個(gè)關(guān)鍵詞,你就會(huì)發(fā)現(xiàn)Code Review的好處基本上是不存在爭(zhēng)議的,有很多很多的文章和博文都在說(shuō)Code Review的重要性,怎么做會(huì)更好,而且很多公司在面試過(guò)程中會(huì)加入“Code Review”的問題。打開Wikipedia的詞條你會(huì)看到這樣的描述——
卡珀斯·瓊斯(Capers Jones)分析了超過(guò)12,000個(gè)軟件開發(fā)項(xiàng)目,其中使用正式代碼審查的項(xiàng)目,發(fā)現(xiàn)潛在缺陷率約在60-65%之間,若是非正式的代碼審查,發(fā)現(xiàn)潛在缺陷率不到50%。大部份的測(cè)試,發(fā)現(xiàn)的潛在缺陷率會(huì)在30%左右。
對(duì)于一些關(guān)鍵的軟件(例如安全關(guān)鍵系統(tǒng)的嵌入式軟件),一般的代碼審查速度約是一小時(shí)150行程序碼,一小時(shí)審查數(shù)百行程序碼的審查速度太快,可能無(wú)法找到程序中的問題。代碼審查一般可以找到及移除約65%的錯(cuò)誤,最高可以到85%。
也有研究針對(duì)代碼審查找到的缺陷類型進(jìn)行分析。代碼審查找到的缺陷中,有75%是和計(jì)算機(jī)安全隱患有關(guān)。對(duì)于產(chǎn)品生命周期很長(zhǎng)的軟件公司而言,代碼審查是很有效的工具。
Code Review的好處我覺得不用多說(shuō)了,主要是讓你的代碼可以更好的組織起來(lái),更易讀,有更高的維護(hù)性,同時(shí)可以達(dá)到知識(shí)共享,找到bug只是其中的副產(chǎn)品。這個(gè)東西已經(jīng)不新鮮了,你上網(wǎng)可以找到很多文章,我就不多說(shuō)了。就像你寫程序要判斷錯(cuò)誤一樣,Code Review也是最基本的常識(shí)性的東西。
我從2002年開始就浸泡在嚴(yán)格的Code Review中,我的個(gè)人成長(zhǎng)和Code Review有很大的關(guān)系,如果我的成長(zhǎng)過(guò)程中沒有經(jīng)歷過(guò)Code Review這個(gè)事,我完全不敢想像。
我個(gè)人認(rèn)為代碼有這幾種級(jí)別:1)可編譯,2)可運(yùn)行,3)可測(cè)試,4)可讀,5)可維護(hù),6)可重用。通過(guò)自動(dòng)化測(cè)試的代碼只能達(dá)到第3)級(jí),而通過(guò)Code Review的代碼少會(huì)在第4)級(jí)甚至更高。關(guān)于Code Review,你可以參看本站的《Code Review中的幾個(gè)提示》
可見,Code Review直接關(guān)系到了你的工程能力!
Code Review 的問題
有下面幾個(gè)情況會(huì)讓你的Code Review沒有效果。
首當(dāng)其沖的是——“人員能力不足”,我經(jīng)歷過(guò)這樣的情況,Code Review的過(guò)程中,大家大眼瞪小眼,沒有什么好的想法,不知道什么是好的代碼,什么是不好的代碼。導(dǎo)致Code Review大多數(shù)都在代碼風(fēng)格上。今天,我告訴你,代碼風(fēng)格這種事,是每個(gè)程序員自查的事情,不應(yīng)該浪費(fèi)大家的時(shí)間。對(duì)此,我有兩個(gè)建議:1)你團(tuán)隊(duì)的人招錯(cuò)了,該換血了。2)讓你團(tuán)隊(duì)的人花時(shí)候閱讀一下《代碼大全》這本書(當(dāng)然,還要讀很多基礎(chǔ)知識(shí)的書)。
次當(dāng)其沖的是——“結(jié)果更重要”,也就是說(shuō),做出來(lái)更重要,做漂亮不重要。因?yàn)槲业腒PI和年終獎(jiǎng)based on how many works I’ve done!而不是How perfect they are ! 這讓我想到那些天天在用Spring MVC做CRUD網(wǎng)頁(yè)的工程師,我承認(rèn),他們很熟練。大量的重復(fù)勞動(dòng)。其實(shí),仔細(xì)想一下好多東西是可以框架化,模板化,或是自動(dòng)生成的。所以,為了堆出這么多網(wǎng)頁(yè)就不停地去堆,做的東西是很多,但是沒有任何成長(zhǎng)。急功近利,也許,你做得多,拿到了不錯(cuò)的年終獎(jiǎng),但是你失去的也多,失去了成為一個(gè)卓越工程師的機(jī)會(huì)。你本來(lái)可以讓你的月薪在1-2年后翻1-2倍的,但一年后你只拿到了為數(shù)不多的年終獎(jiǎng)。
然后是——“人員的態(tài)度問題”,一方面就是懶,不想精益求精,只要干完活交差了事。對(duì)此,你更要大力開展Code Review了,讓這種人寫出來(lái)的代碼曝光在更多人面前,讓他為質(zhì)量不好的代碼蒙羞。另一方面,有人會(huì)覺得那是別人的模塊,我不懂,也沒時(shí)間去懂,不懂他的業(yè)務(wù)怎么做Code Review? 我只想說(shuō),如果你的團(tuán)隊(duì)里這樣的“各個(gè)自掃門前雪”的事越多,那么這個(gè)團(tuán)隊(duì)也就越?jīng)]主動(dòng)性,沒有主動(dòng)性也就越不可能是個(gè)好團(tuán)隊(duì),做的東西也不可能好。而對(duì)于個(gè)人來(lái)說(shuō),也就越不可能有成長(zhǎng)。
接下來(lái)是——“需求變化的問題”,有人認(rèn)識(shí),需求變得快,代碼的生存周期比較短,不需要好的代碼,反正過(guò)兩天這些代碼就會(huì)被廢棄了。如果是一次性的東西,的確質(zhì)量不需要太高,反正用了就扔。但是,我覺得多多少少要Review一下這個(gè)一次性的爛代碼不會(huì)影響那些長(zhǎng)期在用的代碼吧,如果你的項(xiàng)目全部都是臨時(shí)代碼,那么你團(tuán)隊(duì)是不是也是一個(gè)臨時(shí)團(tuán)隊(duì)?關(guān)于如果應(yīng)對(duì)需求變化,你可以看看本站的《需求變化與IoC》《Unix的設(shè)計(jì)思想來(lái)應(yīng)對(duì)多變的需求》的文章 ,從這些文章中,我相信你可以看到對(duì)于需求變化的代碼質(zhì)量需要的更高。
最后是——“時(shí)間不夠問題”,如果是業(yè)務(wù)逼得緊,讓你疲于奔命,那么這不是Code Review好不好問題,這是需求管理和項(xiàng)目管理的問題以及別的非技術(shù)的問題。下面我會(huì)說(shuō)。
不管怎么樣,上述Code Review的問題不應(yīng)該成為“Code Review無(wú)意義”的理由或借口,這就好像“因噎廢食”一樣。干什么事都會(huì)有困難和問題的,有的人就這樣退縮了,但有的人看得到利大于弊,還是去堅(jiān)持,人與人的不同正在這個(gè)地方。這就是為什么運(yùn)動(dòng)會(huì)受傷,但還是會(huì)人去運(yùn)動(dòng),而有人因?yàn)榕率軅屯丝s了一樣。
被業(yè)務(wù)逼得太緊
被業(yè)務(wù)逼得太緊,需求亂變,這其實(shí)和Code Review沒有多大關(guān)系了。對(duì)此,我想先講一個(gè)我的故事。
我去年在阿里的聚石塔,剛?cè)サ臅r(shí)候,聚石塔正在做一個(gè)很大的重構(gòu)——對(duì)架構(gòu)的大調(diào)整。因此壓了很多業(yè)務(wù)需求,等這個(gè)項(xiàng)目花了2-3個(gè)月做完了后,一下子涌入了30-50個(gè)需求,還規(guī)定一個(gè)月完成,搞得團(tuán)隊(duì)疲于奔命。在累了兩周后,我仔細(xì)分析了一下這些需求,發(fā)現(xiàn)很多需求是在重復(fù)做阿里云已經(jīng)做過(guò)的東西,還有一些需求是因?yàn)榫凼@個(gè)平臺(tái)不規(guī)范沒有標(biāo)準(zhǔn)所產(chǎn)生的問題。于是,我做了這么三件事:
1)重新定義聚石塔這個(gè)產(chǎn)品主要目標(biāo)和范圍,確定哪些該做,哪些不該做。
2)為聚石塔制定標(biāo)準(zhǔn) ,讓阿里云的API都長(zhǎng)得基本一樣,并制訂云資源的接入標(biāo)準(zhǔn)。
3)推動(dòng)重構(gòu)阿里云的Portal系統(tǒng),不再實(shí)現(xiàn)阿里云已經(jīng)做過(guò)的東西,與阿里云緊密結(jié)合。
這些事情推動(dòng)起來(lái)并不容易,聚石塔的業(yè)務(wù)方一開始也不理解,我和產(chǎn)品一起做業(yè)務(wù)方的工作,而阿里云也被我逼得很慘(在這里一并感謝,尤其阿里云的同學(xué),老實(shí)說(shuō),和阿里云跨團(tuán)隊(duì)合作中是我這么多年來(lái)感覺最好的一次,相當(dāng)贊)。通過(guò)這個(gè)事,聚石塔需求一下就有質(zhì)的下降了。搞得還有幾個(gè)工程師來(lái)和我說(shuō),你這么搞,聚石塔就沒事可干了。姑且不說(shuō)工程師對(duì)聚石塔的理解是怎么樣的。 我只想說(shuō),我大量地減少了需求,盡最大可能聯(lián)合了該聯(lián)合的人,而不是自己閉門造車,并讓產(chǎn)品的目標(biāo)和方向更明確了。做了這些事情后,大家不但不用加班,而且還有時(shí)間充電去學(xué)技術(shù),并為聚石塔思考未來(lái)的方向和發(fā)展。去年公司996的時(shí)候,我的團(tuán)隊(duì)還在965(搞得跟異教徒似的),而且還有很多時(shí)間去專研新的東西。
說(shuō)這個(gè)故事,我不是為了得瑟,而是因?yàn)橛行┤嗽谖⒉┥吓険粑沂且粋€(gè)道貌岸然的只會(huì)談概念講道理的裝逼犯。所以,我告訴大家我在聚石塔是怎么做的,我公開寫在這里,你也可以向相關(guān)的同學(xué)去求證我說(shuō)的是不是真的。也向你證明,我可能是個(gè)裝逼犯,但絕不是只會(huì)談概念講道理的裝逼犯。
被業(yè)務(wù)方逼得緊不要抱怨,你沒有時(shí)間被逼得像牲口一樣工作,這個(gè)時(shí)候,你需要的是暫停一下想一想,為什么會(huì)像牲口一樣?而這正是讓你變得聰明的機(jī)會(huì)。
我為你總結(jié)一下,
1)你有沒有去Review業(yè)務(wù)部門給你的這么多的需求,哪些是合理的,哪些是不合理的。在Amazon,開發(fā)工程師都會(huì)被教育拿到需求后一定要問——“為什么要做?業(yè)務(wù)影響度有多大?有多少用戶受益?”,回答不清這個(gè)問題,沒有數(shù)據(jù)的支持,就不做。所以,產(chǎn)品經(jīng)理要做很多數(shù)據(jù)挖拙和用戶調(diào)研的工作,而不是拍拍腦袋,聽極少數(shù)的用戶抱怨就要開需求了。
2)產(chǎn)品經(jīng)理也要管理和教育的。你要告訴你的產(chǎn)品經(jīng)理:“你是一個(gè)好的產(chǎn)品經(jīng)理,因?yàn)槟悴坏珜?duì)用戶把握得很好,也會(huì)對(duì)軟件工藝把握得很好。你不但會(huì)開出外在的功能性需求,也同樣會(huì)開出內(nèi)在的讓軟件系統(tǒng)更完善的非功能性需求。你不是在遷就用戶,而是引導(dǎo)用戶。你不會(huì)無(wú)限制地加功能,而是把握產(chǎn)品靈魂控制并簡(jiǎn)化功能。你會(huì)為自己要做的和不做東西的感到同樣的自豪。”你要告訴你的產(chǎn)品經(jīng)理:“做一個(gè)半成品不如做好半年產(chǎn)品”(更多這樣的觀點(diǎn)請(qǐng)參看《Rework摘錄和感想》)
3)做事情是要講效率的。Amazon里喜歡使用一種叫T-Shirt Size Estimation的評(píng)估方法來(lái)優(yōu)先做投入小產(chǎn)出大的“Happy Case”。關(guān)于什么是效率,什么是T-Shirt Size Estimation,你可以看看《加班與效率》一文 。
4)需求總是會(huì)變化的,不要抱怨需求變化太快。你應(yīng)該抱怨的是為什么我們沒有把握好方向?老變?這個(gè)事就像踢足球一樣,你要去的地方是球?qū)⒁サ牡胤剑皇乔颥F(xiàn)在的地方。你要知道球要去哪里,你就知道球之前是怎么動(dòng)的,找到了運(yùn)動(dòng)軌跡后,你才知道球要去像何方。如果你都不知道球要去向何方,那你就是一只無(wú)頭蒼蠅一樣,東一下西一下。
當(dāng)你忙得跟牲口一樣,你應(yīng)該停下來(lái),問一下自己,自己成為牲口的原因,是不是就是因?yàn)樽约鹤鍪聲r(shí)候像就牲口一樣思考?
其它
最后,我在給阿里今年新入職的畢業(yè)生的“技塑人生”的分享中,我給他們布置了5、6個(gè)Homework,分享幾個(gè)給大家:
1)重構(gòu)或?qū)懸粋€(gè)模塊,把他做成真正的Elegant級(jí)別。
2)與大家分享一篇或幾篇技術(shù)文章 ,并收獲10-30個(gè)贊。
3)降低現(xiàn)有至少20%的重復(fù)工作或維護(hù)工作
4)拒絕或簡(jiǎn)化一個(gè)需求(需要項(xiàng)目中所有的Stakeholders都同意)
部署這些作業(yè)的原因,是我希望新入行的同學(xué)們對(duì)自己的工作堅(jiān)持高的標(biāo)準(zhǔn),我知道你們會(huì)因?yàn)楣歉械默F(xiàn)實(shí)而妥協(xié),但是我希望你們就算在現(xiàn)實(shí)中妥協(xié)了也要在內(nèi)心中堅(jiān)持盡可能高的標(biāo)準(zhǔn),不要習(xí)慣成自然,最后被社會(huì)這個(gè)大染缸給潛移默化了。因?yàn)槟阒辽僖獙?duì)自己負(fù)責(zé)。對(duì)自己負(fù)責(zé)就是,用腳投票,如果妥協(xié)得受不了了就離開吧。
芝蘭生于空谷,不以無(wú)人而不芳!君子修身養(yǎng)道,不以窮困而改志!
謝謝聽我嘮叨。
it知識(shí)庫(kù):從Code Review談如何做技術(shù),轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。