1.不要嫌名字長(zhǎng) 無(wú)論是方法,變量,還是函數(shù)的取名,不要嫌棄名稱太長(zhǎng),只要能夠表示清楚含義就可以了。 2.String[] args而不是String args[],中括號(hào)是數(shù)組類(lèi)型的一部分,數(shù)組定義如下:String[] args; 在《Thinking in Java》這邊書(shū)里面,是這么解釋的: 大部分開(kāi)發(fā)人員,習(xí)慣前一種寫(xiě)法。 前一種寫(xiě)法符合我們的口語(yǔ)化,我們口語(yǔ)通常都說(shuō):定義一個(gè)字符串?dāng)?shù)組(String 代碼字符,[]代表數(shù)組) 3.POJO 類(lèi)中的任何布爾類(lèi)型的變量,都不要加is POJO類(lèi)中的任何布爾類(lèi)型的變量,都不要加 is,否則部分框架解析會(huì)引起序列化錯(cuò)誤。 大部分經(jīng)典的書(shū)籍都有提到這一點(diǎn),老話題了。 4.各層命名規(guī)約 A) Service/DAO 層方法命名規(guī)約 1) 獲取單個(gè)對(duì)象的方法用 get 做前綴。 2) 獲取多個(gè)對(duì)象的方法用 list 做前綴。 3) 獲取統(tǒng)計(jì)值的方法用 count 做前綴。 4) 插入的方法用 save(推薦)或 insert 做前綴。 5) 刪除的方法用 remove(推薦)或 delete 做前綴。 6) 修改的方法用 update 做前綴。 這一點(diǎn)確實(shí)很重要,有時(shí)候自己都做不到,規(guī)范大于編碼。 5.不允許出現(xiàn)任何魔法值(即未經(jīng)定義的常量) String key=”Id#taobao_”+tradeId; cache.put(key, value); 魔法數(shù)值:是指在代碼中直接出現(xiàn)的數(shù)值,而只有在這個(gè)數(shù)值記述的那部分代碼中才能明確了解其含義。 在這里進(jìn)行擴(kuò)充下: 魔法數(shù)字的例子 Java代碼
使用了帶名字的數(shù)值的例子 解決方法: Java代碼
6.多個(gè)參數(shù)逗號(hào)后邊必須加空格 有時(shí)候做項(xiàng)目,心急如焚時(shí),就會(huì)忘記下例中實(shí)參的”a”,后邊必須要有一個(gè)空格 Java代碼
7.開(kāi)發(fā)工具編碼設(shè)置 IDE 的 text file encoding 設(shè)置為 UTF-8; IDE 中文件的換行符使用 Unix 格式,不 要使用 windows 格式 8.所有的覆寫(xiě)方法,必須加@Override注解 如果在抽象類(lèi)中對(duì)方法簽名進(jìn)行修改,其實(shí)現(xiàn)類(lèi)會(huì)馬上編譯報(bào)錯(cuò).《Effective Java》這本書(shū)已經(jīng)說(shuō)的清清楚楚了,大家可以去啃啃這一節(jié)的內(nèi)容。 9.提倡盡量不用可變參數(shù)編程 相同參數(shù)類(lèi)型,相同業(yè)務(wù)含義,才可以使用Java的可變參數(shù),避免使用 Object??勺儏?shù)必須放置在參數(shù)列表的最后 Java代碼
10.基本數(shù)據(jù)類(lèi)型與包裝數(shù)據(jù)類(lèi)型的使用標(biāo)準(zhǔn) 所有的POJO類(lèi)屬性必須使用包裝數(shù)據(jù)類(lèi)型。 RPC方法的返回值和參數(shù)必須使用包裝數(shù)據(jù)類(lèi)型。 所有的局部變量推薦使用基本數(shù)據(jù)類(lèi)型。 說(shuō)明:POJO類(lèi)屬性沒(méi)有初值是提醒使用者在需要使用時(shí),必須自己顯式地進(jìn)行賦值,任何NPE 問(wèn)題,或者入庫(kù)檢查,都由使用者來(lái)保證。 正例:數(shù)據(jù)庫(kù)的查詢結(jié)果可能是 null,因?yàn)樽詣?dòng)拆箱,用基本數(shù)據(jù)類(lèi)型接收有 NPE 風(fēng)險(xiǎn)。 反例:某業(yè)務(wù)的交易報(bào)表上顯示成交總額漲跌情況,即正負(fù) x%,x 為基本數(shù)據(jù)類(lèi)型,調(diào)用的RPC 服務(wù),調(diào)用不成功時(shí),返回的是默認(rèn)值,頁(yè)面顯示:0%,這是不合理的,應(yīng)該顯示成中劃線-。所以包裝數(shù)據(jù)類(lèi)型的null值,能夠表示額外的信息,如:遠(yuǎn)程調(diào)用失敗,異常退出 11.序列化類(lèi)新增屬性時(shí),請(qǐng)不要修改serialVersionUID字段 避免反序列失敗 12.構(gòu)造方法里面禁止加入任何業(yè)務(wù)邏輯 如果有初始化邏輯,請(qǐng)放在init方法中,其實(shí)這是符合一個(gè)方法只做一件事的原則。 13.POJO 類(lèi)必須寫(xiě) toString 方法 使用工具類(lèi) source> generate toString 時(shí),如果繼承了另一個(gè) POJO 類(lèi),注意在前面加一下 super.toString。說(shuō)明:在方法執(zhí)行拋出異常時(shí),可以直接調(diào)用 POJO 的 toString()方法打印其屬性值,便于排查問(wèn)題。 我們項(xiàng)目中,這一點(diǎn)沒(méi)有做到… 14.同名的或者相似的方法放置在一起 15.類(lèi)內(nèi)方法定義順序 類(lèi)內(nèi)方法定義順序依次是:公有方法或保護(hù)方法 > 私有方法 > getter/setter 方法。 說(shuō)明: 公有方法是類(lèi)的調(diào)用者和維護(hù)者最關(guān)心的方法,首屏展示最好;保護(hù)方法雖然只是子類(lèi)關(guān)心,也可能是“模板設(shè)計(jì)模式”下的核心方法;而私有方法外部一般不需要特別關(guān)心,是一個(gè)黑盒實(shí)現(xiàn);因?yàn)榉椒ㄐ畔r(jià)值較低,所有 Service 和 DAO 的 getter/setter 方法放在類(lèi)體最后。 16.final可提高程序響應(yīng)效率 final可提高程序響應(yīng)效率,聲明成final的情況: - 不需要重新賦值的變量,包括類(lèi)屬性、局部變量。 - 對(duì)象參數(shù)前加final,表示不允許修改引用的指向。 - 類(lèi)方法確定不允許被重寫(xiě) 17.Map/Set的key為自定義對(duì)象時(shí),必須重寫(xiě)hashCode和equals String 重寫(xiě)了 hashCode 和 equals 方法,所以我們可以非常愉快地使用String對(duì)象作 為 key 來(lái)使用。 18.使用集合轉(zhuǎn)數(shù)組的方法,必須使用集合的toArray(T[]array)傳入的是類(lèi)型完全一樣的數(shù)組,大小就是 list.size()。 反例:直接使用 toArray無(wú)參方法存在問(wèn)題,此方法返回值只能是Object[]類(lèi),若強(qiáng)轉(zhuǎn)其它類(lèi)型數(shù)組將出現(xiàn) ClassCastException 錯(cuò)誤。 正例: Java代碼
說(shuō)明:使用 toArray 帶參方法,入?yún)⒎峙涞臄?shù)組空間不夠大時(shí),toArray 方法內(nèi)部將重新分配內(nèi)存空間,并返回新數(shù)組地址;如果數(shù)組元素大于實(shí)際所需,下標(biāo)為[ list.size() ]的數(shù)組元素將被置為null,其它數(shù)組元素保持原值,因此最好將方法入?yún)?shù)組大小定義與集合元素個(gè)數(shù)一致 19.Arrays.asList()把數(shù)組轉(zhuǎn)換成集合時(shí),不能使用其修改集合相關(guān)的方法 它的 add/remove/clear 方法會(huì)拋出 UnsupportedOperationException 異常。 說(shuō)明: asList 的返回對(duì)象是一個(gè) Arrays 內(nèi)部類(lèi),并沒(méi)有實(shí)現(xiàn)集合的修改方法。 Arrays.asList體現(xiàn)的是適配器模式,只是轉(zhuǎn)換接口,后臺(tái)的數(shù)據(jù)仍是數(shù)組。 Java代碼
第一種情況:list.add(“c”); 運(yùn)行時(shí)異常。 第二種情況:str[0]= “gujin”; 那么 list.get(0)也會(huì)隨之修改。 20.不要在foreach循環(huán)里進(jìn)行元素的remove/add操作 remove元素請(qǐng)使用Iterator方式,如果并發(fā)操作,需要對(duì) Iterator 對(duì)象加鎖。 反例: Java代碼
21.集合初始化時(shí),盡量指定集合初始值大小 ArrayList 盡量使用 ArrayList(int initialCapacity) 初始化。 22.使用entrySet遍歷Map類(lèi)集合KV,而不是keySet keySet 其實(shí)是遍歷了 2 次,一次是轉(zhuǎn)為 Iterator 對(duì)象,另一次是從 hashMap 中取出 key所對(duì)應(yīng)的 value。而 entrySet 只是遍歷了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,使用Map.foreach 方法。 這一點(diǎn)可以參考《Thinking in Java》第17章容器深入研究這一章 23.利用Set元素唯一的特性,可以快速對(duì)另一個(gè)集合進(jìn)行去重操作 避免使用List的contains 方法進(jìn)行遍歷去重操作。 24.數(shù)據(jù)庫(kù)合適的字符存儲(chǔ)長(zhǎng)度 不但節(jié)約數(shù)據(jù)庫(kù)表空間、節(jié)約索引存儲(chǔ),更重要的是提升檢索速度。 25.在表查詢中,一律不要使用 * 作為查詢的字段列表 需要哪些字段必須明確寫(xiě)明。 說(shuō)明:1)增加查詢分析器解析成本。2)增減字段容易與resultMap配置不一致。 26.in操作能避免則避免 若實(shí)在避免不了,需要仔細(xì)評(píng)估 in 后邊的集合元素?cái)?shù)量,控制在 1000 個(gè)之內(nèi)。 27.異常信息應(yīng)該包括兩類(lèi)信息 異常信息應(yīng)該包括兩類(lèi)信息:案發(fā)現(xiàn)場(chǎng)信息和異常堆棧信息。如果不處理,那么往上 拋。logger.error(各類(lèi)參數(shù)或者對(duì)象 toString + “_” + e.getMessage(), e); 28.if/else/for/while/do 語(yǔ)句中必須使用大括號(hào),即使只有一行代碼 這一點(diǎn)我有點(diǎn)不支持,比如下面的代碼: Java代碼
Java代碼
那個(gè)比較好自己對(duì)比吧!??! 29.禁止使用存儲(chǔ)過(guò)程 存儲(chǔ)過(guò)程難以調(diào)試和擴(kuò)展,更沒(méi)有移植性 30.推薦盡量少用 else, if-else的方式可以改寫(xiě)成 Java代碼
31.不要在條件判斷中執(zhí)行復(fù)雜的語(yǔ)句 正例: Java代碼
反例: Java代碼
32.線程安全相關(guān)的類(lèi)使用 SimpleDateFormat 是線程不安全的類(lèi),一般不要定義為 static 變量,如果定義為static,必須加鎖,或者使用 DateUtils 工具類(lèi)。 正例:注意線程安全,使用 DateUtils。亦推薦如下處理: Java代碼
說(shuō)明:如果是 JDK8 的應(yīng)用,可以使用 instant 代替 Date,Localdatetime 代替 Calendar,Datetimeformatter 代替 Simpledateformatter,官方給出的解釋:simple beautiful strong immutable thread-safe。 避免 Random 實(shí)例被多線程使用,雖然共享該實(shí)例是線程安全的,但會(huì)因競(jìng)爭(zhēng)同一seed 導(dǎo)致的性能下降。 說(shuō)明:Random 實(shí)例包括 java.util.Random 的實(shí)例或者 Math.random()實(shí)例。 正例:在 JDK7 之后,可以直接使用 API ThreadLocalRandom,在JDK7之前,可以做到每個(gè)線程一個(gè)實(shí)例。 33.類(lèi)、類(lèi)屬性、類(lèi)方法的注釋必須使用 javadoc 規(guī)范 類(lèi)、類(lèi)屬性、類(lèi)方法的注釋必須使用 javadoc 規(guī)范,使用/*內(nèi)容/格式,不得使用//xxx 方式。 方法內(nèi)部單行注釋,在被注釋語(yǔ)句上方另起一行,使用//注釋。方法內(nèi)部多行注釋使 用/* */注釋,注意與代碼對(duì)齊 可以參考《代碼整潔之道》這本書(shū)中的注釋這一章,里面內(nèi)容更加纖細(xì)。 34.刪除被注釋掉的沒(méi)用的東西 對(duì)于“明確停止使用的代碼和配置”,如方法、變量、類(lèi)、配置文件、動(dòng)態(tài)配置屬性 等要堅(jiān)決從程序中清理出去,避免造成過(guò)多垃圾。清理這類(lèi)垃圾代碼是技術(shù)氣場(chǎng),不要有這樣 的觀念:“不做不錯(cuò),多做多錯(cuò)”。 35.獲取當(dāng)前毫秒數(shù):System.currentTimeMillis() 而不是 new Date().getTime(); 說(shuō)明:如果想獲取更加精確的納秒級(jí)時(shí)間值,用 System.nanoTime。在 JDK8 中,針對(duì)統(tǒng)計(jì)時(shí)間等場(chǎng)景,推薦使用 Instant 類(lèi)。 【強(qiáng)制】線程資源必須通過(guò)線程池提供,不允許在應(yīng)用中自行顯式創(chuàng)建線程。 說(shuō)明: 使用線程池的好處是減少在創(chuàng)建和銷(xiāo)毀線程上所花的時(shí)間以及系統(tǒng)資源的開(kāi)銷(xiāo),解決資源不足的問(wèn)題。如果不使用線程池,有可能造成系統(tǒng)創(chuàng)建大量同類(lèi)線程而導(dǎo)致消耗完內(nèi)存或者“過(guò)度切換”的問(wèn)題。 36.所有的類(lèi)都必須添加創(chuàng)建者信息。 我們?cè)獨(dú)忭?xiàng)目組成員都沒(méi)有加這個(gè),有的也只是用@author Administrator 37.代碼修改的同時(shí),注釋也要進(jìn)行相應(yīng)的修改 尤其是參數(shù)、返回值、異常、核心邏輯等的修改。 38.任何數(shù)據(jù)結(jié)構(gòu)的使用都應(yīng)限制大小 說(shuō)明:這點(diǎn)很難完全做到,但很多次的故障都是因?yàn)閿?shù)據(jù)結(jié)構(gòu)自增長(zhǎng),結(jié)果造成內(nèi)存被吃光。 39.日志文件推薦至少保存 15 天 因?yàn)橛行┊惓>邆湟浴爸堋睘轭l次發(fā)生的特點(diǎn)。 40.對(duì)trace/debug/info級(jí)別的日志輸出,必須使用條件輸出形式或者使用占位符的方式 說(shuō)明:logger.debug(“Processing trade with id: ” + id + ” symbol: ” + symbol); 如果 日志級(jí)別是 warn,上述日志不會(huì)打印,但是會(huì)執(zhí)行字符串拼接操作,如果 symbol 是對(duì)象,會(huì)執(zhí)行 toString()方法,浪費(fèi)了系統(tǒng)資源,執(zhí)行了上述操作,最終日志卻沒(méi)有打印。 正例:(條件) Java代碼
正例:(占位符) Java代碼
41.特殊注釋標(biāo)記,請(qǐng)注明標(biāo)記人與標(biāo)記時(shí)間 注意及時(shí)處理這些標(biāo)記,通過(guò)標(biāo)記掃描,經(jīng)常清理此類(lèi)標(biāo)記。線上故障有時(shí)候就是來(lái)源于這些標(biāo)記處的代碼。 · 待辦事宜(TODO):( 標(biāo)記人,標(biāo)記時(shí)間,[預(yù)計(jì)處理時(shí)間]) 表示需要實(shí)現(xiàn),但目前還未實(shí)現(xiàn)的功能。這實(shí)際上是一個(gè) javadoc 的標(biāo)簽,目前的 javadoc 還沒(méi)有實(shí)現(xiàn),但已經(jīng)被廣泛使用。 只能應(yīng)用于類(lèi),接口和方法(因?yàn)樗且粋€(gè) javadoc 標(biāo)簽)。 · 錯(cuò)誤,不能工作(FIXME):(標(biāo)記人,標(biāo)記時(shí)間,[預(yù)計(jì)處理時(shí)間]) 在注釋中用 FIXME 標(biāo)記某代碼是錯(cuò)誤的,而且不能工作,需要及時(shí)糾正的情況。 42.避免用Apache Beanutils 進(jìn)行屬性的 copy。 說(shuō)明:Apache BeanUtils 性能較差,可以使用其他方案比如 spring BeanUtils, Cglib BeanCopier。 43.注意HashMap的擴(kuò)容死鏈 導(dǎo)致 CPU 飆升的問(wèn)題 44.應(yīng)用中的擴(kuò)展日志(如打點(diǎn)、臨時(shí)監(jiān)控、訪問(wèn)日志等)命名方式 appName_logType_logName.log。logType:日志類(lèi)型,推薦分類(lèi)有stats/desc/monitor/visit 等;logName:日志描述。這種命名的好處:通過(guò)文件名就可知道日志文件屬于什么應(yīng)用,什么類(lèi)型,什么目的,也有利于歸類(lèi)查找。 45.高并發(fā)時(shí),同步調(diào)用應(yīng)該去考量鎖的性能損耗 能用無(wú)鎖數(shù)據(jù)結(jié)構(gòu),就不要用鎖;能鎖區(qū)塊,就不要鎖整個(gè)方法體;能用對(duì)象鎖,就不要用類(lèi)鎖。 46.在代碼中使用“拋異?!边€是“返回錯(cuò)誤碼” 對(duì)于公司外的 http/api開(kāi)放接口必須使用“錯(cuò)誤碼”;而應(yīng)用內(nèi)部推薦異常拋出;跨應(yīng)用間 RPC 調(diào)用優(yōu)先考慮使用 Result方式,封裝isSuccess、“錯(cuò)誤碼”、“錯(cuò)誤簡(jiǎn)短信息”。 說(shuō)明:關(guān)于 RPC 方法返回方式使用 Result 方式的理由: - 使用拋異常返回方式,調(diào)用方如果沒(méi)有捕獲到就會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤。 - 如果不加棧信息,只是 new 自定義異常,加入自己的理解的 error message,對(duì)于調(diào)用端解決問(wèn)題的幫助不會(huì)太多。如果加了棧信息,在頻繁調(diào)用出錯(cuò)的情況下,數(shù)據(jù)序列化和傳輸?shù)男阅軗p耗也是問(wèn)題。 47.謹(jǐn)慎地記錄日志。生產(chǎn)環(huán)境禁止輸出 debug 日志 有選擇地輸出 info 日志;如果使用warn來(lái)記錄剛上線時(shí)的業(yè)務(wù)行為信息,一定要注意日志輸出量的問(wèn)題,避免把服務(wù)器磁盤(pán)撐爆,并記得及時(shí)刪除這些觀察日志。 說(shuō)明:大量地輸出無(wú)效日志,不利于系統(tǒng)性能提升,也不利于快速定位錯(cuò)誤點(diǎn)。紀(jì)錄日志時(shí)請(qǐng) 48.單表行數(shù)超過(guò) 500 萬(wàn)行或者單表容量超過(guò) 2GB,才推薦進(jìn)行分庫(kù)分表。 除非特別注明,雞啄米文章均為原創(chuàng)
轉(zhuǎn)載請(qǐng)標(biāo)明本文地址:http://www./software/690.html
2017年2月13日
作者:雞啄米
分類(lèi):軟件開(kāi)發(fā)
瀏覽:559
評(píng)論:0
|
|
來(lái)自: 北書(shū)房2014 > 《程序員》