《制定代碼規(guī)范并不難,但你知道如何讓它可執(zhí)行嗎?》要點(diǎn):
本文介紹了制定代碼規(guī)范并不難,但你知道如何讓它可執(zhí)行嗎?,希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
策劃:erichua23
編輯:郭蕾
回想起來(lái)自己工作這么些年,也經(jīng)歷了不少團(tuán)隊(duì),經(jīng)歷的項(xiàng)目更不算少了, 但是要說(shuō)到代碼規(guī)范, 問(wèn)我我經(jīng)歷的這些代碼規(guī)范是不是滿(mǎn)意,我不得不如實(shí)回答:不是很滿(mǎn)意.當(dāng)然我自己的代碼規(guī)范和風(fēng)格也沒(méi)有完全固化下來(lái),近一年左右也開(kāi)始關(guān)注到這個(gè)問(wèn)題,為了讓自己的代碼風(fēng)格能逐漸固化,我會(huì)專(zhuān)門(mén)用一個(gè)筆記來(lái)記錄一些可能自己會(huì)糾結(jié)的寫(xiě)法,這樣做了以后明顯能感覺(jué)到自己代碼風(fēng)格的飄忽程度有所收斂.恰巧公司負(fù)責(zé)的項(xiàng)目也需要整理代碼規(guī)范,正因如此我開(kāi)始思考 如何制定可執(zhí)行的代碼規(guī)范 這個(gè)問(wèn)題.
提到團(tuán)隊(duì)的代碼規(guī)范,不止我經(jīng)歷過(guò)的,我和一些朋友也有聊過(guò), 有微軟那個(gè)級(jí)別的,也有 BAT 這種級(jí)別的,項(xiàng)目大的也有,小的亦很多.其中不乏規(guī)范的做的比較好的,有規(guī)范、有工具、還會(huì)有 Code Review 來(lái)保證.但是大公司規(guī)范和流程真的適合所有團(tuán)隊(duì)嗎?我所看到的是大部分團(tuán)隊(duì)參照某某公司的規(guī)范和流程,定義了一個(gè)非常嚴(yán)格的標(biāo)準(zhǔn),然而實(shí)際上并沒(méi)有嚴(yán)格實(shí)施下去或者沒(méi)有持續(xù)實(shí)施下去.最后都會(huì)甩鍋給“歷史包袱太重”、“開(kāi)發(fā)人員太多太雜難以推廣”這樣的理由.
近半年到一年在代碼規(guī)范這一塊我主要思考如何在中小團(tuán)隊(duì)沒(méi)有代碼規(guī)范的基礎(chǔ)上制定代碼規(guī)范.根據(jù)自己的思考也正在組內(nèi)逐步實(shí)踐,從目前實(shí)踐情況來(lái)看我是比較滿(mǎn)意的,所以把自己觀點(diǎn)寫(xiě)出來(lái),希望能對(duì)跟我有同樣困惑的人有些幫助.
所有的規(guī)范,包括但不限于代碼規(guī)范,都會(huì)包含規(guī)范制定、規(guī)范推廣執(zhí)行、規(guī)范修正的過(guò)程. 其中規(guī)范的推廣和執(zhí)行通常是最難的(這就是為什么有很多流程文檔,但是流程還是非常混亂的原因),而制定了什么樣的規(guī)范直接決定了推廣執(zhí)行的難度,所以我們先從代碼規(guī)范的制定說(shuō)起.
大部分團(tuán)隊(duì)?wèi)?yīng)該都是有 KPI 的,而且一般重要的事情都會(huì)被定成 KPI, 所以有些團(tuán)隊(duì)為了強(qiáng)調(diào)代碼規(guī)范, 將其定為某些員工的 KPI,這樣重視代碼規(guī)范行為我是非常欣賞的,但是我不認(rèn)同,因?yàn)槲艺J(rèn)為 代碼規(guī)范不應(yīng)該是一個(gè)文檔, 代碼規(guī)范應(yīng)該是一種行為, 一種持續(xù)的行為,而 KPI 是要求可以量化有明確目標(biāo)的.若把代碼規(guī)范當(dāng)作 KPI, 背了 KPI 的員工為了讓 KPI 可量化, 通常情況會(huì)寫(xiě)出來(lái)一個(gè)代碼規(guī)范文檔,眾所周知文檔最可 量化的當(dāng)然是頁(yè)數(shù),故最終可能會(huì)產(chǎn)出一個(gè)幾十頁(yè)的代碼規(guī)范,它可能是結(jié)合了 Google、Facebook、Tencent 等等大公司的代碼規(guī)范,幾乎面面俱到,看起來(lái)就很高大上.
代碼規(guī)范文檔出來(lái)了,KPI 看起來(lái)也完成得不錯(cuò),那然后呢?如果我們把代碼規(guī)范理解為一種行為,那這文檔就僅僅只是一個(gè)行為準(zhǔn)則,它就像是一部法律,要求大家都要如何做,所以接下來(lái)更重點(diǎn)的工作應(yīng)該是去讓這些文檔落地,讓大家理解認(rèn)可執(zhí)行它.并且還需要有相應(yīng)的監(jiān)督機(jī)制、審查機(jī)制來(lái)保證大家確實(shí)按規(guī)范在寫(xiě)代碼.但是后面這些,也就是整個(gè)代碼規(guī)范實(shí)施最難的點(diǎn),要量化又極其不易.能如何量化呢?量化推廣程度?量化大家對(duì)各條代碼規(guī)范的理解透徹程度?難道用考試來(lái)量化嗎?這就是把代碼規(guī)范設(shè)定成 KPI 的尷尬, 為了讓 KPI 看起來(lái)豐滿(mǎn), 產(chǎn)出了一個(gè)豐滿(mǎn)的規(guī)范, 而對(duì)于整個(gè)過(guò)程中最難的落地執(zhí)行環(huán)節(jié), 豐滿(mǎn)的規(guī)范為其增加了阻力.
以前我對(duì)于代碼規(guī)范的理解是也是越豐富越好,但是在近半年推廣代碼規(guī)范的過(guò)程中我開(kāi)始青睞簡(jiǎn)單一些的代碼規(guī)范,因?yàn)槲蚁嘈糯蟛糠秩藭?huì)贊同:一個(gè)被 100% 徹底執(zhí)行了的 40 分代碼規(guī)范應(yīng)該是好于一個(gè)被執(zhí)行了 40% 的 100 分代碼規(guī)范.
這個(gè)觀點(diǎn)可能會(huì)更比較多人的看法不太一樣, 因?yàn)楹芏嗳硕颊J(rèn)為規(guī)范應(yīng)該前期就定下來(lái),而且盡可能面面俱到,否則后面定規(guī)范容易背上歷史包袱.前期就應(yīng)該定規(guī)范的這個(gè)觀點(diǎn)我比較認(rèn)同,首先我們拋開(kāi)你們團(tuán)隊(duì)已經(jīng)有非常完善代碼規(guī)范這種情況,因?yàn)槿绻悄菢?你只需要按原有規(guī)范執(zhí)行即可.
這里主要討論新項(xiàng)目沒(méi)有規(guī)范的情況下怎么做,我們可以復(fù)盤(pán)一下新項(xiàng)目開(kāi)始階段,通常情況新項(xiàng)目需求節(jié)奏都會(huì)非常快,基礎(chǔ)框架、基礎(chǔ)組件、大批量業(yè)務(wù)需求要開(kāi)發(fā),又因?yàn)槭切马?xiàng)目,通常不會(huì)有特別多的人力投入,這種情況下,一個(gè)很?chē)?yán)格冗長(zhǎng)的代碼規(guī)范,要求大家在拼命跑的過(guò)程中還要去理解執(zhí)行你的規(guī)范,可能性大嗎?所以這個(gè)時(shí)期的代碼規(guī)范需要非常簡(jiǎn)單易于理解,要在所有人即使在趕需求,也能忍受的范圍內(nèi)制定規(guī)范.這個(gè)階段最急迫的需求是用簡(jiǎn)單的代碼規(guī)范讓大家養(yǎng)成習(xí)慣,提升意識(shí),宣告這個(gè)項(xiàng)目是有規(guī)范的.
我們拿前端項(xiàng)目來(lái)舉例,首先應(yīng)該先保證 JS 代碼風(fēng)格是對(duì)的,其次可能根據(jù)技術(shù)選型不同(例如 Angular,React),要遵循另外一批 Best Practice.按上述思路,我會(huì)在前期只要求大家 JS 代碼格式規(guī)范就行了.因?yàn)榘迅鞣N Best Practice 一股腦的全丟進(jìn)去容易繞暈大家. 如果你真的舍不得那些 Best Practice,我建議將其列為建議級(jí)別的,先不做必須,必須的條目盡可能精簡(jiǎn).
上面一段提到代碼規(guī)范應(yīng)該循序漸進(jìn),但是簡(jiǎn)單的規(guī)范從何而來(lái)呢?之前看到過(guò)的一種做法是:團(tuán)隊(duì)內(nèi)大家一起討論,民主決定某一些規(guī)范的細(xì)節(jié),因?yàn)檫@樣可以出來(lái)一個(gè)適配這個(gè)團(tuán)隊(duì)的代碼規(guī)范.
這聽(tīng)起來(lái)很美好,非常民主,大家很平等,但是回想一下以前這么做的結(jié)果是什么?我猜應(yīng)該會(huì)有很多人又回憶起“大括號(hào)應(yīng)不應(yīng)該換行”、“else 是否應(yīng)該換行”、“是否允許空兩行”、“JS 結(jié)尾帶不帶分號(hào)”等等類(lèi)似的爭(zhēng)論吧,然而這些爭(zhēng)論是有必要的嗎?說(shuō)白了,大部分爭(zhēng)論找的理由都只是在為自己的代碼習(xí)慣爭(zhēng)取更多空間.這樣的爭(zhēng)論還只是“民主”引發(fā)問(wèn)題的開(kāi)始,更嚴(yán)重的是這會(huì)在所有開(kāi)發(fā)人員心中形成一種“規(guī)范是可以商量和討論的”心理暗示,這必對(duì)后續(xù)規(guī)范的執(zhí)行成為阻礙,特別是一些本身就有爭(zhēng)議的點(diǎn),總會(huì)有人伺機(jī)反撲.
另外,“民主”的規(guī)范其實(shí)很難做到讓所有人心理上平衡,例如可能會(huì)讓 B 開(kāi)發(fā)覺(jué)得自己在遵從 A 開(kāi)發(fā)的習(xí)慣,即使這種感覺(jué)可能不是那么強(qiáng)烈,它也會(huì)變成規(guī)范執(zhí)行的阻力.
正因?yàn)樯鲜鲈?我非常建議制定規(guī)范時(shí)“獨(dú)裁”.我們的目標(biāo)很清晰,就是要求代碼寫(xiě)法一致,“獨(dú)裁”的基礎(chǔ)上可以選擇一個(gè)第三方的標(biāo)準(zhǔn),例如細(xì)的條目可以完全選擇 Google 或者 Facebook 或者其他一些大公司的標(biāo)準(zhǔn)(當(dāng)然可能還需要考慮我上面提到的循序漸進(jìn),做裁剪,但是規(guī)則細(xì)則不要再去討論和挑戰(zhàn)).首先可以保證的是這些規(guī)范不會(huì)有太大的問(wèn)題,跟著做不會(huì)犯大錯(cuò);其次,“獨(dú)裁”使用的規(guī)范來(lái)源于第三方,對(duì)團(tuán)隊(duì)內(nèi)所有人公平;最后,這樣的規(guī)范和行業(yè)更親近.
我在我們的前端項(xiàng)目里面就選擇了 StandardJS 的規(guī)范,StandardJS 的出現(xiàn)初衷也正是為了解決上述“民主”引發(fā)的問(wèn)題.除此之外,還有一個(gè)好處是這些第三方規(guī)范的成熟不只是規(guī)范本身,它的配套工具會(huì)成熟很多,可以節(jié)省自己很多成本.
上面我們已經(jīng)討論了如何建立代碼規(guī)范,主要強(qiáng)調(diào)了 代碼規(guī)范不應(yīng)只是一紙空文、代碼規(guī)范要循序漸進(jìn)、代碼規(guī)范的制定需要“獨(dú)裁”.這些都屬于“立法”過(guò)程,接下來(lái)要討論的必然是“執(zhí)法”,代碼規(guī)范的“執(zhí)法”主要需要關(guān)注兩點(diǎn),一點(diǎn)是“違法”行為的判定,另一點(diǎn)是“違法”行為的責(zé)任追究,也就是代碼規(guī)則檢查以及發(fā)現(xiàn)不符合規(guī)范的代碼應(yīng)該由誰(shuí)來(lái)負(fù)責(zé).
代碼規(guī)則檢查通常直接使用現(xiàn)有成熟工具就好,例如前端開(kāi)發(fā)常用的 ESLint,現(xiàn)在各種語(yǔ)言都有各自比較成熟的工具,我這里想強(qiáng)調(diào)的是幾個(gè)檢查代碼的時(shí)機(jī),一是寫(xiě)代碼的時(shí)候,這是源頭,配置一個(gè)好的 IDE 檢查規(guī)則能從源頭避免不規(guī)范的代碼.二是提交時(shí)候,通常是設(shè)置 git/svn 的 hooks(PS: git 的 hooks 在 2.9.0 之前相當(dāng)?shù)碾y用,如果你用的版本低于 2.9.0,可以考慮升級(jí)并配置代碼檢查的鉤子).三是 CI 的時(shí)候,這是最后一關(guān),可以保證合流以后的代碼不出現(xiàn)規(guī)范的問(wèn)題.只要在上面三個(gè)點(diǎn)嚴(yán)格執(zhí)行了,不規(guī)范的代碼幾乎已經(jīng)無(wú)處可藏.
“違法”行為判定盡可能通過(guò)工具來(lái)判定,那如果出現(xiàn)了庫(kù)里面提交了不合規(guī)則的代碼應(yīng)該由誰(shuí)去改呢?如果有 CI,那只需要增加提交構(gòu)建,即可在 push 后的第一時(shí)間揪出違規(guī)者.如果沒(méi)有 CI,我建議是先建立 CI,如果實(shí)在沒(méi)有,那可以考慮最后提交代碼負(fù)責(zé)制,最后提交代碼的人可以去找這份代碼是 merge 了誰(shuí)的,追溯到上游把“鍋”丟出去,最終找到違規(guī)者并要求改進(jìn)(不限于代碼的改進(jìn),更重要的是各種代碼檢查環(huán)境的配置).這樣的定義可以讓所有開(kāi)發(fā)知道遇到問(wèn)題以后該如何走下一步,我認(rèn)為是非常有必要的.
說(shuō)到這里我猜必然有讀者想到了 Code Review,實(shí)際上 Code Review 不應(yīng)該是去關(guān)注代碼風(fēng)格的,所有到 Code Review 環(huán)節(jié)的代碼必然是要過(guò)了代碼風(fēng)格檢查的,Code Review 主要關(guān)注的是代碼結(jié)構(gòu)設(shè)計(jì)和代碼邏輯,它是在代碼規(guī)范上一層的東西.如果你的團(tuán)隊(duì)在使用 Code Review 來(lái)保證代碼規(guī)范,那你們可能需要進(jìn)一步完善自己的代碼規(guī)范檢查工具.
代碼規(guī)范的好處大家都知道,但是任重道遠(yuǎn).真正去推行代碼規(guī)范的人,如果按我上面說(shuō)的幾點(diǎn)去做,可能會(huì)有各方面的壓力,特別是上面提到的“獨(dú)裁”和“執(zhí)法”兩點(diǎn),但是從我自己的實(shí)踐經(jīng)驗(yàn)來(lái)看,想象中的壓力小于實(shí)際,主要還是需要向同事們解釋清楚各種做法的理由,得到理解和支持.為了避免前期的推行的壓力過(guò)大,可以考慮裁剪規(guī)則(特別是在沒(méi)有很好代碼規(guī)范文化的團(tuán)隊(duì)內(nèi)),因?yàn)樘嵘龍F(tuán)隊(duì)人員意識(shí)和養(yǎng)成代碼規(guī)范的習(xí)慣應(yīng)該是最最首要的任務(wù),這兩點(diǎn)有了以后,再逐步的把要求提高,應(yīng)該會(huì)容易得多.這個(gè)過(guò)程有困難,但是我堅(jiān)定的認(rèn)為這是值得的.
文章來(lái)自微信公眾號(hào):聊聊架構(gòu)
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.fzlkiss.com/jiaocheng/2717.html