1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        內(nèi)卷時代,更應(yīng)提升代碼質(zhì)量!

        共 4637字,需瀏覽 10分鐘

         ·

        2020-12-28 07:50

        △點擊上方Python貓”關(guān)注 ,回復(fù)“1”領(lǐng)取電子書

        作者:Zachary
        來源:跨界架構(gòu)師
        提到代碼質(zhì)量,不知道你的腦海中浮現(xiàn)出的第一個詞是什么?規(guī)范?可讀性?優(yōu)雅?

        在我的心中,好的代碼質(zhì)量 = 舒服??粗娣邮诌@樣的項目感覺舒服,在其中找問題和改代碼舒服。


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

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


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

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

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


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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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


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

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

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


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

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

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

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


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

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


        /02? 寫單元測試/

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

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

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


        /03? 設(shè)計先行/

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

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


        /04? 項目與團隊”微服務(wù)化”/

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


        /05? 利用相關(guān)的工具/

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


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

        01? 勿過度使用鏈?zhǔn)骄幊?/span>

        很多人會追求極致少的代碼行數(shù),恰好鏈?zhǔn)骄幊棠芡镀渌谩5拇_在很多時候鏈?zhǔn)骄幊炭梢蕴岣叽a的可讀性,但是它帶來的弊端也是顯而易見的,

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

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


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


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

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

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

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


        03? 認(rèn)真編寫訪問修飾符

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

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

        訪問修飾符的過于寬松也是前面提到的鏈?zhǔn)骄幊瘫贿^度使用的推手之一。

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


        04? 慎用繼承

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

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

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


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


        好了,總結(jié)一下。

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

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

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

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

        2. 寫單元測試

        3. 設(shè)計先行

        4. 項目與團隊”微服務(wù)化”

        5. 利用相關(guān)的工具


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

        1. 勿過度使用鏈?zhǔn)骄幊?/span>

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

        3. 認(rèn)真編寫訪問修飾符

        4. 慎用繼承


        希望對你有所啟發(fā)。
        Python貓技術(shù)交流群開放啦!群里既有國內(nèi)一二線大廠在職員工,也有國內(nèi)外高校在讀學(xué)生,既有十多年碼齡的編程老鳥,也有中小學(xué)剛剛?cè)腴T的新人,學(xué)習(xí)氛圍良好!想入群的同學(xué),請在公號內(nèi)回復(fù)『交流群』,獲取貓哥的微信(謝絕廣告黨,非誠勿擾?。?/span>~

        近期熱門文章推薦:

        揭開Python對象的神秘面紗!
        動態(tài)規(guī)劃:特朗普怎樣才能贏?
        趣漫畫:Java 對 Python 的滲透能成功嗎?
        當(dāng)我發(fā)現(xiàn)國際友人翻譯了我的文章之后……

        感謝創(chuàng)作者的好文
        瀏覽 17
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

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

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日本人xxxxxxxxx69 | 国语少妇新婚之夜对白性视频 | 日韩三级图片 | 豆花视频成人版www满18 | 在线观看黄A片免费无码视频 | 日韩mv欧美mv国产精品 | 色偷偷偷偷无码 | 免费人成多视频 | 干日本少妇视频 | a视频免费 |