自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

京東資深架構(gòu)師代碼評(píng)審?fù)嵩?shī)

開發(fā) 開發(fā)工具
架構(gòu)師說, 用20個(gè)字描述代碼評(píng)審的內(nèi)容, 自省也省人。由于是一字一含義, 不連貫, 為了增強(qiáng)趣味性, 每句都增加對(duì)應(yīng)的歪解。

賈言

賈言

架構(gòu)師說, 用20個(gè)字描述代碼評(píng)審的內(nèi)容, 自省也省人。由于是一字一含義, 不連貫, 為了增強(qiáng)趣味性, 每句都增加對(duì)應(yīng)的歪解。只是對(duì)常見評(píng)審的描述, 不盡之處,歡迎補(bǔ)充!

驗(yàn)幻空越重 -- 言歡空月蟲

驗(yàn): 公共方法都要做參數(shù)的校驗(yàn),參數(shù)校驗(yàn)不通過明確拋出異?;?qū)?yīng)響應(yīng)碼。

  • java bean驗(yàn)證已經(jīng)是一個(gè)很古老的技術(shù)了,會(huì)避免我們很多問題,可參考:http://beanvalidation.org/ http://www.infoq.com/cn/news/2010/03/javaee6-validation https://www.sitepoint.com/using-java-bean-validation-method-parameters-return-values/
  • 在接口中也明確使用驗(yàn)證注解修飾參數(shù)和返回值, 作為一種協(xié)議要求調(diào)用方按驗(yàn)證注解約束傳參, 返回值驗(yàn)證注解約束提供方按注解要求返回參數(shù)

幻: 在代碼中要杜絕幻數(shù),幻數(shù)可定義為枚舉或常量以增強(qiáng)其可讀性

空: 要時(shí)刻警惕空指針異常

  • 常見的 a.equals(b) 要把常量放到左側(cè)
  • aInteger == 10 如果 aInteger 為空時(shí)會(huì)拋出空指針異常
  • 不確認(rèn)返回集合是否可為空時(shí)要做非空判斷, 再做for循環(huán)
  • 使用空對(duì)象模式, 約定返回空集合, 而非null
  • 使用StringUtils判斷字符串非空

越: 如果方法傳入數(shù)組下標(biāo)作為參數(shù),要在一開始就做下標(biāo)越界的校驗(yàn),避免下標(biāo)越界異常

重: 不要寫重復(fù)代碼,重復(fù)代碼要使用重構(gòu)工具提取重構(gòu)

命循頻異長(zhǎng) - 明勛品宜昌

命: 包 / 類 / 方法 / 字段 / 變量 / 常量的命名要遵循規(guī)范,要名副其實(shí), 這不但可以增加可讀性,還可以在起名的過程中引導(dǎo)我們思考方法 / 變量 / 類的職責(zé)是否合適

有意義很重要, 典型無(wú)意義命名:

  1. public static final Integer CODE_39120 = 39120; 
  2. public static final String MESSAGE_39120 = "[包裹]與[庫(kù)房號(hào)]不一致,確定裝箱?"
  3.   
  4. public static final Integer CODE_39121 = 39121; 
  5. public static final String MESSAGE_39121 = "[包裹]與[箱號(hào)]的承運(yùn)類型不一致,確定裝箱?"
  6.   
  7. Rule rule1 = request.getRuleMap().get("1050"); 

CODE_39120這個(gè)名字和幻數(shù)沒多大區(qū)別。

循: 不要在循環(huán)中調(diào)用服務(wù),不要在循環(huán)中做數(shù)據(jù)庫(kù)等跨網(wǎng)絡(luò)操作

頻: 寫每一個(gè)方法時(shí)都要知道這個(gè)方法的調(diào)用頻率,一天多少,一分多少,一秒多少,峰值可能達(dá)到多少,調(diào)用頻率高的一定要考慮性能指標(biāo), 考慮是否會(huì)打垮數(shù)據(jù)庫(kù),是否會(huì)擊穿緩存

異: 異常處理是程序員最基本的素質(zhì),不要處處捕獲異常,對(duì)于捕獲了只寫日志,沒有任何處理的 catch 要問一問自己,這樣吃掉異常,是否合理

下面是一個(gè)反例, 在導(dǎo)出文件的controller方法中做了兩層的try...catch, 在catch塊中記錄日志后什么都沒做, 這樣用戶看不到真正想要的內(nèi)容, 研發(fā)也只有看日志才能發(fā)現(xiàn)錯(cuò)誤, 而“看日志”, 通常只有業(yè)務(wù)方反饋問題時(shí)才會(huì)看, 就會(huì)導(dǎo)致研發(fā)人員發(fā)現(xiàn)錯(cuò)誤會(huì)比現(xiàn)場(chǎng)人員還會(huì)晚。

  1. @RequestMapping(value = "/export"
  2. public void export(CityRelationDomain condition, HttpServletResponse response) { 
  3.    ZipOutputStream zos = null
  4.    BufferedWriter bufferedWriter = null
  5.    try { 
  6.       condition.setStart(0); 
  7.       condition.setSize(MAX_EXPORT_LINES); 
  8.       List<CityRelationDomain> list = cityRelationService.getOrdersByCondition(condition); 
  9.       response.setCharacterEncoding("GBK"); 
  10.       response.setContentType("multipart/form-data"); 
  11.       response.setHeader("Content-Disposition", "attachment;fileName=export.zip"); 
  12.       zos = new ZipOutputStream(response.getOutputStream()); 
  13.       bufferedWriter = new BufferedWriter(new OutputStreamWriter(zos, "GBK")); 
  14.       bufferedWriter.write("訂單類型編碼,始發(fā)城市-省,始發(fā)城市-市,目的城市-省,目的城市-市"); 
  15.       ZipEntry zipEntry = new ZipEntry("export.csv"); 
  16.       zos.putNextEntry(zipEntry); 
  17.       for (CityRelationDomain domain : list) { 
  18.          try { 
  19.             bufferedWriter.newLine(); 
  20.             bufferedWriter.write(CSVExportUtil.trans2CSV(domain.getOrderCode())); 
  21.             bufferedWriter.write(','); 
  22.             bufferedWriter.write(CSVExportUtil.trans2CSV(domain.getProvinceNameFrom())); 
  23.             bufferedWriter.write(','); 
  24.             bufferedWriter.write(CSVExportUtil.trans2CSV(domain.getCityNameFrom())); 
  25.             bufferedWriter.write(','); 
  26.             bufferedWriter.write(CSVExportUtil.trans2CSV(domain.getProvinceNameTo())); 
  27.             bufferedWriter.write(','); 
  28.             bufferedWriter.write(CSVExportUtil.trans2CSV(domain.getCityNameTo())); 
  29.          } catch (Exception e) { 
  30.             e.printStackTrace(); 
  31.          } 
  32.       } 
  33.       bufferedWriter.newLine(); 
  34.            bufferedWriter.flush(); 
  35.            zos.closeEntry(); 
  36.            bufferedWriter.close(); 
  37.    } catch (Exception e) { 
  38.       e.printStackTrace(); 
  39.       logger.error("導(dǎo)出CSV文件異常"); 
  40.    } finally { 
  41.       try { 
  42.          if (zos != null) { 
  43.             zos.close(); 
  44.          } 
  45.          if (bufferedWriter != null) { 
  46.             bufferedWriter.close(); 
  47.          } 
  48.       } catch (IOException e) { 
  49.          e.printStackTrace(); 
  50.       } 
  51.    } 

長(zhǎng): 如果一行代碼過長(zhǎng),要分解開來;如果一個(gè)方法過長(zhǎng),要重構(gòu)方法;如果一個(gè)類過長(zhǎng)要考慮拆分類

依輪線日簡(jiǎn) - 依倫先日賤

依: 如果調(diào)用了外部依賴, 一定要搞清楚這個(gè)外部依賴可以提供的性能指標(biāo),***約定 SLA

輪: 不要重復(fù)造輪子,如果已經(jīng)有成熟類庫(kù)實(shí)現(xiàn)了類似功能,要優(yōu)先使用成熟類庫(kù)的方法,這是因?yàn)槌墒祛悗?kù)中的方法都經(jīng)過很多人的測(cè)試驗(yàn)證,通常情況下我們自己實(shí)現(xiàn)的質(zhì)量***等同于成熟類庫(kù)的質(zhì)量。

線: 要注意我們的 jsf 服務(wù),web 應(yīng)用,消費(fèi)消息的 worker 都是多線程環(huán)境,要注意線程安全問題,最典型的 HashMap,SimpleDateFormat ,ArrayList 是非線程安全的,另外如果使用 Spring 自動(dòng)掃描服務(wù),那么這個(gè)服務(wù)默認(rèn)是單例,其內(nèi)部成員是多個(gè)線程共享的,如果直接用成員變量是有線程不安全的。

兩個(gè)典型的錯(cuò)誤代碼片段:

  • 無(wú)視 SimpleDateFormat 非線程安全
    1. @Service 
    2. public class AService { 
    3.     private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd"); 
    4.   
    5.     public void doSomething() { 
    6.         //use FORMAT 
    7.     } 
  • 使用 Service 成員變量
    1. @Service 
    2. public class BService { 
    3.     private Pojo b; 
    4.   
    5.     public void doB() { 
    6.          b = getB(); 
    7.          process(b); 
    8.     } 

日: 打印日志和設(shè)定合理的日志級(jí)別,如有必要要添加 if 條件限定是否打印日志,在日志中使用 JSON 序列化,生成長(zhǎng)字符串的 toString() 都要做 if 限定打印,否則配置的日志級(jí)別沒達(dá)到,也會(huì)做大量字符串拼接,占用很多 gc 年輕代內(nèi)存. 另外一定要通過log4j打印日志而不是直接把日志打印到控制臺(tái)。

典型錯(cuò)誤示例:

  1. @Service 
  2. public class FooService { 
  3.     private static final Logger LOGGER = LoggerFactory.getLogger(FooService.class); 
  4.   
  5.     public void doFooThing(Foo foo) { 
  6.         LOGGER.debug("get parameter foo {}", JSONObject.toString(foo)); 
  7.         try {/*do something*/} catch (Exception ex) {ex.printStackTrace();} 
  8.     } 

簡(jiǎn): 盡可能保持整體設(shè)計(jì)的簡(jiǎn)潔,方法實(shí)現(xiàn)的簡(jiǎn)潔,要根據(jù)情況使用內(nèi)存緩存,redis 緩存,jmq 異步處理。這里的簡(jiǎn)需要把握好分寸。

接偶正分壯 - 潔偶正粉妝

接: 接口是用來隔離變化的,如果一個(gè)業(yè)務(wù)有幾種不同的形態(tài),但都有相同的處理,那么可以定義接口來隔離業(yè)務(wù)形態(tài)的不同,在服務(wù)調(diào)用處,通過業(yè)務(wù)類型字段來獲得不同的服務(wù)類。而不要實(shí)現(xiàn)一個(gè)類,然后在類的各個(gè)方法中都根據(jù)業(yè)務(wù)類型做 if else 或更復(fù)雜的各種判斷。

典型示例:

  • 做法 1 :
    1. public interface BarService {    void doBarThing(Bar b); 
    2.       
    3.     void doBarFatherThing(Bar b); 
    4. public class BarServiceImpl  implement BarService{ 
    5.     public void doBarThing(Bar b) { 
    6.         if (b.getType() == BarType.A) { 
    7.             //do some logic 
    8.         } else (b.getType() == BarType.B) { 
    9.             //do some B type logic 
    10.         } 
    11.         //do other doBarThing logic 
    12.     } 
    13.       
    14.     public void doBarFatherThing(Bar b) { 
    15.         if (b.getType() == BarType.A) { 
    16.             //do some logic 
    17.         } else (b.getType() == BarType.B) { 
    18.             //do some B type logic 
    19.         } 
    20.         //do other doBarFatherThing logic 
    21.     } 
  • 做法 2 :
    1. public interface BarService { 
    2.     void doBarThing(Bar b); 
    3.       
    4.     void doBarFatherThing(Bar b); 
    5. public class BarServiceFactory { 
    6.     public BarService getBarService(BarType type) { 
    7.         // get bar service logic 
    8.     } 
    9. //如果有公共邏輯就定義, 沒有就不定義 
    10. public class BaseBarService implement BarService { 
    11.     public void doBarThing(Bar b) { 
    12.         //do other doBarThing logic 
    13.     } 
    14.       
    15.     public void doBarFatherThing(Bar b) { 
    16.         //do other doBarFatherThing logic 
    17.     } 
    18.       
    19. public class TypeABarService extends BaseBarService  implement BarService { 
    20.     public void doBarThing(Bar b) { 
    21.         // doATypeThing 
    22.         super.doBarThing(b); 
    23.     } 
    24.       
    25.     public void doBarFatherThing(Bar b) { 
    26.         // do bar type A service 
    27. super.doBarFatherThing(b); //如果需要就調(diào)用, 不需要就不調(diào)用父類 
    28.     } 
    29.       

做法 2 的好處是將不同類型的邏輯解耦,各自發(fā)展,不會(huì)相互影響,如果添加類型也不必影響現(xiàn)有類型邏輯。

偶: 認(rèn)識(shí)系統(tǒng)之間的耦合關(guān)系,通過同步數(shù)據(jù)來做兩個(gè)系統(tǒng)之間的交互是一種很強(qiáng)的耦合關(guān)系,會(huì)使數(shù)據(jù)接收方依賴于數(shù)據(jù)發(fā)送方的數(shù)據(jù)庫(kù)定義,如果發(fā)送方想改數(shù)據(jù)結(jié)構(gòu),必須要求下游接收方一起修改;通過接口調(diào)用是一種常見的系統(tǒng)耦合關(guān)系,接口的提供方要保證接口的可用性,接口的調(diào)用方要考慮接口不可用時(shí)的應(yīng)對(duì)方案; mq 消息是一種解耦的方法,兩個(gè)系統(tǒng)不存在實(shí)時(shí)的耦合關(guān)系。但是 mq 解耦的方式不能濫用,在同一系統(tǒng)內(nèi)不宜過多使用 mq 消息來做異步,要盡可能保證接口的性

能, 而不是通過 mq 防止出問題后重新消費(fèi)。

正: 模塊之間依賴關(guān)系要正向依賴,不能讓底層模塊依賴于上層模塊;不能讓數(shù)據(jù)層依賴于服務(wù)層也不能讓服務(wù)層依賴于 UI 層; 也不能在模塊之間形成循環(huán)依賴關(guān)系。

分: 分而治之,復(fù)雜的問題要分解成幾個(gè)相對(duì)簡(jiǎn)單的問題來解決,首先要分析出核心問題, 然后分析出核心的入?yún)⑹鞘裁?,結(jié)果是什么,入?yún)⑼ㄟ^幾步變化可以得出結(jié)果。

壯: 時(shí)刻注意程序的健壯性,從兩個(gè)方面實(shí)踐提升健壯性:

  • 契約,在設(shè)計(jì)接口時(shí)定義好協(xié)議參數(shù),并在實(shí)現(xiàn)時(shí)***時(shí)間校驗(yàn)參數(shù),如果參數(shù)有問題,直接返回給調(diào)用方; 如果出現(xiàn)異常情況, 也按異常情況約定應(yīng)對(duì)策略
  • 考慮各種邊界條件的輸出,比如運(yùn)單號(hào)查詢服務(wù), 要考慮用戶輸入錯(cuò)誤運(yùn)單時(shí)怎么返回,有邊界的查詢條件,如果用戶查詢條件超過邊界了, 應(yīng)該返回什么
  • 為失敗做設(shè)計(jì),如果出問題了有降級(jí)應(yīng)對(duì)方案。

作者:趙玉開,十年以上互聯(lián)網(wǎng)研發(fā)經(jīng)驗(yàn),2013年加入京東,在運(yùn)營(yíng)研發(fā)部任架構(gòu)師,期間先后主持了物流系統(tǒng)自動(dòng)化運(yùn)維平臺(tái)、青龍數(shù)據(jù)監(jiān)控系統(tǒng)和物流開放平臺(tái)的研發(fā)工作,具有豐富的物流系統(tǒng)業(yè)務(wù)和架構(gòu)經(jīng)驗(yàn)。在此之前在和訊網(wǎng)負(fù)責(zé)股票基金行情系統(tǒng)的研發(fā)工作,具備高并發(fā)、高可用互聯(lián)網(wǎng)應(yīng)用研發(fā)經(jīng)驗(yàn)。

【本文來自51CTO專欄作者張開濤的微信公眾號(hào)(開濤的博客),公眾號(hào)id: kaitao-1234567】

 

 戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來源: 51CTO專欄
相關(guān)推薦

2015-12-09 15:16:03

架構(gòu)師京東架構(gòu)

2016-04-20 17:18:29

分布式數(shù)據(jù)庫(kù)京東WOT

2018-07-03 15:46:24

Java架構(gòu)師源碼

2018-02-05 09:30:23

高性能高并發(fā)服務(wù)

2012-11-01 15:08:10

IBM資深架構(gòu)師

2019-10-21 09:32:48

緩存架構(gòu)分層

2013-10-17 15:45:24

紅帽

2013-10-17 15:54:46

紅帽

2015-04-10 17:35:26

WOT2015谷歌資深架構(gòu)師李聰

2021-06-07 09:35:11

架構(gòu)運(yùn)維技術(shù)

2014-04-09 18:01:42

京東

2012-12-17 17:38:37

System CentWindows SerHyper-V

2013-11-14 10:06:11

紅帽redhat

2009-02-19 16:19:48

SaaS開發(fā)SaaS安全SaaS

2018-09-17 05:00:59

架構(gòu)系統(tǒng)練級(jí)

2013-01-28 10:23:12

軟件架構(gòu)師架構(gòu)師程序員

2016-08-29 11:33:23

京東云云計(jì)算云安全

2018-07-04 13:41:17

架構(gòu)系統(tǒng)結(jié)構(gòu)數(shù)據(jù)庫(kù)

2017-12-15 20:30:03

開發(fā)碼農(nóng)架構(gòu)師

2025-04-09 04:00:00

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)