<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          代碼質量在「內(nèi)卷時代」的重要性

          共 4533字,需瀏覽 10分鐘

           ·

          2020-12-27 09:21

          這里是Z哥的個人公眾號

          每周五11:45 按時送達

          當然了,也會時不時加個餐~

          我的第「173」篇原創(chuàng)敬上



          大家好,我是Z哥。

          提到代碼質量,不知道你的腦海中浮現(xiàn)出的第一個詞是什么?規(guī)范?可讀性?優(yōu)雅?

          在我的心中,好的代碼質量 = 舒服。看著舒服,接手這樣的項目感覺舒服,在其中找問題和改代碼舒服。


          軟件開發(fā)這個行業(yè)是一個年輕的行業(yè),如果在十幾年前談代碼質量,可能還算是個比較高級的問題。但是在大家都認為越來越內(nèi)卷的當下,注重和提升代碼質量我認為是每個程序員的必修課。說的嚴重一些,它影響了你在團隊中的價值,說的表面一些,它是你在團隊中的“面子”。

          假象一下,你接手了兩個項目,一個項目代碼干干凈凈、非常整潔,另一個隨處可見的相似代碼以及雜亂無章的分類擺放。你對這兩個項目的前負責人是什么想法?未來你更愿意和誰合作?我想答案是顯而易見的。


          在我看來要寫出舒服的代碼并不需要對那些代碼規(guī)范背的滾瓜爛熟,其實只要掌握一個六字核心原則:高內(nèi)聚低耦合。如此寫出的代碼至少能在60分以上。

          可以回想一下,當你在做一個簡單項目的時候,使用那些成熟的框架和工具可以輕松地完成大部分工作。甚至會感覺有點無聊,因為感覺都是在CRUD。這就是應用了經(jīng)過精心設計的高內(nèi)聚低耦合的框架和工具所具有的效果,讓事情變簡單。

          講句題外話,「高內(nèi)聚低耦合」在軟件開發(fā)領域真是一個黃金原則,在哪都適用,大到一個分布式系統(tǒng)的設計,小到一個class的設計。如果我的腦子只能記住一條原則的話,毫不猶豫會選擇它。


          那么如何讓自己也能寫出高內(nèi)聚低耦合的代碼呢?我們要對「高內(nèi)聚低耦合」有更深入地理解,而不是僅僅停留在這6個字上。

          葡萄牙馬德拉大學精確科學與工程中心的教授,被認為是計算機領域先驅者之一的賴瑞·康斯坦丁帶隊對內(nèi)聚性和耦合性做了深入的研究和分析,對內(nèi)聚性和耦合性的強弱關系進行了梳理,得到了以下結論。(摘自于維基百科)

          內(nèi)聚性的分類如下,強度由低到高排列:

          偶然內(nèi)聚性:是指模塊中的機能只是剛好放在一起,模塊中各機能之間唯一的關系是其位在同一個模塊中(例如:“工具”模塊)。

          邏輯內(nèi)聚性:是只要機能只要在邏輯上分為同一類,不論各機能的本質是否有很大差異,就將這些機能放在同一模塊中(例如將所有的鼠標和鍵盤都放在輸入處理副程序中)。模塊內(nèi)執(zhí)行幾個邏輯上相似的功能,通過參數(shù)確定該模塊完成哪一個功能。

          時間性內(nèi)聚性:是指將相近時間點運行的程序,放在同一個模塊中(例如在捕捉到一個異常后調(diào)用一函數(shù),在函數(shù)中關閉已開啟的文件、產(chǎn)生錯誤日志、并告知用戶)。

          程序內(nèi)聚性:是指依一組會依照固定順序運行的程序放在同一個模塊中(例如一個函數(shù)檢查文件的權限,之后開啟文件)。

          聯(lián)系內(nèi)聚性/信息內(nèi)聚/通信內(nèi)聚:是指模塊中的機能因為處理相同的資料或者指各處理使用相同的輸入數(shù)據(jù)或者產(chǎn)生相同的輸出數(shù)據(jù),因此放在同一個模塊中(例如一個模塊中的許多機能都訪問同一個記錄)。

          依序內(nèi)聚性/順序內(nèi)聚:是指模塊中的各機能彼此的輸入及輸出資料相關,一模塊的輸出資料是另一個模塊的輸入,類似工廠的生產(chǎn)線(例如一個模塊先讀取文件中的資料,之后再處理資料)。

          功能內(nèi)聚性:是指模塊中的各機能是因為它們都對模塊中單一明確定義的任務有貢獻(例如XML字符串的詞法分析)。


          耦合性的分類如下,強度由高到低排列:

          內(nèi)容耦合:也稱為病態(tài)耦合當一個模塊直接使用另一個模塊的內(nèi)部數(shù)據(jù),或通過非正常入口而轉入另一個模塊內(nèi)部。

          共享耦合/公共耦合:也稱為全局耦合指通過一個公共數(shù)據(jù)環(huán)境相互作用的那些模塊間的耦合。公共耦合的復雜程度隨耦合模塊的個數(shù)增加而增加。

          外部耦合:發(fā)生在二個模塊共享一個外加的資料格式、通信協(xié)議或是設備界面,基本上和模塊和外部工具及設備的溝通有關。

          控制耦合:指一個模塊調(diào)用另一個模塊時,傳遞的是控制變量(如開關、標志等),被調(diào)模塊通過該控制變量的值有選擇地執(zhí)行塊內(nèi)某一功能;

          特征耦合/標記耦合:也稱為數(shù)據(jù)結構耦合,是指幾個模塊共享一個復雜的數(shù)據(jù)結構,如高級語言中的數(shù)組名、記錄名、文件名等這些名字即標記,其實傳遞的是這個數(shù)據(jù)結構的地址;

          資料耦合/數(shù)據(jù)耦合:是指模塊借由傳入值共享資料,每一個資料都是最基本的資料,而且只分享這些資料(例如傳遞一個整數(shù)給計算平方根的函數(shù))。

          消息耦合:可以借由以下二個方式達成:狀態(tài)的去中心化(例如在對象中),組件間利用傳入值或消息傳遞 (計算機科學)來通信。

          無耦合:模塊完全不和其他模塊交換信息。


          如果你代碼寫的還不夠多,上面有些差異還無法很好的感知。但是你不需要把這些概念一字一句背下來,只要平時在寫代碼的時候多思考一下:“當前的代碼設計是屬于哪種類型?”。如果不能確定的話回頭來看這篇文章:D。慢慢地,通過寫更多的代碼,你會對耦合和內(nèi)聚的強弱,有更敏感的感知力。

          根據(jù)上面的這些概念,寫出高質量代碼的思路就很清晰了。method的歸類、class的歸類能根據(jù)功能內(nèi)聚性歸類的絕不用順序內(nèi)聚,能根據(jù)順序內(nèi)聚性歸類的絕不用更弱的。耦合也是同樣的,能不耦合的就不耦合,能用消息耦合的絕不用數(shù)據(jù)耦合。

          但是想要保證代碼按照這個設想去發(fā)展,還是需要通過做一些具體的事情作為抓手。這些事不需要全部做,但每一項都有助于提高代碼質量。


          /01? 執(zhí)行代碼規(guī)范+Code Review/

          在Z哥看來,執(zhí)行代碼規(guī)范,最重要的價值并不是非得讓100%的代碼符合這個規(guī)范,而是讓所有人一起養(yǎng)成一種意識,意識到我的代碼會被別人看到,被評價。這樣才能在寫代碼的時候,不僅僅是為了實現(xiàn)功能。

          所以具體代碼規(guī)范是什么樣,并沒那么重要,可以是自己定義的,也可以是參考大廠的。當然我更推薦前者,大廠的規(guī)范雖好,但是你要全部照搬,這個執(zhí)行成本可不小。

          如果你想提高代碼質量,但又不想做很多事。那么執(zhí)行代碼規(guī)范+Code Review可以是你的唯一選擇。如果你是一位個人開發(fā)者,那么可以讓身邊你認為代碼寫的最好的人幫你做CodeReview,以他的規(guī)范作為代碼規(guī)范即可。


          很多人覺得代碼規(guī)范是一種約束,會降低開發(fā)效率。其實不會,最多在初期因為自己并不習慣一些規(guī)范,所以花了很多時間在修正代碼。一旦走上正軌后,代碼規(guī)范反而會提高開發(fā)效率,因為節(jié)省了很多閱讀代碼的時間以及同事之間溝通的時間。

          就算它真的降低了開發(fā)效率,但你要提升效率也不應該降低代碼質量,而是通過其它方式去提效。


          /02? 寫單元測試/

          寫單元測試之所以能提高代碼質量,是因為如果不是高內(nèi)聚低耦合的代碼,你會發(fā)現(xiàn)單元測試非常難寫。

          比如,你只想測一下方法A,但是發(fā)現(xiàn)里面的依賴錯綜復雜,好吧,都stub掉。最后發(fā)現(xiàn)測一個方法寫了幾十個stub,這種操作我親眼看到過……。這就是前面提到的「內(nèi)容耦合」過多了。

          所以,能輕松地寫出單元測試,并且將其養(yǎng)成一種習慣,你的代碼質量必然不會差。


          /03? 設計先行/

          雖然設計不出完美的代碼,但是優(yōu)先考慮設計可以讓你多思考“我應該怎么寫這段代碼”,而不是直接抄起家伙就寫,寫到哪算到哪。

          畢竟大多數(shù)功能都不可能一步到位,需要多次迭代。這種情況下最初的設計就顯得尤為重要,畢竟大部分人遇到不舒服的代碼不會推翻重寫,最多就是修修補補,甚至是直接在這之上疊加新的代碼。


          /04? 項目與團隊”微服務化”/

          保證一個幾萬行代碼的項目質量和幾百萬行代碼的項目必然難度不同。所以,如果合適的話可以將項目拆小,并且由專門的團隊負責。這樣可以提高團隊把控代碼質量意愿,并降低其難度。


          /05? 利用相關的工具/

          主流的編程語言或多或少都有一些靜態(tài)代碼分析工具、單元測試覆蓋率統(tǒng)計工具,這些要充分利用起來。它們可以快速的幫助避免一些低級的代碼壞味道,節(jié)約大量時間。


          /06? 幾個代碼層面的小建議/??

          01? 勿過度使用鏈式編程

          很多人會追求極致少的代碼行數(shù),恰好鏈式編程能投其所好。的確在很多時候鏈式編程可以提高代碼的可讀性,但是它帶來的弊端也是顯而易見的,

          1. 調(diào)試的時候觀察變量變得很不方便。

          2. 容易在當前方法里處理不應該在這里處理的業(yè)務邏輯。畢竟很多class的方法和屬性是public的,相比單獨做一層封裝再調(diào)用,“點”出來直接用多香啊~所以在使用鏈式編程的時候也得遵守「得墨忒耳定律」。


          得墨忒耳定律:
          每個單元對于其他的單元只能擁有有限的知識:只是與當前單元緊密聯(lián)系的單元;
          每個單元只能和它的朋友交談:不能和陌生單元交談;
          只和自己直接的朋友交談。
          維基百科


          02? 避免隨處可見的try-catch

          Try-catch雖好,切勿貪杯。很多人喜歡寫try-catch然后通過一個單獨封裝的通用返回模型告知調(diào)用方出現(xiàn)了什么異常。

          這種方法的目的最初是為了避免上層調(diào)用者沒有做異常捕獲導致程序崩潰,但是弊端也是顯而易見的,如果調(diào)用方?jīng)]有正確的判斷返回模型里的異常相關屬性,會導致程序在錯誤的狀態(tài)下繼續(xù)執(zhí)行,這個后果就不可預知了。

          所以我認為通過try-catch封裝異常應該出現(xiàn)在更上層的代碼里,越底層的代碼越不應該封裝異常。


          03? 認真編寫訪問修飾符

          很多編程語言都有多個訪問修飾符,我們在編寫的代碼的時候應該盡可能的選擇最嚴格的修飾符,而不是什么都是public。

          因為public會導致很多變量在不知道什么情況下就被外部修改了,導致bug層出不窮、排查困難,項目質量堪憂。

          訪問修飾符的過于寬松也是前面提到的鏈式編程被過度使用的推手之一。

          訪問修飾符的目的是為了防止程序員在無意間誤用不應該使用的方法和屬性,畢竟代碼往往不只有一個人寫。


          04? 慎用繼承

          繼承的確挺香的,可以少寫很多代碼。但是使用不當會破壞封裝的效果,造成訪問修飾符的失效。

          繼承的正確使用姿勢應該傳達的是“子父”的關系,而不是“相似”的關系。比如“汽車”可以繼承于“交通工具”,但是不應該繼承于“自行車”,雖然它們都有輪子。

          像汽車和自行車的這種情況要復用的話,可以抽象提煉出相同的部分,然后通過「組合」的方式進行。


          最后,如果你對代碼質量有更高的追求,想修煉和強化“內(nèi)功”,那必須不能錯過這本經(jīng)典書籍。(之前的黃皮版本更新成這本灰皮了)


          好了,總結一下。

          這篇呢,Z哥和你分享了我對代碼質量這件事的看法。在行業(yè)越來越內(nèi)卷的趨勢下,注重“質”總是沒錯的。

          Z哥認為想要提高代碼質量最核心的原則就是:高內(nèi)聚低耦合。文中給你羅列了賴瑞·康斯坦丁教授提煉了不同的內(nèi)聚性和耦合性原則來表達關系的強弱。

          基于對內(nèi)聚性和耦合性原則的理解,再通過以下抓手進行代碼質量的提升工作:

          1. 執(zhí)行代碼規(guī)范+Code Review

          2. 寫單元測試

          3. 設計先行

          4. 項目與團隊”微服務化”

          5. 利用相關的工具


          最后還分享了幾個代碼層面的建議:

          1. 勿過度使用鏈式編程

          2. 避免隨處可見的try-catch

          3. 認真編寫訪問修飾符

          4. 慎用繼承


          希望對你有所啟發(fā)。



          推薦閱讀:


          原創(chuàng)不易,如果你覺得這篇文章還不錯,就「在看」或者「分享」一下吧。鼓勵我的創(chuàng)作 :)


          如果你有關于軟件架構、分布式系統(tǒng)、產(chǎn)品、運營的困惑

          可以試試點擊「閱讀原文

          瀏覽 16
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日本A黄色 | 后射在线视频 | 国产高清一级a片免费看古女 | 天天淫天天色天天奸 | GoGo香蕉视频 |