<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      代碼的藝術(shù)-Writing Code Like a Pianist

      前言

      如何評定一個系統(tǒng)的質(zhì)量?什么樣的系統(tǒng)或者軟件可以稱之為高質(zhì)量?可以從三個角度來看,一是架構(gòu)設(shè)計,例如技術(shù)選型、分布式系統(tǒng)中的數(shù)據(jù)一致性考慮等,二是項目管理,無論是敏捷開發(fā)還是瀑布式開發(fā),都應(yīng)當(dāng)對技術(shù)負(fù)債進(jìn)行清理,對代碼進(jìn)行重構(gòu)等,最后離不開的是代碼質(zhì)量,代碼質(zhì)量的高低直接影響系統(tǒng)的可維護(hù)性和可擴(kuò)展性。好比一輛汽車,內(nèi)飾高級,外觀漂亮,但是底盤不行,動力孱弱,也難以稱得上是一輛好車。本文將從主觀和客觀的角度,和大家探討一下,作為程序員,應(yīng)該如何寫出整潔高質(zhì)量的代碼。

      主觀角度

      工程師精神

      點(diǎn)開京ME頭像可以看到,咱們內(nèi)部的title是“xx開發(fā)工程師”,而不是“xx代碼編寫員”,這個師可以理解為大師的師(master),大師級程序員把系統(tǒng)當(dāng)作故事來講,而不是當(dāng)作程序來寫。作為開發(fā)者,應(yīng)該對自己寫下的代碼負(fù)責(zé),當(dāng)在一個類上@author冠名的時候,應(yīng)當(dāng)有一種成就感,在未來的某一天,可能一年,兩年甚至五年之后,其他同事讀到這段代碼,會由衷的發(fā)出感嘆“牛B”,而不是吐槽“寫的什么玩意”,Doug Lea寫的并發(fā)包,時隔多年,他的大名依然如雷貫耳。

      提高代碼可讀性

      首先應(yīng)當(dāng)達(dá)成共識的是,代碼是寫給人看的,給機(jī)器運(yùn)行那只是基礎(chǔ),優(yōu)秀的代碼,不需要過多的注釋,代碼本身就是注釋。可讀性指的是,其他開發(fā)人員能夠迅速理解代碼的意圖和功能,簡潔的代碼更易于理解、測試和維護(hù)。其次,避免重復(fù),代碼重復(fù)是軟件中一切邪惡的根源,許多原則和設(shè)計模式都是為了消除重復(fù)而創(chuàng)建。

      客觀角度

      接下來從客觀角度,例舉日常代碼評審中的常見問題,給大家作一些參考。

      try/catch使用

      1. try/catch塊應(yīng)該盡量的小,只針對無法預(yù)料的情況進(jìn)行try/catch,可以預(yù)見的異常情況應(yīng)該在try之前被校驗住。

      無法預(yù)料的情況:遠(yuǎn)程調(diào)用,IO讀寫,第三方API等。 可以預(yù)見的情況:某個參數(shù)為空,某個列表無元素等。

       

       

       

      try/catch塊小有什么好處?

      ?代碼整潔,可以減少其他代碼的縮進(jìn)
      ?異常控制精細(xì),可以對具體異常進(jìn)行具體的提示、UMP報警、日志輸出或者錯誤碼返回

       

      2. 如果確實(shí)需要對整段方法進(jìn)行tryCatch,不如新寫一個方法,將業(yè)務(wù)邏輯處理和異常處理區(qū)分開來。

      例如:

       

       

       

       

      try/catch代碼塊中的內(nèi)容多,說明對代碼掌控能力不夠好 如果存在try,那么盡量保證try在第一行,并且在catch/finally后不該有其他內(nèi)容

      方法長度

      方法行數(shù)應(yīng)該盡可能的短,越短越好。能夠讓讀者點(diǎn)進(jìn)來的一瞬間就明白這個方法做了什么事情。舉個例子:

       

       

       

      這是一個查詢價格的方法,這個方法長度截圖已經(jīng)一頁截不下了。如果要想搞明白這個方法做了什么事,憑借方法體中的注釋是沒法輕易梳理清楚。

      只需要做簡單的一些處理的包裝,這個方法就能變得通俗易懂,而且并不用寫一行注釋。

      簡單重構(gòu)后:

       

       

       

       

       

       

       

       

       

      從上面的代碼上看,第一段將價格查詢的代碼分成了兩個部分,首先解析查詢的審批狀態(tài),然后根據(jù)審批狀態(tài)分別查詢價格。第二段將價格查詢分成了兩個部分,一個是查詢審批中的價格,另一個是查詢審批通過的價格,最后將二者組合起來返回。第三段是截了審批中價格查詢的代碼,顯而易見地,查詢審批中價格有兩種模式,百分比模式和底價模式,查詢到結(jié)果后,組合返回即得到商品的渠道價。

      對比一下不難看出,原代碼塊篇幅過長,嵌套較深(for循環(huán)嵌套if再嵌套if),導(dǎo)致可讀性下降。如果我想改動某塊的代碼,都需要深思熟慮。但是在拆分之后,就可以快速定位到目標(biāo)代碼塊,并且不用擔(dān)心對其他方法產(chǎn)生影響,另外,對其進(jìn)行單元測試也會比較方便編寫測試用例。

      禁止在方法內(nèi)部修改入?yún)?shù)據(jù)

      從系統(tǒng)概念上來看,一般可以將系統(tǒng)分為兩類,一類是給一個輸入,得到一個輸出,這類稱之為響應(yīng)式,另一類是給一個輸入,但是沒有輸出,這類被認(rèn)為是命令式。同理,對于方法而言,響應(yīng)式方法即給定一個入?yún)?,得到一個出參,比較常見的比如模型轉(zhuǎn)換、數(shù)據(jù)查詢等,命令式方法有發(fā)送消息、run一個線程。

      但是無論怎么變化,這些都有一個共同點(diǎn),他們不會去修改入?yún)⒌臄?shù)據(jù)。

      1. 引起意外的副作用:如果方法修改了傳入的參數(shù),而調(diào)用者依賴于原始的參數(shù)值,那么調(diào)用者可能會在不知情的情況下受到影響。這可能導(dǎo)致程序的行為變得難以預(yù)測,增加代碼的復(fù)雜性和錯誤的可能性。
      2.破壞數(shù)據(jù)的一致性:如果多個方法共享同一個對象作為參數(shù),并且這些方法都可以修改該對象,這些方法可能會相互干擾,導(dǎo)致數(shù)據(jù)狀態(tài)變得混亂和不可預(yù)測。
      3.可能增加代碼的維護(hù)難度:當(dāng)方法修改傳入的參數(shù)時,調(diào)用該方法的代碼可能需要依賴于這種修改行為。這樣會增加代碼的耦合性,使得代碼更難以理解、維護(hù)和重用。當(dāng)需要對方法進(jìn)行修改時,可能需要同時修改調(diào)用該方法的所有地方,增加了代碼的維護(hù)成本。

      舉個例子:

       

       

       

      這里調(diào)用了3個set方法,但是誰能一眼看出來,它把值set到哪個object里了?還得挨個點(diǎn)進(jìn)去看看具體實(shí)現(xiàn),才知道在哪里賦值了。

      如果確實(shí)需要修改參數(shù)的值,可以創(chuàng)建一個新的對象來存儲修改后的結(jié)果,并將其返回給調(diào)用者。這樣可以保持代碼的清晰性、可維護(hù)性和可測試性,減少意外的副作用和數(shù)據(jù)一致性問題。

      方法參數(shù)

      方法的參數(shù)也是越少越好,最理想的參數(shù)是無參,其次是單參,應(yīng)該盡量避免三個或者三個以上的參數(shù)

      繼續(xù)上面的代碼,最后一行“設(shè)置渠道類型”,set方法里有兩個入?yún)?,完全可以將其賦值對象提取出來,減少一個入?yún)?,如下?/p>

       

       

       

       

      如果方法的處理邏輯,只依賴于某一局部變量object的數(shù)據(jù),那么完全可以將這個方法放在對象內(nèi)部,進(jìn)一步減少方法參數(shù),提高代碼復(fù)用性,例如:

       

       

       

      這樣來看,就成功將兩個入?yún)⒌姆椒?,縮減成了無參方法,和原始代碼相比,原始代碼方法的作用域僅限于類內(nèi)部,而最終的無參方法,只需要拿到目標(biāo)對象實(shí)例即可在任何地方調(diào)用,還能減少重復(fù)代碼的編寫。

      減少縮進(jìn)

      代碼中出現(xiàn)大量的縮進(jìn)顯然是影響閱讀的,在可能的情況下,我們應(yīng)該盡可能的減少代碼中的縮進(jìn)和層次。好的代碼讀起來應(yīng)該是和報紙一樣,排版整齊優(yōu)雅,而不是爬樓梯。

      來看看下面的代碼:

       

       

       

      代碼中出現(xiàn)兩層if嵌套,首先我們可以對第一層if嵌套做一個簡化,簡單將if的判斷條件做一個反轉(zhuǎn)得到下面代碼:

       

       

       

      這樣就減少了一層縮進(jìn),然后再將變量和參數(shù)進(jìn)行一些微調(diào):

       

       

       

      這樣,和之前的代碼比起來,是不是可讀性提高了?

      單一職責(zé)

      在面向?qū)ο缶幊讨校?單一職責(zé)原則"(Single Responsibility Principle,SRP)是指一個類或模塊應(yīng)該只有一個引起它變化的原因,即一個類或模塊應(yīng)該只有一個主要責(zé)任或目標(biāo)。通過細(xì)化功能和職責(zé),可以提高代碼的可維護(hù)性、復(fù)用性和可擴(kuò)展性。

      看下面的代碼:

       

       

       

      這個方法是從聲明上來看,是用于保存任務(wù)數(shù)據(jù),但是實(shí)際上如果入?yún)⒅械哪承?shù)據(jù)不為空(實(shí)際上看這個方法的實(shí)現(xiàn)也很難一眼看出來具體是哪些數(shù)據(jù)),會進(jìn)行更新update操作。這種寫法不僅容易讓讀者感到困惑,也會降低代碼的可擴(kuò)展性。

       

      Q:AtomicInteger的compareAndSet方法違反了單一職責(zé)嗎? A:并不違反單一職責(zé)原則。compareAndSet 方法是 AtomicInteger 類提供的一種原子操作,用于比較當(dāng)前值與給定期望值是否相等,如果相等則將當(dāng)前值設(shè)置為新值。這個方法的職責(zé)是實(shí)現(xiàn)原子性的比較和設(shè)置操作,確保在多線程環(huán)境下的線程安全性。compareAndSet 方法作為其中的一種操作,是為了滿足特定的需求而設(shè)計的,它并不違反單一職責(zé)原則。單一職責(zé)原則要求一個類或模塊只有一個主要責(zé)任,而 AtomicInteger 類的主要責(zé)任是提供原子整數(shù)操作,compareAndSet 方法是其中的一部分,屬于該類主要責(zé)任的一部分。因此,compareAndSet 方法并不違反單一職責(zé)原則。

       

      使用意義明確的命名

      下面的代碼,checkParam的返回值是布爾值,但是作為讀者,我不知道是應(yīng)該check通過了返回True,還是check失敗的情況下返回True。

       

       

       

       

      一般而言,check作為開頭的方法名稱,沒有返回值,對于check不通過的情況以異常的形式拋出。返回布爾值的方法通常以is作為起始,換種寫法看看是不是會好讀很多?

       

       

       

      使用有意義的命名

      這里比較典型的是flow編排文件里的條件判斷節(jié)點(diǎn),使用0,1這類沒有意義的數(shù)字,很難一眼看出來說了什么,需要挨個點(diǎn)進(jìn)去看邏輯,才能梳理明白,改成有意義的命名,便于理解。

       

       

       

       

      類、方法命名規(guī)則

      類名使用名詞或者名詞短語 方法命名使用動詞或者動名詞結(jié)構(gòu)

      這個比較好理解,暫不舉例了。

      不要留無關(guān)內(nèi)容

      在發(fā)起MR之前,檢查一遍代碼里有沒有“被注釋掉的代碼”以及TODO。

      對于注釋掉的代碼而言,如果后續(xù)有其他開發(fā)人員介入,他們會覺得非常困惑,這兩行代碼為什么要注釋掉?它們重要嗎?它們放在那里,是因為在未來的某一天需要用?還是說只是當(dāng)時忘記刪除了?還是說為了給未來修改做提示?這些顧慮可能讓其他開發(fā)人員也不敢動手清理這些被注釋的代碼,進(jìn)而造成這些代碼被永久的保留下來,形成“幽靈代碼”。

      對于TODO來說,建議在寫todo的時候,要求在后面跟上自己的ERP,誰來解決,怎么解決,deadLine是什么時候。因為在大多數(shù)情況下,Later equals never。久而久之,連自己都忘了這個todo,忘了當(dāng)時為啥寫這個todo,應(yīng)該怎么處理,給系統(tǒng)埋下隱患。

       

       

       

      如上,當(dāng)年寫下這個TODO的同事已經(jīng)離職了,現(xiàn)在只有上帝才知道todo什么東西。

      枚舉

      養(yǎng)成良好的習(xí)慣,在用枚舉定義的變量,拉一條引用指向枚舉,方便其他開發(fā)人員閱讀。

      例如:

       

       

       

      這是一個可窮舉的變量(因為狀態(tài)是有限的),但是讀者不知道具體都有哪些狀態(tài)。這里其實(shí)是有一個枚舉關(guān)聯(lián)上來的.

       

       

       

      為了方便閱讀,可以在變量定義的地方,使用javaDoc的@see/@link方式,說明這個變量的枚舉范圍。

       

       

       

      單元測試

      單測的重要性不言而喻,這里先挖個坑,后續(xù)單開一篇寫。

      結(jié)語

      寫在最后,給大家推薦一本經(jīng)典書籍《代碼整潔之道》,實(shí)際上該書的出版時間較早,書中的某些知識或許有些過時,但是前面幾章內(nèi)容仍然值得一讀。整潔的代碼需要團(tuán)隊的共同努力,團(tuán)隊成員應(yīng)該遵循一致的編碼風(fēng)格和標(biāo)準(zhǔn),進(jìn)行代碼審查和知識分享,共同維護(hù)和改進(jìn)代碼質(zhì)量。它不僅僅是一種編碼風(fēng)格,更是一種思維方式和價值觀。優(yōu)雅的代碼,就像是藝術(shù)品,正如標(biāo)題所言,應(yīng)當(dāng)像一名鋼琴家一樣編寫代碼。

       

      作者:京東零售 譚磊

      來源:京東云開發(fā)者社區(qū) 轉(zhuǎn)載請注明來源

      posted @ 2024-01-22 11:43  京東云技術(shù)團(tuán)隊  閱讀(50)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲综合一区国产精品| 亚洲av永久无码天堂影院| 日韩精品中文字幕一线不卡| 国产萌白酱喷水视频在线观看| 精品在免费线中文字幕久久| 国产精品一区二区久久精品| 九九热在线观看视频免费| 少妇性l交大片| 中文字幕有码无码人妻在线| 玩弄放荡人妻少妇系列| 女人18片毛片60分钟| 久久天天躁夜夜躁狠狠躁2022| 亚洲精品动漫一区二区三| 欧美xxxxhd高清| 伊人春色激情综合激情网| 亚洲第一精品一二三区| 精品国产粉嫩内射白浆内射双马尾| 无码综合天天久久综合网| 九九热视频在线观看精品| 少妇人妻偷人精品免费视频| 国产久爱免费精品视频| 亚洲一区二区三级av| 国产一区二区日韩在线| 任我爽精品视频在线播放| 色综合一本到久久亚洲91| 亚洲日韩AV秘 无码一区二区| 亚洲国产日韩一区三区| 国产女人看国产在线女人| 欧美日韩视频综合一区无弹窗| 国产熟睡乱子伦视频在线播放| 美日韩av一区二区三区| 色8久久人人97超碰香蕉987 | 鹿泉市| 在线精品另类自拍视频| 香港日本三级亚洲三级| 桓台县| av无码小缝喷白浆在线观看| 日本熟妇hdsex视频| 成人av午夜在线观看| 不卡免费一区二区日韩av| 久久综合色之久久综合|