熟读《阿里巴巴java开发手册》(六、工程结构,七、 设计规约,专有名词解释)
目錄
六、工程結構
(一) 應用分層
(二) 二方庫依賴
(三) 服務器
七、 設計規約
附 2: 專有名詞解釋
六、工程結構
(一) 應用分層
1. 【推薦】 圖中默認上層依賴于下層,箭頭關系表示可直接依賴,如:開放接口層可以依賴于Web 層,也可以直接依賴于 Service 層,依此類推:
? 開放接口層:可直接封裝 Service 方法暴露成 RPC 接口;通過 Web 封裝成 http 接口; 進行網關安全控制、 流量控制等。
? 終端顯示層:各個端的模板渲染并執行顯示的層。 當前主要是 velocity 渲染, JS 渲染, JSP 渲染,移動端展示等。
? Web 層:主要是對訪問控制進行轉發,各類基本參數校驗,或者不復用的業務簡單處理等。
? Service 層:相對具體的業務邏輯服務層。
? Manager 層:通用業務處理層,它有如下特征:
1) 對第三方平臺封裝的層,預處理返回結果及轉化異常信息。
2) 對 Service 層通用能力的下沉,如緩存方案、 中間件通用處理。
3) 與 DAO 層交互,對多個 DAO 的組合復用。
? DAO 層:數據訪問層,與底層 MySQL、 Oracle、 Hbase 等進行數據交互。
? 外部接口或第三方平臺:包括其它部門 RPC 開放接口,基礎平臺,其它公司的 HTTP 接口。
2. 【參考】 ( 分層異常處理規約) 在 DAO 層,產生的異常類型有很多,無法用細粒度的異常進行 catch,使用 catch(Exception e)方式,并 throw new DAOException(e),不需要打印日志,因為日志在 Manager/Service 層一定需要捕獲并打印到日志文件中去,如果同臺服務器再打日志,浪費性能和存儲。在 Service 層出現異常時,必須記錄出錯日志到磁盤,盡可能帶上參數信息,相當于保護案發現場。如果 Manager 層與 Service 同機部署,日志方式與 DAO 層處理一致,如果是單獨部署,則采用與 Service 一致的處理方式。 Web 層絕不應該繼續往上拋異常,因為已經處于頂層,如果意識到這個異常將導致頁面無法正常渲染,那么就應該直接跳轉到友好錯誤頁面, 加上用戶容易理解的錯誤提示信息。開放接口層要將異常處理成錯誤碼和錯誤信息方式返回。
3. 【參考】 分層領域模型規約:
? DO( Data Object): 此對象與數據庫表結構一一對應,通過 DAO 層向上傳輸數據源對象。
? DTO( Data Transfer Object):數據傳輸對象, Service 或 Manager 向外傳輸的對象。
? BO( Business Object):業務對象, 由 Service 層輸出的封裝業務邏輯的對象。
? AO( Application Object): 應用對象, 在 Web 層與 Service 層之間抽象的復用對象模型,極為貼近展示層,復用度不高。
? VO( View Object):顯示層對象,通常是 Web 向模板渲染引擎層傳輸的對象。
? Query:數據查詢對象,各層接收上層的查詢請求。 注意超過 2 個參數的查詢封裝,禁止使用 Map 類來傳輸。
(二) 二方庫依賴
1. 【強制】 定義 GAV 遵從以下規則:
1) GroupID 格式: com.{公司/BU }.業務線 [.子業務線],最多 4 級。
說明: {公司/BU} 例如: alibaba/taobao/tmall/aliexpress 等 BU 一級;子業務線可選。
正例: com.taobao.jstorm 或 com.alibaba.dubbo.register
2) ArtifactID 格式:產品線名-模塊名。語義不重復不遺漏,先到中央倉庫去查證一下。
正例: dubbo-client / fastjson-api / jstorm-tool
3) Version:詳細規定參考下方。
2. 【強制】 二方庫版本號命名方式:主版本號.次版本號.修訂號
1) 主版本號: 產品方向改變, 或者大規模 API 不兼容, 或者架構不兼容升級。
2) 次版本號: 保持相對兼容性,增加主要功能特性,影響范圍極小的 API 不兼容修改。
3) 修訂號: 保持完全兼容性, 修復 BUG、 新增次要功能特性等。
說明: 注意起始版本號必須為: 1.0.0,而不是 0.0.1, 正式發布的類庫必須先去中央倉庫進行查證,使版本號有延續性, 正式版本號不允許覆蓋升級。如當前版本: 1.3.3, 那么下一個合理的版本號: 1.3.4 或1.4.0 或 2.0.0
3. 【強制】 線上應用不要依賴 SNAPSHOT 版本( 安全包除外) 。
說明: 不依賴 SNAPSHOT 版本是保證應用發布的冪等性。另外,也可以加快編譯時的打包構建。
4. 【強制】 二方庫的新增或升級,保持除功能點之外的其它 jar 包仲裁結果不變。如果有改變,必須明確評估和驗證。
說明: 在升級時,進行 dependency:resolve 前后信息比對,如果仲裁結果完全不一致,那么通過dependency:tree 命令,找出差異點,進行<exclude>排除 jar 包。
5. 【強制】 二方庫里可以定義枚舉類型,參數可以使用枚舉類型,但是接口返回值不允許使用枚舉類型或者包含枚舉類型的 POJO 對象。
6. 【強制】 依賴于一個二方庫群時,必須定義一個統一的版本變量,避免版本號不一致。
說明: 依賴 springframework-core,-context,-beans,它們都是同一個版本,可以定義一個變量來保存版本: ${spring.version},定義依賴的時候,引用該版本。
7. 【強制】 禁止在子項目的 pom 依賴中出現相同的 GroupId,相同的 ArtifactId,但是不同的Version。
說明: 在本地調試時會使用各子項目指定的版本號,但是合并成一個 war,只能有一個版本號出現在最后的 lib 目錄中。 可能出現線下調試是正確的,發布到線上卻出故障的問題。
8. 【推薦】 底層基礎技術框架、核心數據管理平臺、或近硬件端系統謹慎引入第三方實現。
9. 【推薦】 所有 pom 文件中的依賴聲明放在<dependencies>語句塊中,所有版本仲裁放在<dependencyManagement>語句塊中。
說明: <dependencyManagement>里只是聲明版本,并不實現引入,因此子項目需要顯式的聲明依賴, version 和 scope 都讀取自父 pom。而<dependencies>所有聲明在主 pom 的<dependencies>里的依賴都會自動引入,并默認被所有的子項目繼承。
10.【推薦】 二方庫不要有配置項,最低限度不要再增加配置項。
11.【參考】 為避免應用二方庫的依賴沖突問題,二方庫發布者應當遵循以下原則:
1) 精簡可控原則。移除一切不必要的 API 和依賴,只包含 Service API、必要的領域模型對象、 Utils類、常量、枚舉等。如果依賴其它二方庫,盡量是 provided 引入,讓二方庫使用者去依賴具體版本號;無 log 具體實現,只依賴日志框架。
2) 穩定可追溯原則。每個版本的變化應該被記錄,二方庫由誰維護,源碼在哪里,都需要能方便查到。除非用戶主動升級版本,否則公共二方庫的行為不應該發生變化。
(三) 服務器
1. 【推薦】 高并發服務器建議調小 TCP 協議的 time_wait 超時時間。
說明: 操作系統默認 240 秒后,才會關閉處于 time_wait 狀態的連接,在高并發訪問下,服務器端會因為處于 time_wait 的連接數太多,可能無法建立新的連接,所以需要在服務器上調小此等待值。
正例: 在 linux 服務器上請通過變更/etc/sysctl.conf 文件去修改該缺省值(秒):net.ipv4.tcp_fin_timeout = 30
2. 【推薦】 調大服務器所支持的最大文件句柄數( File Descriptor,簡寫為 fd) 。
說明: 主流操作系統的設計是將 TCP/UDP 連接采用與文件一樣的方式去管理,即一個連接對應于一個fd。 主流的 linux 服務器默認所支持最大 fd 數量為 1024,當并發連接數很大時很容易因為 fd 不足而出現“open too many files” 錯誤,導致新的連接無法建立。 建議將 linux 服務器所支持的最大句柄數調高數倍(與服務器的內存數量相關) 。
3. 【推薦】 給 JVM 環境參數設置-XX:+HeapDumpOnOutOfMemoryError 參數,讓 JVM 碰到OOM 場景時輸出 dump 信息。
說明: OOM 的發生是有概率的,甚至相隔數月才出現一例,出錯時的堆內信息對解決問題非常有幫助。
4. 【推薦】 在線上生產環境, JVM 的 Xms 和 Xmx 設置一樣大小的內存容量, 避免在 GC 后調整堆大小帶來的壓力。
5. 【參考】 服務器內部重定向使用 forward; 外部重定向地址使用 URL 拼裝工具類來生成, 否則會帶來 URL 維護不一致的問題和潛在的安全風險。
七、 設計規約
1. 【強制】 存儲方案和底層數據結構的設計獲得評審一致通過,并沉淀成為文檔。
說明: 有缺陷的底層數據結構容易導致系統風險上升,可擴展性下降,重構成本也會因歷史數據遷移和系統平滑過渡而陡然增加,所以,存儲方案和數據結構需要認真地進行設計和評審,生產環境提交執行后,需要進行 double check。
正例: 評審內容包括存儲介質選型、表結構設計能否滿足技術方案、存取性能和存儲空間能否滿足業務發展、表或字段之間的辯證關系、字段名稱、字段類型、索引等;數據結構變更(如在原有表中新增字段)也需要進行評審通過后上線。
2. 【強制】 在需求分析階段,如果與系統交互的 User 超過一類并且相關的 User Case 超過 5個,使用用例圖來表達更加清晰的結構化需求。
3. 【強制】 如果某個業務對象的狀態超過 3 個,使用狀態圖來表達并且明確狀態變化的各個觸發條件。
說明: 狀態圖的核心是對象狀態,首先明確對象有多少種狀態,然后明確兩兩狀態之間是否存在直接轉換關系,再明確觸發狀態轉換的條件是什么。
正例: 淘寶訂單狀態有已下單、待付款、已付款、待發貨、已發貨、已收貨等。比如已下單與已收貨這兩種狀態之間是不可能有直接轉換關系的。
4. 【強制】 如果系統中某個功能的調用鏈路上的涉及對象超過 3 個,使用時序圖來表達并且明確各調用環節的輸入與輸出。
說明: 時序圖反映了一系列對象間的交互與協作關系,清晰立體地反映系統的調用縱深鏈路。
5. 【強制】 如果系統中模型類超過 5 個,并且存在復雜的依賴關系,使用類圖來表達并且明確類之間的關系。
說明: 類圖像建筑領域的施工圖,如果搭平房,可能不需要,但如果建造螞蟻 Z 空間大樓,肯定需要詳細的施工圖。
6. 【強制】 如果系統中超過 2 個對象之間存在協作關系,并且需要表示復雜的處理流程,使用活動圖來表示。
說明: 活動圖是流程圖的擴展,增加了能夠體現協作關系的對象泳道,支持表示并發等。
7. 【推薦】 需求分析與系統設計在考慮主干功能的同時,需要充分評估異常流程與業務邊界。
反例: 用戶在淘寶付款過程中,銀行扣款成功,發送給用戶扣款成功短信,但是支付寶入款時由于斷網演練產生異常,淘寶訂單頁面依然顯示未付款,導致用戶投訴。
8. 【推薦】 類在設計與實現時要符合單一原則。
說明: 單一原則最易理解卻是最難實現的一條規則,隨著系統演進,很多時候,忘記了類設計的初衷。
9. 【推薦】 謹慎使用繼承的方式來進行擴展,優先使用聚合/組合的方式來實現。
說明: 不得已使用繼承的話,必須符合里氏代換原則,此原則說父類能夠出現的地方子類一定能夠出現,比如, “把錢交出來” ,錢的子類美元、歐元、人民幣等都可以出現。
10.【推薦】 系統設計時,根據依賴倒置原則,盡量依賴抽象類與接口,有利于擴展與維護。
說明: 低層次模塊依賴于高層次模塊的抽象,方便系統間的解耦。
11.【推薦】 系統設計時,注意對擴展開放,對修改閉合。
說明: 極端情況下,交付線上生產環境的代碼都是不可修改的,同一業務域內的需求變化,通過模塊或類的擴展來實現。
12.【推薦】 系統設計階段,共性業務或公共行為抽取出來公共模塊、公共配置、公共類、公共方法等, 避免出現重復代碼或重復配置的情況。
說明: 隨著代碼的重復次數不斷增加,維護成本指數級上升。
13.【推薦】 避免如下誤解: 敏捷開發 = 講故事 + 編碼 + 發布。
說明: 敏捷開發是快速交付迭代可用的系統,省略多余的設計方案,摒棄傳統的審批流程,但核心關鍵點上的必要設計和文檔沉淀是需要的。
反例: 某團隊為了業務快速發展,敏捷成了產品經理催進度的借口, 系統中均是勉強能運行但像面條一樣的代碼, 可維護性和可擴展性極差,一年之后,不得不進行大規模重構,得不償失。
14.【參考】 系統設計主要目的是明確需求、理順邏輯、后期維護,次要目的用于指導編碼。
說明: 避免為了設計而設計,系統設計文檔有助于后期的系統維護和重構,所以設計結果需要進行分類歸檔保存。
15.【參考】 設計的本質就是識別和表達系統難點, 找到系統的變化點,并隔離變化點。
說明: 世間眾多設計模式目的是相同的, 即隔離系統變化點。
16.【參考】 系統架構設計的目的:
? 確定系統邊界。確定系統在技術層面上的做與不做。
? 確定系統內模塊之間的關系。確定模塊之間的依賴關系及模塊的宏觀輸入與輸出。
? 確定指導后續設計與演化的原則。使后續的子系統或模塊設計在規定的框架內繼續演化。
? 確定非功能性需求。非功能性需求是指安全性、可用性、可擴展性等。
17.【參考】 在做無障礙產品設計時,需要考慮到:
? 所有可交互的控件元素必須能被 tab 鍵聚焦,并且焦點順序需符合自然操作邏輯。
? 用于登陸校驗和請求攔截的驗證碼均需提供圖形驗證以外的其它方式。
? 自定義的控件類型需明確交互方式。
?
附 2: 專有名詞解釋
1. POJO( Plain Ordinary Java Object) : 在本手冊中, POJO 專指只有 setter / getter /toString 的簡單類,包括 DO/DTO/BO/VO 等。
2. GAV( GroupId、 ArtifactctId、 Version) : Maven 坐標,是用來唯一標識 jar 包。
3. OOP( Object Oriented Programming) : 本手冊泛指類、對象的編程處理方式。
4. ORM( Object Relation Mapping) : 對象關系映射,對象領域模型與底層數據之間的轉換,本文泛指 iBATIS, mybatis 等框架。
5. NPE( java.lang.NullPointerException) : 空指針異常。
6. SOA( Service-Oriented Architecture) : 面向服務架構,它可以根據需求通過網絡對松散耦合的粗粒度應用組件進行分布式部署、組合和使用, 有利于提升組件可重用性,可維護性。
7. IDE( Integrated Development Environment) : 用于提供程序開發環境的應用程序,一般包括代碼編輯器、編譯器、調試器和圖形用戶界面等工具, 本《手冊》 泛指 IntelliJ IDEA 和eclipse。
8. OOM( Out Of Memory) : 源于 java.lang.OutOfMemoryError, 當 JVM 沒有足夠的內存來為對象分配空間并且垃圾回收器也無法回收空間時, 系統出現的嚴重狀況。
9. 一方庫: 本工程內部子項目模塊依賴的庫( jar 包) 。
10.二方庫: 公司內部發布到中央倉庫,可供公司內部其它應用依賴的庫( jar 包) 。
11.三方庫: 公司之外的開源庫( jar 包) 。
?
?
總結
以上是生活随笔為你收集整理的熟读《阿里巴巴java开发手册》(六、工程结构,七、 设计规约,专有名词解释)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 熟读《阿里巴巴java开发手册》(五、
- 下一篇: mysql死锁场景汇总整理