一什麼是架構
和架構相關的幾個問題域
架構需要解決的非業務問題域包括如下
A 系統目標系統性能穩定性
B項目目標開發成本質量
C項目過程需求的不確定性和開發過程的團隊協作性
不同的問題域解決之道也不相同!而同一問題域的不同層次的要求解決之道也不盡相同
什麼是架構
架構到底是啥愚以為下面的這段英文描述的很清楚
Thats like asking what is culture? Culture is the way you do things in a group of people Architecture is the way you do things in a software product You could argue by analogy then that architecture is to a software product as culture is to a team It is how that team has established and chosen its conventions
Which leads us inevitably to the question of goodness? How do you know if an architecture is good? Consider an architecture that isnt built using a strong domain model and instead relies heavily on stored procedures That might be OK or it might not be OK You could have decided that part of your architecture is to use a really strong domain model and not use stored procedures right? So an architecture is some reasonable regularity about the structure of the system the way the team goes about building its software and how the software responds and adapts to its own environment How well the architecture responds and adapts and how well it goes through that construction process is a measure of whether that architecture is any good
The system architecture determines how hard or easy it is to implement a given feature Good architectures are those in which it is considered easy to create the features desired In that the way to judge whether an architecture is good is whether the architecture is good for the purposes to which it is applied
The definition of goodness has to be related to fitness for purpose Is this glove good? I dont know What are you doing with the glove? Are you throwing snowballs cooking barbeques or playing golf? Theres a set of changes that are going to occur to a software system over time Probably the utilitarian or most useful definition of goodness is the answer to this question: are the changes that will keep this system successful in this domain in this product line relatively easy? If they are then its probably a good architecture
架構的背後
為了實現架構的目標涉及到以下三個方面技術組織和過程這裡舉例說明
) 技術對開發效率和運行性能以及組織和過程的影響
案例A.映射的問題公司產品的一個重要需求是根據客戶輸入映射到PDF文件上技術上整體實現需要四個步驟在PDF文件上畫好所有的數據域通過讀入一個XML映射文件獲得運行數據並生成FDF合並FDF和PDF生成目標文件後兩步工作都由代碼自動化了因而實現的主要工作在於前兩步
在第一個實現版本裡XML映射文件的DTD太簡單致使一個xml文件至少在行左右同時xml文件太verbose了這樣的結果直接導致運行系統在峰值時由於XML消耗了大量內存G的內存根本吃不消同時對XML解析執行使用了CPU的大量時間導致開發人員需要做大量的工作開發效率降低了通常需要盡一周才能完成一個xml文件員工都不願意做也導致開發過程的漫長 開發部門對於BA部門和ST部門的要求反應變的緩慢
在第二個版本的實現中重新實現了DTD加入了大量的關鍵字同時也消除了verbose大量的縮小了XML大小從多行減低到多行不僅減低了內存使用提高執行效率也提高了開發效率基本只要一天就可以完成一個映射文件同時對BA部門和ST部門的反應也快了
案例B腳本的問題產品在web層提供了腳本支持出於方便開發的目的但是沒有對腳本的環境限制腳本可以做系統程序的大部分工作導致開發人員偷懶在web層混入了大量業務邏輯代碼最終造成業務邏輯分散而不可控制
) 組織結構對技術開發效率和應變能力的影響
案例A部門的分工問題開發部門根據不同的職責分成AB和C等數個小組大部分開發中互不相干但也有時候需要跨組的支持比如B要實現某個需求需要A在一定條件在記錄一個或多個信息因為每個開發人員各自負責一部分工作導致跨組溝通的困難同時由於整個開發部采取任務績效有時間壓力加上只是一個小的要求於是在A人員的同意下B人員直接在A代碼中寫入業務邏輯每次都是這樣的小改動不斷的發展後代碼開發變凌亂
案例B開發的歷史問題當某個開發人員寫下的代碼有是問題的接手開發人員由於文檔不全以及沒有測試用例不願意承擔變化的代價選擇小修小補這個小修小補有可能和有問題的代碼混雜導致更大的代碼
) 過程對開發效率和應變能力以及組織的影響
案例A過程的問題開發部門的上下游部門BA部門和ST部門的合作關系ST部門的績效考核考核基於發現錯誤的數量導致ST為了完成任務提出一些非正常性要求PM部門出於部門的方便通常提出一些實現難度比較大要求開發部門本身又存在時間壓力導致一些需求的實現本應在低一層的代碼中實現的卻在高層用蹩足的方式實現
案例B幫助系統的問題幫助系統一開始采用一個個單獨分散的靜態頁面出於性能的考慮和部門負責考慮幫助系統不斷改進中過程缺乏組織性文件的命名規則隨意存儲位置隨意造成了管理的混亂直接的後果是頁面的入口混亂和各自引用關系混亂
在幫助系統的第二版從靜態頁面轉成動態頁面采取統一分類和命名規則並統一了入口同時采取分級管理引用關系適度冗余雖然減低了運行性能但提高了開發效率和可維護性
二架構的性能問題解決討論
性能問題——嗯一個非常神聖而高深的問題的從我剛剛開始工作的時候至今依然是然而我相信一定存在一個基本的思路和方法我以為解決性能問題的工作還是在於分解通過分解來確定問題域
先介紹三個公式性能問題的公式:
總處理單量 = 總處理時間/ 單筆請求處理時間 * 總並發數
這個公式另一個寫法為:
總處理時間 = 單筆請求處理時間 * 總處理單量 / 總並發數
不同的寫法代表不同個關注點適合不同類型的業務類型 一般說前一種寫法代表在線請求的後一種寫法代表後台batch
也有客戶給明確要求系統要支持xxx並發這個就需要了解客戶的這個並發數是如何計算得來需要通過分析客戶的業務而通常是根據總處理單量來確定客戶實際的並發數
但無論如如何四個變量中總處理單量和總處理時間是先被確定的換句話說需要關注是單筆請求處理時間和並發數也就是降低單筆請求處理時間或者增加並發數
對於單筆請求處理時間其公式為
單筆請求處理時間 = 數據計算時間 + 數據讀寫時間+其它技術導致時間消耗
很顯然降低單筆請求處理時間就需要降低三個因素消耗的時間
降低單筆請求處理時間第一原則是 只計算一次緩存計算結果
降低數據讀取時間分三種
Global的系統啟動時加載
Long Time 可采用LRU方式cache
Per operation 第一次訪問加載operation結束後丟棄
降低數據寫入時間
例如文件寫入通過buffer一次flush對於SQL采用batch提交(hibernate的做法)
改進計算時間針對不同技術結構采用不同手段
讓計算支持並發提高性能例如采用MapReduce的方式
改進算法例如數據庫中的SQL改進
減少不必要計算時間
減少其它技術原因導致的消耗
如JVM的GC導致性能消耗等
對於總並發數其公式為總並發數 = 單機服務器並發能力 * 總並發服務器數
那麼如何確定那些因素需要調整呢在於兩個方面的分解
業務層面
業務層面只是指通過業務行為分析 把性能問題分解為不同的部分每個部分面臨性能壓力現狀和目標最終確定需要優化的問題域
業務層面分解包括個內容: 功能 內容時間和區域最重要的是前三個
以ebay為例 ebay對於前端功能劃分劃分為多個功能不同的服務器處理不同的功能
內容是指內容熱點比如對於search來說就按體育數碼音樂等劃分不同內容有不同熱點數據以及不同搜索關鍵匹配
時間 時間是一個非常重要的因素在一些特點是時間段呢性能的要求會非常高比如下半夜的訪問點擊量和白天的就有不同對於一些batch來說 月末或者年末處理的單量就有明顯的提高比如分紅險的記息平時每天只有單而年末會有w單
地點劃分不太常見不過也有助於分配計算資源
業務層面的分析不僅是確定問題所在還是確定優化的策略比如有一個batch計算執行時間比較長而通過業務分析發現該計算只針對特定的業務 系統全部有效單量是w單而符合計算要求的只有單只要加上一個前置判斷就可以免除無謂的計算運行時間減少數個小時(大約秒一單)
技術層面
系統建立時技術結構通常一個系統結構如下:接入網絡Web服務器應用服務器以及數據庫服務器
在這樣結構下要小心的分析和驗證系統性能的瓶頸需要優化Web服務器或者提高數據庫並發能力等等這部分網上的資料非常多
三架構的開發成本以及品質問題解決討論
架構一個重大關注點在於控制開發成本這點很重要因為通常講維護成本是開發成本的倍降低開發成本核心在於提高效率這也意味著提高了開發對需求的響應時間而時間對公司來說是重要的
提高開發效率和品質的基本手段是分解——即充分的分離系統中不同的關注點好處不用說了可以並發的工作每個人面對的問題都簡單而容易操作而與分解對應的集成只有提供了好的集成能力分解才成為現實而只有分解了才能清晰的提供業務更多適應性
分解和集成的手段分為編程語言和技術框架兩個層面所謂語言就是強框架而框架就是弱語言
現代面向對象的語言提供如下能力抽象和派生能力以及接口隔離能力實際提供兩種分解和集成能力
把邏輯分解在兩個層次中而通過繼承的方式把兩個部分集成在一起
把邏輯的外觀和實現分解在兩個地方而通過接口實現的方式把兩部分集成在一起
另一種語言AspectJ或者C#語言之後提供的特性把流程邏輯分解在不同的地方而通過簽名匹配利用代碼生成的方式來把幾部分集成在一起
然而語言提供的集成能力畢竟底層而且有限擴展起來也格外小心因而技術框架提供另外的集成能力就格外重要
對象關聯關系的分解和集成如Spring提供容器管理能力
模塊間關聯關系的分解和集成如OSGiESB等
不同系統的類型分解和集成如Spring利用動態代理提供的Exporter模式
流程邏輯的分解和集成如Spring Web Flow以及jBPM
討論完手段現在要轉身看看我們面臨的問題域了問題域可分解為兩種類型業務上和技術上(又見分解分而治之真是老祖宗傳下的靈丹妙藥啊)
業務上問題域分解為邏輯的縱向抽象層次以及邏輯的橫向模塊分解和集成
技術上問題域分解為縱向的技術主題以及橫向的技術職責的分解和集成
所以通常而言領域模型設計中模塊分解抽象分層和職責分層都是重要手段問題域為流程業務實體和計算(包括規則)
對象的抽象分解和集成
對象的依賴分解和集成(模塊內和模塊外)
流程的分解和集成(頁面流工作流以及計算流程)
進程邊界用戶請求重定向以及業務數據持久化等
BTW通常語言做為架構的基礎引入和更換是有巨大風險的而通過提供強大的框架能力框架盡可能多的完成技術問題並通過元數據模式以及約定降低業務和框架的耦合避免因為框架升級帶來不必要的成本
從技術手段上提高開發效率的另外兩個手段是代碼生成和類庫引用但代碼生成和類庫引用都只解決了邏輯的分解能力沒有提供集成能力所以一般情況下需要提供框架集成尤其代碼生成需要在系統的最外層避免集成帶來的問題
對於開發團隊來說額外面臨一個問題組織內部的學習成本問題
需要保持分解以及集成能力本身的簡約性
這個……其實是一個culture問題不再羅唆!
采用模式和約定是減少學習成本的另一種手段ROR的興起就是最好的例證
總結一下解決架構面臨開發成本問題需要如下幾個方面
問題域
分解與分層
架構與類庫SpringHibernate起支撐性作用
模式和技巧
領域模型
方法論
開發方法OO(設計模式)FP(函數式編程)
設計方法Domain Model Prototype和業務行為的分析模式
架構面臨的品質問題則通過自動化測試代碼檢測工具來完成
必須大量應用自動化測試減少人工硬調試的復雜性重復性和不確定性
自動化測試包括單元測試和集成測試無論是單元測試還是集成測試對面臨需要脫離隔離依賴關系並保證開發的並行性
From:http://tw.wingwit.com/Article/program/net/201311/15671.html