乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      如何寫出漂亮的代碼?寫代碼應(yīng)該遵守的原則和規(guī)范

       timtxu 2019-09-06

      這篇文章講述了代碼重構(gòu)的一些原則和措施,在自己寫代碼的過程中,應(yīng)該遵守這些原則,寫出漂亮的代碼。持續(xù)分享互聯(lián)網(wǎng)研發(fā)技術(shù)干貨,歡迎關(guān)注我。

      寫代碼的一些原則

      • 命名規(guī)范,含義明確。不同含義的變量和方法在詞語、大小寫、詞組上要有有效的區(qū)分。

      • Never repeat yourself。常量、方法塊、處理邏輯盡量少做重復(fù),可以抽象出共用代碼的最好抽象出來

      • 代碼塊職責(zé)單一,功能原子化。一段代碼、一個(gè)方法最好只做一件事情,可以是控制某個(gè)流程,組裝某個(gè)信息等,混在一起不利于后續(xù)的修改。

      • 開放擴(kuò)展,關(guān)閉修改。穩(wěn)定的東西盡量沉到下層,變化暴露到上層。這樣做的目的是后續(xù)維護(hù)代碼,盡量多添加,少修改。功能原子化也是為了達(dá)到這個(gè)目的,只有當(dāng)功能足夠小,耦合性足夠低的時(shí)候,在添加新功能的時(shí)候,才可以不去修改老的,而主要通過擴(kuò)展的方式增加業(yè)務(wù)

      • 高內(nèi)聚,低耦合。達(dá)到這個(gè)目的不簡單,一個(gè)基本思路就是盡量讓代碼處理的事情原子化,然后根據(jù)相關(guān)性的強(qiáng)弱選擇不同的聚合方式。以個(gè)人的體會來說,方法用來聚合同一個(gè)數(shù)據(jù)的操作,類用來聚合相關(guān)性比較強(qiáng)的一組數(shù)據(jù)或者操作,模塊用來聚合概念上有相似性的數(shù)據(jù)或者操作,層則用來聚合使用方式相同的數(shù)據(jù)或者操作。

      具體的措施

      以下是一些具體的措施:

      一、命名

      • 常量:所有字母大寫,不同單詞用下劃線隔開,如METHOD_TIME_THREAD;

      • 變量名和方法名:使用小駝峰式命名結(jié)構(gòu),第一個(gè)單詞字母小寫,后續(xù)單詞的第一個(gè)字母大寫,單詞直接拼接在一起,如outNo,orderId;

      • 接口名和類名:大駝峰式命名結(jié)構(gòu),所有單詞的第一個(gè)字母都大寫;

      • 數(shù)據(jù)庫字段、網(wǎng)絡(luò)請求字段:所有字母小寫,單詞之間用下劃線隔開,如out_no,order_id。

      二、常量

      • 對于固定的字符串、整數(shù),盡量使用常量,避免“魔法”字符串和整數(shù)(稱之為魔法的意思是,可能稍一不注意,東西取錯(cuò)了都不知道)

      • 常量是無狀態(tài)的,所以常量類和常量的命名上,最好別帶太強(qiáng)的業(yè)務(wù)信息,可以直接使用字面意思命名,否則當(dāng)別人使用該常量的時(shí)候,名字會很奇怪。

      • 常量類盡量集中存放,但不要分的太細(xì)。集中放是因?yàn)槌A克闶枪操Y源,理論上所有代碼都要共用,放的越集中就容易讓后續(xù)開發(fā)者發(fā)現(xiàn),不至于重新定義一模一樣的常量。不要分的太細(xì)也是為了讓后續(xù)開發(fā)者容易識別,如果每個(gè)業(yè)務(wù)都分一套常量,到時(shí)候常量類就會迅速膨脹,而且起不到常量的作用

      這里舉一個(gè)例子:

      HashMap<String,String> contentMap = new HashMap<String,String>();//放入一個(gè)數(shù)據(jù)的時(shí)候是這樣的:contentMap.put('orderId',orderId);// 取出數(shù)據(jù)的時(shí)候是這樣的:String orderId = contentMap.get('orderId');

      這里的“orderId”字符串就稱之為魔法字符串,其實(shí)很容易寫錯(cuò)。而且假如以后這個(gè)參數(shù)改個(gè)名字叫:movieOrderId,那這些字符串就得改很多處,而且不能通過搜索特定字符串一次性替換(因?yàn)楹芏嘧兞棵步衞rderId,而且并不見得所有的“orderId”都應(yīng)該改)。而如果使用常量來代表“orderId”字符串,就在key形成了一致性約束,以后改名字的時(shí)候,只需要改常量的內(nèi)容,put和get操作就自動(dòng)一致了。這是一個(gè)簡單的變量“高內(nèi)聚”

      三、刪掉未使用代碼

      • 當(dāng)前不用的代碼一定要?jiǎng)h掉,一是不整潔,二是影響后續(xù)rd的判斷,不是自己寫的刪也不合適,用也不合適。

      • 沒想好的代碼不要寫一半放在原地,應(yīng)該刪掉代碼,寫個(gè)todo提示

      四、代碼布局

      • 根據(jù)重要程度對變量、方法排個(gè)基本次序。人在閱讀理解的時(shí)候,會遵從類似金字塔的邏輯,所以要讓讀代碼的人先看到重要的,再看次要的。

      • 相關(guān)的代碼要集中在一起,不相關(guān)的代碼要用空行隔開,這樣便于快速瀏覽代碼的邏輯。

      • 變量順序:靜態(tài)常量、成員變量,所有變量按照重要性順序排列。這樣做是因?yàn)槿说拇竽X有首因效應(yīng),對最先看到的事物記憶最深刻。

      • 方法順序:構(gòu)造方法,靜態(tài)方法、私有成員方法、共有成員方法,也需要按照重要性順序排列,具體順序可以合理權(quán)衡。理論上,靜態(tài)方法,多為工具類型的方法,和當(dāng)前類有強(qiáng)綁定的關(guān)系,可以放在靠前的位置,如果沒有強(qiáng)綁定的關(guān)系,可以考慮抽離到外部類,避免和當(dāng)前類含糊不清。私有成員方法和共有成員方法需要根據(jù)方法的重要性確定其順序,比如提供重要服務(wù)的接口需要放最前,而get、set方法,肯定是要放最后。

      • 方法內(nèi)代碼根據(jù)功能分塊,例子(不同的功能要隔開,有關(guān)系的功能最好集中在一起,用序號標(biāo)識出流程)

      五、注釋

      • 重要的系統(tǒng)盡量多加,比如支付、訂單這種,改動(dòng)風(fēng)險(xiǎn)較高,能說明的最好是說明下。多寫注釋的原因主要在于代碼是英文為主,以中文為母語的人常常會將同一個(gè)單詞理解成不同的含義,比如voucher這種多義詞,既可以理解成單據(jù)、憑證,也可以理解為代金卷。特別是對于簡寫和隱形約定,很難做到每個(gè)人都理解,所以盡量多寫些注釋吧

      • 重要流程、算法邏輯、特殊判斷一定要加注釋,

      • 接口入?yún)?、返回值的限定,可能出現(xiàn)的各種情況最好用注釋說明

      六、日志

      • 日志要分類,最好一個(gè)業(yè)務(wù)一個(gè)日志,混在一起會難以統(tǒng)計(jì)和排查問題

      • 日志要分級,error,info,debug要分清。error日志就是要認(rèn)真對待的,出任何問題都要小心謹(jǐn)慎;info日志是打提示信息,比如請求參數(shù)、返回內(nèi)容、重要流程的節(jié)點(diǎn)信息等;

      • 日志的重點(diǎn)要清晰,一般模式是:先打印日志的目的(比如異常就說什么異常,提示就說什么參數(shù)的提示),然后接上重要的參數(shù)信息,參數(shù)可用你代碼中使用到的參數(shù),這樣看到日志后,可以更快速的對應(yīng)到具體的代碼上,方便排查問題。

      七、異常和中斷處理

      • 盡量統(tǒng)一處理異常和中斷,不要到處都是try-catch模塊或者if-else的判斷返回,一般是在業(yè)務(wù)接口上統(tǒng)一處理異常,下層邏輯在出現(xiàn)非預(yù)期的情況時(shí),盡量拋到上層來統(tǒng)一處理。這里提供一種參考的異常處理和代碼中斷模式。我們先可以繼承RuntimeException,實(shí)現(xiàn)一個(gè)自己的異常類TransException,由于RuntimeException是可以不捕獲的異常,所以當(dāng)TransException拋出來的時(shí)候,從下到上的方法都不需要throw,也不需要try-catch,這樣我們就可以在最上層catch住,統(tǒng)一處理異常。

      • 分析上面兩個(gè)類,異常類包括:錯(cuò)誤枚舉(包括錯(cuò)誤碼,錯(cuò)誤信息)、詳細(xì)的錯(cuò)誤信息。當(dāng)我們遇到可掌握的異常時(shí),可以構(gòu)造一個(gè)特定的TransException對象,將特定的錯(cuò)誤枚舉,具體的異常信息(比如具體的參數(shù)異常信息,錯(cuò)誤堆棧,可展示的下層業(yè)務(wù)異常信息等)填到詳細(xì)信息里邊,然后在任意地方throw,由上層統(tǒng)一打印錯(cuò)誤信息,組裝返回內(nèi)容,而不用一層一層的return false。

      • 出了未知異常,盡量掌控所有可以掌控的異常。達(dá)到這個(gè)目的主要有以下做法:1、操作數(shù)據(jù)前要檢查,有問題要細(xì)化錯(cuò)誤場景;2、try-catch異常盡量精細(xì),不要try-catch太多代碼。要么是一個(gè)流程,要么是一個(gè)數(shù)據(jù)操作,catch住異常要很清楚的知道這是什么類型的異常,將錯(cuò)誤場景細(xì)化

      八、模塊劃分

      模塊劃分的目的是為了“高內(nèi)聚”,把具有相同意義的代碼和數(shù)據(jù)放在一起,一是方便了閱讀和查找,二是可以將穩(wěn)定的代碼沉到下層,變化抽象到上層。下圖是我們之前商量過的代碼分層框架, 不一定要完全按照這種模式來,但可以有意的按照這種思路去把代碼分離開。

      如何寫出漂亮的代碼?寫代碼應(yīng)該遵守的原則和規(guī)范

      從下到上來說各層代表含義:

      • domain:主要是領(lǐng)域?qū)ο?,包括枚舉、常量、VO對象,服務(wù)之間傳遞信息所需要的model等等

      • dao:數(shù)據(jù)庫對應(yīng)的DO對象,DAO對象等,專門負(fù)責(zé)處理數(shù)據(jù)庫的東西

      • service:主要負(fù)責(zé)提供原子服務(wù),包含外部rpc服務(wù)的封裝,相對原子的數(shù)據(jù)處理過程,對dao層的操作等等

      • thrift service(server impl):thrift server 端,基于 basic service,實(shí)現(xiàn) thrift service,一般需要將 domain model 封裝為 thrift model。

      • thrift service(client repackage):thrift client 端,基于 thrift service,重新封裝一層 service,一般包含: thrift model 與 domain model 之間的轉(zhuǎn)換、Thrift Exception 異常轉(zhuǎn)換等。

      • biz:主要處理各種業(yè)務(wù)流程,組合service層的原子服務(wù)達(dá)到某個(gè)目的,處理某個(gè)業(yè)務(wù)

      • provider:不直面客戶端的也可以沒有這個(gè)模塊,主要負(fù)責(zé)接收外部請求,做權(quán)限管理(比如驗(yàn)證登陸)、參數(shù)校驗(yàn),然后調(diào)用biz層的接口完成做具體業(yè)務(wù)處理

      • task:用于處理定時(shí)任務(wù)、外部調(diào)度任務(wù)的模塊,負(fù)責(zé)接受任務(wù)消息或者調(diào)度請求,然后調(diào)用biz層的接口完成某件任務(wù)

      • common:主要是一些工具類(時(shí)間、MD5工具等等),以及一些對象轉(zhuǎn)換的conventor

      這樣分模塊的目的是為了減少代碼的耦合性,把相關(guān)的數(shù)據(jù)和代碼抽象的更集中,每當(dāng)你想用某個(gè)常量、枚舉、對象的時(shí)候,你大致掃一下domain就知道當(dāng)下有什么東西,不致于針對同一個(gè)東西寫好幾份代碼。而對于service來說,站在原子服務(wù)的角度來說,因?yàn)閟ervice足夠小,所以增加新業(yè)務(wù)時(shí),service是可以不修改的,而只需要添加服務(wù)就可以,biz層也只需要添加邏輯,組合service的服務(wù)就可以達(dá)到目的,這樣就達(dá)到了“開放擴(kuò)展,關(guān)閉修改”的目的,降低修改代碼帶來的風(fēng)險(xiǎn)。

      九、使用模型

      處理外部數(shù)據(jù)時(shí),盡量使用自己的業(yè)務(wù)模型,除非特別簡單的http回應(yīng),其它的處理都是應(yīng)該封裝自己的model的。

      為什么要把外部數(shù)據(jù)映射成model呢?

      • 原因一:讓看代碼的人,知道你當(dāng)下的業(yè)務(wù)在處理的過程中,到底和哪些參數(shù)相關(guān),他要重點(diǎn)關(guān)注哪些參數(shù)。如果沒有model,直接操作外部數(shù)據(jù),就會將這些知識散亂的分布在各處的代碼,一旦業(yè)務(wù)有變化,就不知道加減參數(shù)會不會對之前的業(yè)務(wù)有影響

      • 原因二:轉(zhuǎn)換成model也是為了在一開始就對所需要的參數(shù)進(jìn)行合法性檢查,業(yè)務(wù)能不能做最好在獲取參數(shù)時(shí),就直接判斷,不能走了一些流程后,突然發(fā)現(xiàn)參數(shù)不可用,然后再中斷流程,這樣會消耗服務(wù)的性能。而轉(zhuǎn)換model也是為了對所有參數(shù)進(jìn)行一次性的合法性檢查。

      • 原因三:外部數(shù)據(jù)映射成model,會在添加或者刪除數(shù)據(jù)時(shí)造成一定的約束,對比操作json,添加和刪除都較為隨意,既不能在類型上進(jìn)行約束,也不能在對應(yīng)關(guān)系上強(qiáng)制約束,后續(xù)開發(fā)者為了圖省事,寫著寫著就亂的沒法用了。

      模型要有業(yè)務(wù)含義,在傳遞給服務(wù)時(shí),一定要和該服務(wù)有很強(qiáng)的業(yè)務(wù)關(guān)系,不要為了簡單使用DO,或者參數(shù)差不多、但業(yè)務(wù)不相關(guān)的model圖省事。對于沒有形成強(qiáng)業(yè)務(wù)綁定的model,經(jīng)常會因?yàn)橐粋€(gè)業(yè)務(wù)的修改,導(dǎo)致當(dāng)下業(yè)務(wù)也需要聯(lián)動(dòng)的修改。要降低耦合性

      避免超級model,做任何業(yè)務(wù),都把參數(shù)往一個(gè)model中塞。這樣一是讓看代碼的人毫無頭緒,不知道到底哪些參數(shù)和當(dāng)下業(yè)務(wù)相關(guān),二是讓修改的人很擔(dān)心,去掉一個(gè)參數(shù)會不會影響到多個(gè)業(yè)務(wù)。所以盡量避免使用公共model,如果確實(shí)參數(shù)重合度比較高的,可以考慮model之間的有意義的繼承。

      多用模型,少用hashmap。hashmap當(dāng)時(shí)它相當(dāng)于一個(gè)自由模型,啥都可以塞,啥都可以取,使用上是方便,但是沒有套上任何業(yè)務(wù)信息,業(yè)務(wù)越大,修改越多,就會越不可控。每次修改都會造成一些隱患。

        本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多