[譯]Quora是如何維持高質量代碼的

原文連接:Moving Fast With High Code Quality
譯者:傑微刊—程慧 git

 

一個高質量的代碼庫能夠加快長期開發的速度,由於它會使得迭代、協做和維護更加容易。在Quora,咱們十分重視代碼庫的質量。 github

 

 

Quora,代碼,測試

 


除了會取得收益以外,要維護高質量的代碼,會帶來一大筆間接費用,還會犧牲實際開發週期。不少人發現,實際產生的收益很難抵消這一間接費用,這時人們會面臨兩個選擇:要麼以低質量代碼提高開發速度,要麼維護高質量代碼而犧牲開發速度。而對於初創公司來講,他們但願開發速度能快一些,因此就不得不使用低質量的代碼。 服務器


咱們開發了一系列工具和流程,這樣就能夠在維護高質量代碼庫的同時,提高開發的速度。在這篇文章中,咱們將會介紹關於保證代碼質量的一些方法,以及一些平衡這兩方面的具體案例。 架構


維護高質量代碼的目標 框架


維護高質量代碼主要的好處在於可以長期推進開發速度,這也是咱們所關注的重點。經過編寫清晰代碼而產生的短時間成本,就能夠換來長期的收益。 編輯器


記住這一點,而後下面是四點基本原則,咱們發現對代碼質量很是有幫助: 模塊化


Quara的代碼質量基本原則 工具


1. 代碼的閱讀和理解都要很容易——如今的狀況是更多的時間用在了代碼的閱讀上,而不是代碼的編寫上。實際上,應該把閱讀的時間減小,即使這樣意味着須要花費更多的時間來寫代碼。 性能


2. 代碼的不一樣部分須要有不一樣的質量標準——不一樣的代碼行須要有不一樣的使用時間、範圍、被破壞的風險、被破壞後形成的成本及其修復的成本,等等。整體來說,這些對長期迭代速度的影響不一樣,因此執行一個統一的質量標準是不合理的。 單元測試


3. 代碼質量的間接費用是能夠縮減的——維護高質量成本的間接費用通常是能夠節省的,這能夠經過使用自動化、更好的工具、更好的流程和培訓更優質的開發人員來實現。


4. 代碼庫一致性很重要——保持整個代碼庫的一致性是十分有價值的,即使這意味着有一部分代碼不能是最優的。一個不一致的代碼庫是很難閱讀和理解的(見第一點),也很難編寫,很難經過自動化工具進行優化。


下面,我來介紹幾個咱們將這幾點原則用於實際開發的例子。


提交後code review


咱們代碼庫的代碼變動須要從六個維度進行評估——正確性、隱私、性能、架構、複用性和風格。讀代碼是code review的關鍵部分,因此說,code review在提高代碼可讀性方面起着相當重要的做用。


Quora,代碼,測試

 


可是有一點很差的是,code review一樣會減緩開發速度。好比說,提交前code review在行業中目前是比較常見的,其中代碼必須在推送以前就進行審查和修改。這樣的話,即便是每一輪審查只須要2天的時間,這樣重複2-3輪,也會耽誤開發人員一週的時間,這是嚴重的時間浪費。


在Quora,咱們主要作的是提交後code review。也就是說,代碼首先進入生產階段,而後再找人進行code review。爲了讓你對這一工做的規模有個認識,舉個例子,昨天咱們48我的總共推送了187次代碼。提交後review是很好的辦法,由於它解放了開發人員,能夠去作其餘的工做。code review人員也能夠更好的管理本身的時間,能夠在他們方便的時候作代碼審查,而不是非得匆忙的完成這一工做,以便不影響其餘人的工做。過程合理的話,預計代碼審查一週內能夠完成,而實際上大部分狀況下,一到兩天就能夠完成。之因此說一週的時間,也是通過仔細考慮的,由於一週足夠長,能夠容許審查人員靈活安排,而一週的時間又有點短,由於它須要將很差結果的影響最小化,好比說有人讀了代碼以後將很差的代碼在整個代碼庫中進行傳播。實際還有這樣一層緣由,不少的開發人員都是按周進行我的工做安排的。


咱們之因此能夠作提交後code review,是由於咱們相信咱們的每一位開發人員,咱們選擇的都是最優秀的人才,而且咱們在他們的代碼質量培訓/工具方面投入了大量資金。這也督促咱們對代碼進行更好的測試,而好的測試能幫助檢測代碼的準確性,甚至在任何code review工做開始以前就能夠檢測。對此,咱們採用的是Phabricator,一個穩健的、高配置的審查工具。咱們對它作了幾點改進,這樣就能與咱們的提交後code review工做流更好的配合。好比說,咱們構建了一個命令行工具,能夠將代碼推向生產階段,並提出代碼審查請求。有了該工具,Phabricator的diff就能夠繼續工做,而無需去修復那些commits。


全部這些說明,對於不一樣類型的代碼問題,咱們有不一樣的代碼審查標準。若是說咱們事先發現了某一個潛在錯誤,問題比較大,可能會帶來很大影響,那麼咱們會轉而執行提交前審查,而不是日常的提交後審查。這方面的幾個例子:


1. 涉及用戶隱私和匿名的代碼。


2. 涉及核心的抽象類(abstraction),由於不少其餘的代碼均可能依賴於它。


3. 涉及基礎設施的某些部分,其有些錯誤可能會致使宕機的風險。


固然這還取決於開發人員如何決策——若是他們想要對某些代碼進行提交前審查,從而從中獲取更多想法,這也是能夠的,而不用非得采用日常的提交後code review,只不過這種狀況比較少見。


code review任務分派


爲了作好code review,每個變動都應該由有着相關經驗的人員來審查。若是這些code review人員能負責「維護」這些他們審查過的代碼的話那就更好了,這樣他們能夠得到必定物質報酬,進而造成長期的交易關係。


咱們以前實施了一個簡單的系統,其模塊和目錄層級代碼的「全部權」只須要在文件開頭賦予一個元標籤(meta tag)就能夠指定了。好比:


__reviewer__ = 'vanessa, kornel'


若是某commit要對文件作一些修改,其reviewer就會根據文件(或結構樹【ancestor tree】),進行分析,並自動做爲reviewer添加到commit中。咱們針對code review任務的分派或者說路由選擇還有一些其餘的規則,好比說,若是沒有reviewer的話,一個數據科學家可自動做爲一個reviewer添加到啓動A/B測試的commit中。實際上咱們已經搭建了一些工具,可讓咱們更容易的制定更多這類自定義的「路由」規則。舉個例子,若是咱們想作,那就很容易就能增長一個規則,能夠將某一個新任務全部的commits都路由指派給相應的人員。


這樣的一個智能系統,將全部的commits都分配給合適的人員進行代碼審查,能有效減輕開發人員的負擔,不然他們還須要四處尋找合適的審查人員,還要確保大部分的審查人員否能認真審查每條commit。


測試


測試對咱們的開發流程來講是很是重要的一步,咱們寫了不少的單元測試、功能測試和UI測試代碼,覆蓋很大的測試範圍。而一個綜合性測試可讓開發人員並行工做,工做進行的更快,而不用擔憂會破壞現有功能。咱們投入了大量時間來制定測試框架(創建在nosetests之上),使其容易使用、可快速應用,從而下降編寫測試代碼的間接費用。


咱們還開發了幾項工具,能夠實現測試的自動化。咱們以前發佈了一篇關於「持續集成系統」的文章,描述了一箇中心服務器,能夠在部署任何新代碼以前運行全部測試。該測試服務器能夠並行運行,這樣的話運行全部的測試只須要不到5分鐘的時間。這樣的快速運轉能夠激勵人們常常性的編寫和執行測試程序。咱們有一個叫作「test-local」的工具,只能識別和執行代碼工做副本的測試變動相關的測試文件。爲了能作的更好,咱們的測試還須要進行模塊化(這能進一步幫咱們在測試失敗的時候進行快速調試)。爲了確保好的測試代碼能獲得指望的性能,咱們維護了一個共享文檔,描述了編寫測試代碼相關的最佳實踐。這些指導方針在代碼審查過程當中會被嚴格執行。


Quora,代碼,測試


同code review同樣,咱們對不一樣類型的變動也有不一樣的測試標準,對測試範圍有更高的要求,尤爲是變動成本很高的狀況。


全部這些系統使得咱們可以從寫測試代碼的過程當中獲取最大收益,能夠以很小的間接費用節省不少的開發週期。


代碼質量指南


咱們很是熱衷於共享代碼質量標準的指南,它能夠幫咱們作不少事情:


① 做爲新開發人員培訓的很好的工具。


② 與整個團隊分享每一個人的智慧和最佳實踐。


③ 下降開發和代碼審查過程的間接費用。好比說,咱們討論一次就能夠得出一些有價值的結論的話,那麼再在每次code review時討論代碼行應該是80個字符串仍是100個字符串就徹底沒有意義了。


Quora,代碼,測試

 


除了針對不一樣語言的語法風格指南,咱們還有一些針對抽象事務的指導,好比如何寫一個好的測試用例,或者如何作出更好的模塊架構,從而提升工做效率。這些指南不是一成不變的,是隨着咱們對不一樣的過程有了更深的理解而不斷髮展的。咱們還有不少重構的工具(一些開源工具好比codemod,還有一些內部開發的工具),以備咱們改變指南的時候須要從新「修改」全部的歷史代碼。

舊代碼的清理


一個快速發展的團隊會嘗試不少不一樣的工具,固然其中不乏有一些能夠用而有一些不可用。到最後,任何一家快速發展的公司,隨着時間的推移其代碼庫都會開發不少多餘的東西,而這些可能永遠都不會再用,放在那裏只會使不少東西變得混亂。清理這些廢棄代碼可使得代碼庫更健康的運行,還能提高開發的速度。


Quora,代碼,測試

 


咱們會按期組織「清理周」,對這些多餘代碼進行清理。在清理周內,某一些團隊或者有時會發動整個公司專門來清理舊代碼。這種按期的清理模式能夠下降在「正常工做」和「清理工做」之間來回轉換的成本,還能使得清理工做更加社交化,更加有樂趣。


代碼庫有些部分會比其餘部分相對更好清理一些。一樣地,清理代碼庫的不一樣部分會對開發速度產生不一樣的影響。爲了能更好的利用好舊代碼清理的時間,咱們在考慮成本的基礎上優化了相關模塊,來進行清理工做,以及衡量清理工做對將來開發速度的影響。


Linting


咱們極可能會低估在某一實例中不遵循上述代碼質量指南(好比說docstring的格式或代碼行長度)所形成的成本,但事實上成本的確是增長了。同時,要記住各類各樣的規則並應用,也是一件很煩的事情,尤爲是規則還在不斷增長。最終形成的結果就是,不少人都選擇再也不遵循這些指導方針。


咱們開發了一個內部的linter,叫作qlint,能夠相應減輕一些上述困擾。qlint是一個很智能的linter,能夠讀懂文本結構以及AST,是基於flake8和pylint的。它旨在使得將來增長自定義的lint規則變得更容易。好比說,咱們其中一個作法是Python中任何一個「私有」變量都須要進行突出強調,因此咱們在qlint中新增了一個規則,那就是能夠檢測出這類私有變量中任何不合理的地方。


咱們還將qlint與不少系統集成起來,提供無縫的開發環境,這樣人們就沒必要親自盯着lint錯誤。對於新手來講,qlint是一個與咱們經常使用的文本編輯器——Vim,Emacs和Sublime——充分集成的工具,能夠在規則被破壞的狀況下提供可視的反饋(紅色標記)。它還與咱們的推送流程集成在了一塊兒,任何人在進行code推送的時候均可以運行qlint(以互動的方式)。而實際上,若是某項規則被commit打破,它有可能就會影響到部署工做。咱們還將咱們的風格指南與qlint集成起來,這樣對每個lint錯誤,qlint均可以給出一個超連接,指向相關風格指導的相應規則。咱們的Phabricator也能夠用qlint。經過這種方式,全部被qlint找到的錯誤都被明顯的標記出來,這樣他們的代碼審查工做就變得至關容易了。


Quora,代碼,測試


全部這些都幫咱們實現了以很小的成本就能提高代碼的一致性和質量。


結論


就像文章中所說的那樣, Quora對代碼的重視程度是很高的。咱們講求務實主義,搭建了不少好的系統、工具和流程,能幫咱們加強並維護長期開發的生產效率。今天咱們努力維持一個良好的平衡,咱們的團隊也在不斷成長和發展,因此咱們相信,將來咱們還將生產更多的工具和系統。


若是你想幫咱們搭建這樣的系統,或者想成爲咱們強大開發團隊的一份子,幫助咱們以這樣一種務實的、深入的方式提高代碼質量,那麼歡迎加入咱們

 

----------------------------------------------

相信愛閱讀的您,最近已經注意到了咱們。
咱們將陸續推出一系列關於業務設計和技術架構方面的好內容。


也歡迎您提出意見、推薦文章,爲讓別人更瞭解這個世界,做出本身的貢獻。

歡迎任何目的的聯繫。
個人郵箱:weikan@jointforce.com
個人QQ:3272840549。

 

原文連接:http://www.jointforce.com/jfperiodical/article/942?f=jf_tg_bky

相關文章
相關標籤/搜索