作者:Anders小明
發(fā)表于Blogjava
(2007.12.14日補(bǔ)充更新了部分內(nèi)容,其中有關(guān)Web網(wǎng)站性能特點(diǎn)部分內(nèi)容來自網(wǎng)絡(luò))
一、什么是架構(gòu)
1. 和架構(gòu)相關(guān)的幾個(gè)問題域
架構(gòu)需要解決的非業(yè)務(wù)問題域包括如下:
A 系統(tǒng)目標(biāo):系統(tǒng)性能,穩(wěn)定性.
B.項(xiàng)目目標(biāo):開發(fā)成本,質(zhì)量
C.項(xiàng)目過程:需求的不確定性和開發(fā)過程的團(tuán)隊(duì)協(xié)作性
不同的問題域,解決之道也不相同!而同一問題域的不同層次的要求,解決之道也不盡相同。
2. 什么是架構(gòu)
架構(gòu)到底是啥,愚以為下面的這段英文描述的很清楚。
That's 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 isn't 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 don't know. What are you doing with the glove? Are you throwing snowballs, cooking barbeques, or playing golf? There's 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 it's probably a good architecture.
3. 架構(gòu)的背后
為了實(shí)現(xiàn)架構(gòu)的目標(biāo)涉及到以下三個(gè)方面:技術(shù),組織和過程。這里舉例說明。
1) 技術(shù)對開發(fā)效率和運(yùn)行性能,以及組織和過程的影響。
案例A.映射的問題。公司產(chǎn)品的一個(gè)重要需求是根據(jù)客戶輸入,映射到PDF文件上。技術(shù)上整體實(shí)現(xiàn)需要四個(gè)步驟:在PDF文件上畫好所有的數(shù)據(jù)域,通過讀入一個(gè)XML映射文件,獲得運(yùn)行數(shù)據(jù)并生成FDF,合并FDF和PDF生成目標(biāo)文件。后兩步工作都由代碼自動(dòng)化了,因而實(shí)現(xiàn)的主要工作在于前兩步。
在第一個(gè)實(shí)現(xiàn)版本里,XML映射文件的DTD太簡單,致使一個(gè)xml文件至少在4000行左右,同時(shí)xml文件太verbose了。這樣的結(jié)果直接導(dǎo)致運(yùn)行系統(tǒng)在峰值時(shí),由于XML消耗了大量內(nèi)存,1G的內(nèi)存根本吃不消;同時(shí)對XML解析執(zhí)行使用了CPU的大量時(shí)間;導(dǎo)致開發(fā)人員需要做大量的工作,開發(fā)效率降低了,通常需要盡一周才能完成一個(gè)xml文件,員工都不愿意做;也導(dǎo)致開發(fā)過程的漫長, 開發(fā)部門對于BA部門和ST部門的要求反應(yīng)變的緩慢。
在第二個(gè)版本的實(shí)現(xiàn)中,重新實(shí)現(xiàn)了DTD,加入了大量的關(guān)鍵字同時(shí)也消除了verbose,大量的縮小了XML大小,從4000多行減低到900多行。不僅減低了內(nèi)存使用,提高執(zhí)行效率;也提高了開發(fā)效率,基本只要一天就可以完成一個(gè)映射文件。同時(shí)對BA部門和ST部門的反應(yīng)也快了。
案例B:腳本的問題。產(chǎn)品在web層提供了腳本支持,出于方便開發(fā)的目的。但是沒有對腳本的環(huán)境限制,腳本可以做系統(tǒng)程序的大部分工作。導(dǎo)致開發(fā)人員偷懶,在web層混入了大量業(yè)務(wù)邏輯代碼。最終造成業(yè)務(wù)邏輯分散而不可控制。
2) 組織結(jié)構(gòu)對技術(shù),開發(fā)效率和應(yīng)變能力的影響。
案例A.部門的分工問題。開發(fā)部門根據(jù)不同的職責(zé),分成A,B和C等數(shù)個(gè)小組。大部分開發(fā)中互不相干。但也有時(shí)候,需要跨組的支持,比如B要實(shí)現(xiàn)某個(gè)需求,需要A在一定條件在記錄一個(gè)或多個(gè)信息。因?yàn)槊總€(gè)開發(fā)人員各自負(fù)責(zé)一部分工作,導(dǎo)致跨組溝通的困難。同時(shí)由于整個(gè)開發(fā)部采取任務(wù)績效,有時(shí)間壓力,加上只是一個(gè)小的要求。于是在A人員的同意下,B人員直接在A代碼中寫入業(yè)務(wù)邏輯。每次都是這樣的小改動(dòng),不斷的發(fā)展后,代碼開發(fā)變凌亂。
案例B.開發(fā)的歷史問題,當(dāng)某個(gè)開發(fā)人員寫下的代碼,有是問題的,接手開發(fā)人員由于文檔不全以及沒有測試用例,不愿意承擔(dān)變化的代價(jià),選擇小修小補(bǔ),這個(gè)小修小補(bǔ)有可能和有問題的代碼混雜,導(dǎo)致更大的代碼。
3) 過程對開發(fā)效率和應(yīng)變能力,以及組織的影響
案例A.過程的問題。開發(fā)部門的上下游部門BA部門和ST部門的合作關(guān)系。ST部門的績效考核,考核基于發(fā)現(xiàn)錯(cuò)誤的數(shù)量,導(dǎo)致ST為了完成任務(wù),提出一些非正常性要求。PM部門出于部門的方便通常提出一些實(shí)現(xiàn)難度比較大要求。開發(fā)部門本身又存在時(shí)間壓力,導(dǎo)致一些需求的實(shí)現(xiàn)本應(yīng)在低一層的代碼中實(shí)現(xiàn)的,卻在高層用蹩足的方式實(shí)現(xiàn)。
案例B.幫助系統(tǒng)的問題。幫助系統(tǒng)一開始采用一個(gè)個(gè)單獨(dú)分散的靜態(tài)頁面。出于性能的考慮和部門負(fù)責(zé)考慮。幫助系統(tǒng)不斷改進(jìn)中,過程缺乏組織性,文件的命名規(guī)則隨意,存儲(chǔ)位置隨意,造成了管理的混亂。直接的后果是頁面的入口混亂和各自引用關(guān)系混亂。
在幫助系統(tǒng)的第二版,從靜態(tài)頁面轉(zhuǎn)成動(dòng)態(tài)頁面。采取統(tǒng)一分類和命名規(guī)則,并統(tǒng)一了入口。同時(shí)采取分級管理引用關(guān)系,適度冗余。雖然減低了運(yùn)行性能。但提高了開發(fā)效率和可維護(hù)性。
二、架構(gòu)的性能問題解決討論
性能問題——嗯,一個(gè)非常神圣而高深的問題的。從我剛剛開始工作的時(shí)候,至今依然是。然而我相信,一定存在一個(gè)基本的思路和方法,我以為解決性能問題的工作還是在于分解,通過分解來確定問題域。
1. 性能調(diào)優(yōu)的關(guān)鍵
性能調(diào)優(yōu)的關(guān)鍵是:發(fā)現(xiàn)性能瓶頸所在,慢是相對概念,評價(jià)標(biāo)準(zhǔn)是符合不符合系統(tǒng)要求。調(diào)整同時(shí)需要考慮維護(hù)成本,因?yàn)榫S護(hù)成本通常是開發(fā)成本的3倍。
2. 性能調(diào)優(yōu)的公式
先介紹三個(gè)公式性能問題的公式:
總處理單量 = 總處理時(shí)間/ 單筆請求處理時(shí)間 * 總并發(fā)數(shù)
這個(gè)公式另一個(gè)寫法為:
總處理時(shí)間 = 單筆請求處理時(shí)間 * 總處理單量 / 總并發(fā)數(shù)
不同的寫法代表不同的關(guān)注點(diǎn),適合不同類型的業(yè)務(wù)類型, 一般說前一種寫法代表在線請求的,后一種寫法代表后臺(tái)batch;即高并發(fā)或大數(shù)據(jù)量問題.
也有客戶給明確要求系統(tǒng)要支持xxx并發(fā),這個(gè)就需要了解客戶的這個(gè)并發(fā)數(shù)是如何計(jì)算得來,需要通過分析客戶的業(yè)務(wù),而通常是根據(jù)總處理單量來確定客戶實(shí)際的并發(fā)數(shù)。
但無論如如何,四個(gè)變量中,總處理單量和總處理時(shí)間是先被確定的,換句話說需要關(guān)注是單筆請求處理時(shí)間和并發(fā)數(shù),也就是降低單筆請求處理時(shí)間或者增加并發(fā)數(shù)。
對于單筆請求處理時(shí)間,其公式為:
單筆請求處理時(shí)間 = 數(shù)據(jù)計(jì)算時(shí)間 + 數(shù)據(jù)讀寫時(shí)間+其它技術(shù)導(dǎo)致時(shí)間消耗
很顯然降低單筆請求處理時(shí)間就需要降低三個(gè)因素消耗的時(shí)間。
1.降低單筆請求處理時(shí)間
第一原則是, 只計(jì)算一次.緩存計(jì)算結(jié)果;
第二是,延遲部分計(jì)算(在不影響結(jié)果的情況下,將部分后續(xù)計(jì)算延后處理)
第三是,提前部分計(jì)算(例如對于年度的batch計(jì)算,可以在每個(gè)月都計(jì)算各自數(shù)據(jù),年底匯總即可)
2.降低數(shù)據(jù)讀取時(shí)間,分三種
2.1. Global的,系統(tǒng)啟動(dòng)時(shí)加載
2.2. Long Time, 可采用LRU方式cache
3.2. Per operation. 第一次訪問加載,operation結(jié)束后丟棄.
3.降低數(shù)據(jù)寫入時(shí)間
例如文件寫入通過buffer一次flush;對于SQL采用batch提交(hibernate的做法);對于同一張表數(shù)據(jù)只做一次更新;
4 .改進(jìn)計(jì)算時(shí)間,針對不同技術(shù)結(jié)構(gòu)采用不同手段。
4.1.讓計(jì)算支持并發(fā),提高性能,例如采用MapReduce的方式
4.2.改進(jìn)算法.例如數(shù)據(jù)庫中的SQL改進(jìn).
4.3.減少不必要計(jì)算時(shí)間.
5.減少其它技術(shù)原因?qū)е碌南?/span>
如JVM的GC導(dǎo)致性能消耗等
對于總并發(fā)數(shù),其公式為:
總并發(fā)數(shù) = 單機(jī)服務(wù)器并發(fā)能力 * 總并發(fā)服務(wù)器數(shù)
3. 確定改進(jìn)方案
那么如何確定那些因素需要調(diào)整呢,在于兩個(gè)方面的分解:
A. 業(yè)務(wù)層面
業(yè)務(wù)層面只是指通過業(yè)務(wù)行為分析, 把性能問題分解為不同的部分,每個(gè)部分面臨性能壓力現(xiàn)狀和目標(biāo),最終確定需要優(yōu)化的問題域.
業(yè)務(wù)層面分解包括4個(gè)內(nèi)容: 功能, 內(nèi)容,時(shí)間和區(qū)域.最重要的是前三個(gè).
以eBay為例, ebay對于前端功能劃分劃分為70多個(gè)功能,不同的服務(wù)器處理不同的功能.
內(nèi)容是指內(nèi)容熱點(diǎn),比如對于search來說,就按體育,數(shù)碼,音樂等劃分,不同內(nèi)容有不同熱點(diǎn)數(shù)據(jù),以及不同搜索關(guān)鍵匹配.
時(shí)間, 時(shí)間是一個(gè)非常重要的因素,在一些特定時(shí)間段,性能的要求會(huì)非常高.比如下半夜的訪問點(diǎn)擊量和白天的就有不同.對于一些batch來說, 月末或者年末處理的單量就有明顯的提高,比如分紅險(xiǎn)的記息,平時(shí)每天只有7000單,而年末會(huì)有12w單.
地點(diǎn)劃分,不太常見,不過也有助于分配計(jì)算資源.
業(yè)務(wù)層面的分析不僅是確定問題所在,還是確定優(yōu)化的策略.比如有一個(gè)batch計(jì)算,執(zhí)行時(shí)間比較長,而通過業(yè)務(wù)分析,發(fā)現(xiàn)該計(jì)算只針對特定的業(yè)務(wù), 系統(tǒng)全部有效單量是12w單,而符合計(jì)算要求的只有3000單,只要加上一個(gè)前置判斷就可以免除無謂的計(jì)算,運(yùn)行時(shí)間減少數(shù)個(gè)小時(shí)(大約0.2秒1單).
B. 技術(shù)層面
系統(tǒng)建立時(shí)技術(shù)結(jié)構(gòu),通常一個(gè)系統(tǒng)結(jié)構(gòu)如下:接入網(wǎng)絡(luò),Web服務(wù)器,應(yīng)用服務(wù)器,以及數(shù)據(jù)庫服務(wù)器.
在這樣結(jié)構(gòu)下,要小心的分析和驗(yàn)證系統(tǒng)性能的瓶頸,需要優(yōu)化Web服務(wù)器,或者提高數(shù)據(jù)庫并發(fā)能力等等。這部分網(wǎng)上的資料非常多。
采用并發(fā)立刻面臨一個(gè)問題,即負(fù)載均衡.負(fù)載均衡如果無法正常的工作,那么并發(fā)也就無法正確的工作.負(fù)載均衡可以靜態(tài)分布,也要?jiǎng)討B(tài)分布.這里面涉及的問題比較多.服務(wù)器自帶的負(fù)載均衡有時(shí)不能滿足業(yè)務(wù)上的需要,要自行開發(fā).
4. Web網(wǎng)站性能特點(diǎn)
互聯(lián)網(wǎng)網(wǎng)站的特點(diǎn)是交易少,事務(wù)短和并發(fā)高.對于網(wǎng)站這一特點(diǎn)需要做一番分解.網(wǎng)站的計(jì)算可以分解為:靜態(tài)內(nèi)容和動(dòng)態(tài)內(nèi)容,動(dòng)態(tài)內(nèi)容又可以分為狀態(tài)無關(guān)(stateless)和狀態(tài)有關(guān)(stateful).
靜態(tài)內(nèi)容通過負(fù)載均衡或者CDN就可以簡單做到.
動(dòng)態(tài)內(nèi)容特別是狀態(tài)有關(guān)的就復(fù)雜一點(diǎn).動(dòng)態(tài)內(nèi)容中涉及到兩大技術(shù):session和cache.
Session技術(shù)導(dǎo)致很多問題.負(fù)載均衡中導(dǎo)致session復(fù)制的難題.解決的方式是:1. 把所有的session數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫中,這樣通過增加數(shù)據(jù)庫的IO讀取,換取應(yīng)用服務(wù)器沒有任何session數(shù)據(jù)問題(另一種做法是把session數(shù)據(jù)放到cookie或者頁面hidden值中);2. 負(fù)載均衡采用Hash法,固定的把同一個(gè)請求綁定到同一臺(tái)服務(wù)器上,這樣通過犧牲一定的負(fù)載,換取應(yīng)用服務(wù)器的session數(shù)據(jù).
應(yīng)用session sticky,雖然避免了session的復(fù)制,但是依然面臨failover的問題.如果應(yīng)用程序在session中放入了domain object,在failover就容易出問題.一個(gè)解決方法是對session的set和get進(jìn)行攔截,發(fā)現(xiàn)是domain object就只在session中記錄ID+ClassName結(jié)構(gòu),而把對象放入cache中,failover時(shí)session中內(nèi)容簡單,就通過cache從數(shù)據(jù)庫加載.(SpringSide對于jBPM的擴(kuò)展采用相同策略)
Cache技術(shù)本事沒有特別的要說的,但它處在負(fù)載均衡環(huán)境中就會(huì)帶來問題:緩存數(shù)據(jù)失效(版本低).解決的問題有兩種:1. 獨(dú)立緩存+廣播通知.一旦數(shù)據(jù)更新后立刻廣播通知,這樣引發(fā)的問題是通知的管理.2. 采用中央緩存,如memcached技術(shù),代價(jià)是網(wǎng)絡(luò)讀寫.
Center Cache和Cluster Cache的特性比較如下:
Center Cache沒有同步問題,所以,remove/clear的時(shí)候,比較有優(yōu)勢,不需要把通知發(fā)送到好幾個(gè)計(jì)算機(jī)上。但是,Center Cache的所有操作,get/put/remove/clear都是Remote操作。而Cluster Cache的get/put都是Local操作,所以,Cluster Cache在get/put操作上具有優(yōu)勢。
Local get/put在關(guān)聯(lián)對象的組裝和分拆方面,優(yōu)勢比較明顯。 關(guān)聯(lián)對象的分拆是這個(gè)意思, 比如,有一個(gè)Topic對象,下面有幾個(gè)Post對象,每個(gè)Post對象都有一個(gè)User對象。 Topic對象存放到Cache中的時(shí)候,下面的關(guān)聯(lián)對象都要拆開來,分成各自的Entity Region來存放。
Topic Region -> Topic ID -> Topic Object
Post Region -> Post ID -> Post Object
User Region -> User ID -> User Object
這個(gè)時(shí)候,put的動(dòng)作可能發(fā)生多次。Remote Put的開銷就比較大。 Get的過程類似,也需要get多次,才能拼裝成一個(gè)完整的Topic對象。
三、架構(gòu)的開發(fā)成本以及品質(zhì)問題解決討論
架構(gòu)一個(gè)重要的關(guān)注點(diǎn)在于控制開發(fā)成本,這點(diǎn)很重要,因?yàn)橥ǔVv維護(hù)成本是開發(fā)成本的3倍。降低開發(fā)成本核心,在于提高效率,這也意味著提高了開發(fā)對需求的響應(yīng)時(shí)間,而時(shí)間對公司來說是重要的。
1. 問題域
問題域可分解為兩種類型,業(yè)務(wù)上和技術(shù)上。(又見分解,分而治之真是老祖宗傳下的靈丹妙藥啊)
1. 業(yè)務(wù)上。問題域分解為,邏輯的縱向抽象層次,以及邏輯的橫向模塊分解和集成。
2. 技術(shù)上。問題域分解為,縱向的技術(shù)主題,以及橫向的技術(shù)職責(zé)的分解和集成。
A. 領(lǐng)域基本問題
所以通常而言,領(lǐng)域模型設(shè)計(jì)中,模塊分解,抽象分層和職責(zé)分層都是重要手段。問題域?yàn)椋毫鞒蹋瑯I(yè)務(wù)實(shí)體和計(jì)算(包括規(guī)則)。
- 對象的抽象分解和集成
- 對象的依賴分解和集成(模塊內(nèi)和模塊外)
- 流程的分解和集成(頁面流,工作流以及計(jì)算流程)
- 進(jìn)程邊界:用戶請求重定向,以及業(yè)務(wù)數(shù)據(jù)持久化等。
B. 領(lǐng)域組件問題
面向?qū)ο笳Z言本身沒有提供的組件級別的依賴關(guān)系集成能力。語言不提供,因?yàn)轭I(lǐng)域組件的粒度太大,超越了語言的范疇。但我們可以通過框架提供,在Java體系中,目前已經(jīng)有一個(gè)較好的解決方案:OSGi(JSR291)。可以完美的解決組件服務(wù)依賴關(guān)系管理,包括熱替換。
同時(shí)另一個(gè)問題——邏輯分層的問題:保險(xiǎn)產(chǎn)品面臨的核心層,國家層以及公司層三個(gè)邏輯層次分解和集成能力。這點(diǎn)的解決方案可以通過OSGi + Spring來解決,包括了靜態(tài)差異性替換和動(dòng)態(tài)差異性替換。
還有組件邊界保護(hù)問題,我們希望限制別的組件訪問本組件內(nèi)部實(shí)現(xiàn),有兩種手段可以完成,1是提交部署時(shí),通過在代碼提交時(shí)的代碼檢查工具,或者發(fā)布時(shí)編譯工具完成;2是通過OSGi的邊界限制能力。
C. 邏輯替換問題
邏輯的替換根據(jù)開發(fā)方式不同,有兩種類型:基于接口和基于繼承;
A. 基于接口(包括了靜態(tài)替換和動(dòng)態(tài)替換)
1. 靜態(tài)替換是override,在OSGi中只要停止原有服務(wù),啟用新服務(wù)即可,而在Spring中更改相應(yīng)配置文件即可;
2. 動(dòng)態(tài)替換,其實(shí)是指運(yùn)行時(shí)Condition Service Locator,在OSGi中可以利用Extension Point(Plug-in)解決,而Spring中只要提供一個(gè)類似Service Locator就可以。
B. 基于繼承(或者靜態(tài)類)
1.開發(fā)時(shí),直接修改源代碼編譯;
2.編譯時(shí),采用AspectJ,在編譯時(shí)提供替換;
3.加載時(shí),開發(fā)一個(gè)新邏輯的同名類,但其加載路徑優(yōu)先于原有類;
2. 基本手段
提高開發(fā)效率和品質(zhì)的基本手段是分解——即充分的分離系統(tǒng)中不同的關(guān)注點(diǎn),好處不用說了,可以并發(fā)的工作,每個(gè)人面對的問題都簡單而容易操作。而與分解對應(yīng)的集成,只有提供了好的集成能力,分解才成為現(xiàn)實(shí),而只有分解了,才能清晰的提供業(yè)務(wù)更多適應(yīng)性。
分解和集成的手段分為編程語言和技術(shù)框架兩個(gè)層面。所謂語言就是強(qiáng)框架,而框架就是弱語言。
A. 語言
現(xiàn)代面向?qū)ο蟮恼Z言提供如下能力:抽象和派生能力,以及接口隔離能力。實(shí)際提供兩種分解和集成能力:
1. 把邏輯分解在兩個(gè)層次中,而通過繼承的方式把兩個(gè)部分集成在一起。
2. 把邏輯的外觀和實(shí)現(xiàn)分解在兩個(gè)地方,而通過接口實(shí)現(xiàn)的方式把兩部分集成在一起。
另一種語言AspectJ或者C#語言2.0之后提供的特性:把流程邏輯,分解在不同的地方,而通過簽名匹配,利用代碼生成的方式來把幾部分集成在一起。
B. 框架
然而語言提供的集成能力,畢竟底層,而且有限,擴(kuò)展起來也格外小心。因而技術(shù)框架提供另外的集成能力就格外重要:
1. 對象關(guān)聯(lián)關(guān)系的分解和集成,如Spring提供容器管理能力
2. 模塊間關(guān)聯(lián)關(guān)系的分解和集成,如OSGi,ESB等
3. 不同系統(tǒng)的類型分解和集成,如Spring利用動(dòng)態(tài)代理提供的Exporter模式。
4. 流程邏輯的分解和集成,如Spring Web Flow以及jBPM。
C. 設(shè)計(jì)
說起集成,就不得不提到一種類型的對象存在——VO對象。VO對象是為了集成而存在的;其意義是:1. 保護(hù)系統(tǒng)的信息邊界,提供一種結(jié)構(gòu)可以使其它系統(tǒng)或者組件通過編碼方式獲取系統(tǒng)內(nèi)信息的方式;2. 保護(hù)系統(tǒng)的事務(wù)邊界,領(lǐng)域?qū)ο蠹夹g(shù)上攜帶著持久化信息,通過VO可以屏蔽得以屏蔽。常見的VO對象存在于Web層和Domain層。
因此,VO對象的存在只是為了集成而存在,其是否存在的取決于框架的兩個(gè)方面:對象路徑訪問能力以及事務(wù)邊界管理。
Web層VO對象,以SWF為例,早在SWF 1.x時(shí)代,框架就提供了豐富的對象路徑訪問能力,但其Web交互是典型的MVC2方式,事務(wù)邊界在view的render前關(guān)閉,因而導(dǎo)致需要特定的VO對象來避免持久化信息問題;而SWF 2.x時(shí)代,view的render是在事務(wù)邊界內(nèi),VO不再需要。
Domain層VO對象,通常是用于不同領(lǐng)域組件間的交互,但隨著架構(gòu)的改進(jìn),集成代碼獨(dú)立存在而不再嵌入到組件內(nèi)部,組件的邊界問題保護(hù)不復(fù)存在;更進(jìn)一步的是,框架提供自動(dòng)化的接口適配映射能力的增強(qiáng)。因而VO對象也失去存在的意義。
BTW:通常語言作為架構(gòu)的基礎(chǔ)引入和更換是有巨大風(fēng)險(xiǎn)的;而通過提供強(qiáng)大的框架能力,框架盡可能多的完成技術(shù)問題,并通過元數(shù)據(jù),模式以及約定降低業(yè)務(wù)和框架的耦合。避免因?yàn)榭蚣苌墡聿槐匾某杀尽?/span>
3. 其它手段
從技術(shù)手段上,提高開發(fā)效率的另外兩個(gè)手段是代碼生成和類庫引用。但代碼生成和類庫引用,都只解決了邏輯的分解能力,沒有提供集成能力,所以一般情況下需要提供框架集成,尤其代碼生成需要在系統(tǒng)的最外層,避免集成帶來的問題。
4. 學(xué)習(xí)成本
對于開發(fā)團(tuán)隊(duì)來說,額外面臨一個(gè)問題,組織內(nèi)部的學(xué)習(xí)成本問題。
1. 需要保持分解以及集成能力本身的簡約性
這個(gè)……其實(shí)是一個(gè)culture問題,不再羅唆!
2. 采用模式和約定是減少學(xué)習(xí)成本的另一種手段。ROR的興起就是最好的例證。
成本還表現(xiàn)在組織的劃分上,應(yīng)用開發(fā)/框架開發(fā),而在每個(gè)層面又劃分為橫向模塊劃分。
總結(jié)一下,解決架構(gòu)面臨開發(fā)成本問題需要如下幾個(gè)方面:
0. 問題域
1. 分解與分層
2. 架構(gòu)與類庫,Spring,Hibernate。起支撐性作用。
3. 模式和技巧
4. 領(lǐng)域模型
5. 方法論
5.1.開發(fā)方法:OO(設(shè)計(jì)模式),FP(函數(shù)式編程)。
5.2.設(shè)計(jì)方法:Domain Model Prototype和業(yè)務(wù)行為的分析模式。
5. 質(zhì)量問題
架構(gòu)面臨的品質(zhì)問題,則通過自動(dòng)化測試,代碼檢測工具來完成。
必須大量應(yīng)用自動(dòng)化測試,減少人工硬調(diào)試的復(fù)雜性,重復(fù)性和不確定性。
自動(dòng)化測試包括單元測試和集成測試。無論是單元測試還是集成測試對面臨需要脫離隔離依賴關(guān)系并保證開發(fā)的并行性。
單元測試面臨的項(xiàng)目執(zhí)行問題:
5.1. 設(shè)計(jì)的粒度問題。設(shè)計(jì)的粒度大小將直接決定單元測試的難易程度。開發(fā)分工如果是設(shè)計(jì)和開發(fā)兩種角色集一體的,問題自我消化;但如果是分開,就會(huì)帶來一些分工認(rèn)識問題。
5.2. 遺留系統(tǒng)風(fēng)險(xiǎn)。遺留系統(tǒng)通常依賴關(guān)系復(fù)雜,設(shè)計(jì)結(jié)構(gòu)以及粒度也不好,同時(shí)缺乏既有測試用例。在遺留系統(tǒng)維護(hù)成本很高,為了滿足測試用例,通常需要對遺留系統(tǒng)重構(gòu),風(fēng)險(xiǎn)很高。
5.3. 測試用例評估與考核。測試用例不是越多越好,通常系統(tǒng)重構(gòu)也會(huì)導(dǎo)致一些測試用例被拋棄,過多非核心用例反而是在重構(gòu)中帶來成本。因此對于測試用例進(jìn)行評估成為一種必要,評估的標(biāo)準(zhǔn)較難確定。
5.4. 工作量評估。寫測試用例技術(shù)上并非難題,但不代表沒有工作量。如果評估工作量也是一個(gè)問題。
5.5. 測試用例的簡易度。雖然技術(shù)上非難題,但是業(yè)務(wù)開發(fā)面臨的種種問題,還是需要項(xiàng)目做一定的封裝,以便提高測試用例的開發(fā)和運(yùn)行的效率。
以上幾點(diǎn)都是直接影響項(xiàng)目的進(jìn)度,因此如果不能有效處理好,很難說服項(xiàng)目經(jīng)理在項(xiàng)目計(jì)劃中執(zhí)行單元測試。
6. 文檔的思考
6.1. 文檔的分類
架構(gòu)文檔,high level設(shè)計(jì)文檔和detail設(shè)計(jì)文檔
6.2. Detail設(shè)計(jì)文檔面臨的問題
A. 維護(hù)成本高。開發(fā)過程中設(shè)計(jì)到的具體而維的細(xì)節(jié)變化較頻繁,導(dǎo)致維護(hù)成本偏高;而開發(fā)成本和維護(hù)成本1:3的比例,導(dǎo)致這些文檔在后期維護(hù)的成本也很高;
B. 驗(yàn)收成本高。目前缺乏自動(dòng)化的驗(yàn)收工作;ST是黑盒測試,驗(yàn)收的是系統(tǒng),而非文檔;獨(dú)立驗(yàn)收人員的學(xué)習(xí)曲線太高;而開發(fā)人員自我驗(yàn)收的效果不好,即便是交叉驗(yàn)收也容易達(dá)成私下協(xié)議;
C. 收益低。文檔的維護(hù)人員,工作缺乏成就感;這些文檔的閱讀者通常是IT人員,使用代碼閱讀無疑具有更好的閱讀效果;