久久综合九色综合97婷婷-美女视频黄频a免费-精品日本一区二区三区在线观看-日韩中文无码有码免费视频-亚洲中文字幕无码专区-扒开双腿疯狂进出爽爽爽动态照片-国产乱理伦片在线观看夜-高清极品美女毛茸茸-欧美寡妇性猛交XXX-国产亚洲精品99在线播放-日韩美女毛片又爽又大毛片,99久久久无码国产精品9,国产成a人片在线观看视频下载,欧美疯狂xxxx吞精视频

有趣生活

當(dāng)前位置:首頁>時(shí)尚>怎么寫出好的代碼(如何寫出漂亮的代碼)

怎么寫出好的代碼(如何寫出漂亮的代碼)

發(fā)布時(shí)間:2024-10-23閱讀(19)

這篇文章講述了代碼重構(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操作就自動一致了。這是一個(gè)簡單的變量“高內(nèi)聚”

三、刪掉未使用代碼
  • 當(dāng)前不用的代碼一定要刪掉,一是不整潔,二是影響后續(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)盡量多加,比如支付、訂單這種,改動風(fēng)險(xiǎn)較高,能說明的最好是說明下。多寫注釋的原因主要在于代碼是英文為主,以中文為母語的人常常會將同一個(gè)單詞理解成不同的含義,比如voucher這種多義詞,既可以理解成單據(jù)、憑證,也可以理解為代金卷。特別是對于簡寫和隱形約定,很難做到每個(gè)人都理解,所以盡量多寫些注釋吧
  • 重要流程、算法邏輯、特殊判斷一定要加注釋,
  • 接口入?yún)ⅰ⒎祷刂档南薅ǎ赡艹霈F(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)定的代碼沉到下層,變化抽象到上層。下圖是我們之前商量過的代碼分層框架, 不一定要完全按照這種模式來,但可以有意的按照這種思路去把代碼分離開。

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

  • domain:主要是領(lǐng)域?qū)ο螅杜e、常量、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)動的修改。要降低耦合性

避免超級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ù)越大,修改越多,就會越不可控。每次修改都會造成一些隱患。

轉(zhuǎn)自:http://ningg.top/develop-series-refactor-best-practice/

TAGS標(biāo)簽:  怎么  寫出  好的  代碼  如何  怎么寫出好的代碼(如

歡迎分享轉(zhuǎn)載→http://m.avcorse.com/read-449172.html

Copyright ? 2024 有趣生活 All Rights Reserve吉ICP備19000289號-5 TXT地圖HTML地圖XML地圖