乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      應(yīng)用程序框架設(shè)計(jì)之二:分層和層間數(shù)據(jù)傳遞(上)

       rookie 2012-08-20

      還 記得97年左右開始的胖客戶機(jī)和瘦客戶機(jī)之爭(zhēng)嗎?之后又是CS和BS之爭(zhēng),然后又是兩層和多層之爭(zhēng)...,十年之后的今天我們?cè)倩剡^(guò)頭看這些爭(zhēng)論,一切似 乎看起來(lái)都那么理所應(yīng)當(dāng):程序怎么能不分層???可是再想一下,原來(lái)我們用了整整十年的時(shí)間才達(dá)成了一個(gè)程序架構(gòu)要多層的共識(shí)(效率多低?。?!

      要分層,當(dāng)然基本就是三層了,其實(shí)多層的基礎(chǔ)也是三層:界面層、業(yè)務(wù)邏輯層、存儲(chǔ)層。多層只不過(guò)在三層的基礎(chǔ)上把每一層或多或少再拆分出一些來(lái)而已,總的來(lái)說(shuō)沒有什么大的變化。本系列文章中討論都以三層為基本概念。

      本 文著重討論的不是如何分層和層的定義,而是在分層情況下,討論層與層之間的數(shù)據(jù)傳遞問(wèn)題。現(xiàn)在的程序很少仔細(xì)地去分析層與層之間的數(shù)據(jù)傳遞問(wèn)題,通常都是 一個(gè)對(duì)象從界面生成開始一路穿過(guò),直接保存到數(shù)據(jù)庫(kù)(最顯著的標(biāo)志當(dāng)然就是xxxID了)。這樣的做法對(duì)程序傷害很大。

      首先我們從一個(gè)簡(jiǎn)單的例子開始:應(yīng)用程序的添加用戶功能。界面很簡(jiǎn)單,如下:

       

      添加用戶

       

      要 為這個(gè)界面設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu)通常也很簡(jiǎn)單,class LoginInfo{ public String name; public String password; } 就好了,然后我們?cè)趂orm提交的時(shí)候new一個(gè)并且填充好LoginInfo結(jié)構(gòu),就save(loginInfo)到數(shù)據(jù)庫(kù)里邊了,最常的做法還會(huì)加 入一個(gè)int loginInfoID字段。我們把這種類似LoginInfo可以直接存儲(chǔ)到數(shù)據(jù)庫(kù)中的數(shù)據(jù)結(jié)構(gòu)命名為Persistence Object,簡(jiǎn)稱PO。嗯,看起來(lái)從頭到腳用一個(gè)數(shù)據(jù)結(jié)構(gòu)并沒有什么問(wèn)題啊!

      問(wèn)題會(huì)來(lái)的,bigtall來(lái)改變一下需求,通常我們需要給用戶密碼輸入兩次,所以界面修改如下:

      添加用戶


      這 樣,form提交到服務(wù)器的數(shù)據(jù)結(jié)構(gòu)就應(yīng)該是這樣:class LoginInfo2{ public String name; public String password; public String password2; },然后服務(wù)器做的第一件事情就是比較password和password2是否相等,然后new一個(gè)LoginInfo結(jié)構(gòu),把name和 password填充到里邊,然后保存到數(shù)據(jù)庫(kù)。我們同時(shí)把LoginInfo結(jié)構(gòu)修改成這樣class LoginInfo{ public int loginInfoID; public String name; public String password; } 。

      大家可以看到,隨著需求的變化,原來(lái)的“PO直通車”演化成了兩個(gè)結(jié)構(gòu),我們把LoginInfo2類似的界面層和其它層溝通的數(shù)據(jù)結(jié)構(gòu)叫做View Object,簡(jiǎn)稱VO。是不是這樣就夠了?當(dāng)然不是,我們?cè)賮?lái)修改一下需求,給系統(tǒng)加入權(quán)限功能,所以這個(gè)添加用戶實(shí)際上應(yīng)該修改成這樣:

      添加用戶



      我們需要繼續(xù)做一些改進(jìn)(或者叫做“重構(gòu)”吧),首先修改VO,同時(shí)我們把命名也規(guī)范一下:

      class LoginInfoVO{public String name; public String password; public String password2; public String[] roles;},

      然后把以前的LoginInfo拆分成三個(gè)類:

      class LoginInfoBO{public String name; public String password; public RoleInfo[] roles;}

      class LoginInfoPO{public int loginInfoID; public String name; public String password;}

      class RoleInfoPO{public int loginInfoID; public String role;}。

      至此,我們順利地引出了三個(gè)概念:View Object(VO)、Business Object(BO)、Persistence Object(PO)。 他們分別是三層結(jié)構(gòu)的顯示層、業(yè)務(wù)邏輯層和存儲(chǔ)層內(nèi)部使用的數(shù)據(jù)結(jié)構(gòu),它們還有一個(gè)統(tǒng)稱,叫做數(shù)據(jù)傳輸對(duì)象Data Object(DO)。我們也可以把VO,BO和PO看成是DO在不同階段的不同表示形態(tài)。當(dāng)一個(gè)DO從顯示層開始穿越整個(gè)系統(tǒng)的時(shí)候,它的形態(tài)和結(jié)構(gòu)就 開始變化,從VO轉(zhuǎn)變到BO,最終到PO,但是這個(gè)過(guò)程不一定是可逆的,這個(gè)過(guò)程如果反向,從PO->BO->VO,很可能就對(duì)應(yīng)不同的對(duì)象 了。比如當(dāng)輸入錯(cuò)誤的時(shí)候,回饋?lái)?yè)面可能就需要增加一個(gè)錯(cuò)誤信息提示。雖然實(shí)際使用的時(shí)候,我們經(jīng)常會(huì)忽略這種細(xì)微的差異性,實(shí)際上這個(gè)錯(cuò)誤信息,只對(duì)顯 示層有意義。

      DO的轉(zhuǎn)換規(guī)律一般可以總結(jié)為如下的幾個(gè)類型,實(shí)際變化則可以是各種類型的組合:

      • 屬性內(nèi)容的減少

      屬 性內(nèi)容的增減在DO不同形態(tài)之間的轉(zhuǎn)變時(shí)候經(jīng)常會(huì)發(fā)生。比如上例中添加用戶LoginInfo對(duì)象的VO轉(zhuǎn)換到BO的時(shí)候,就需要丟棄“重復(fù)輸入密碼”的 屬性。有些VO對(duì)象甚至根本不需要轉(zhuǎn)換成BO。在BO轉(zhuǎn)換成PO的時(shí)候同樣也會(huì)有屬性內(nèi)容減少的情況出現(xiàn),比如“部門”這類樹狀層次結(jié)構(gòu)對(duì)象,因?yàn)檫\(yùn)行效 率的因素,也許會(huì)需要BO中有“下級(jí)部門列表”,實(shí)際存儲(chǔ)到數(shù)據(jù)庫(kù)的時(shí)候,PO只需要一個(gè)“上級(jí)部門ID”就可以了。

      • 對(duì)象內(nèi)容的填充或者增加

      屬 性內(nèi)容同樣會(huì)有可能增加,但是在系統(tǒng)處理DO轉(zhuǎn)換的時(shí)候,屬性增加可能就意味著需要進(jìn)行額外的查詢和填充,比如我們使用“用戶名”和“密碼”進(jìn)行登錄的時(shí) 候,最終系統(tǒng)需要通過(guò)數(shù)據(jù)庫(kù)查詢得到并且存儲(chǔ)“用戶ID”,以此來(lái)保證用戶的唯一性。又比如提交的數(shù)據(jù)存在校驗(yàn)錯(cuò)誤,我們可能需要重新刷新該頁(yè)面,并且增 加新屬性“ErrorMessage”,以便把它顯示在界面上,提醒用戶注意。

      • 對(duì)象的拆分和組合

      我們可以看上面最后一個(gè)“添加用戶”的例子,一個(gè)LoginInfo的BO轉(zhuǎn)化為PO的時(shí)候被拆分成了2個(gè)對(duì)象,一個(gè)存放基本的用戶信息,一個(gè)存放對(duì)應(yīng)的Role信息。通常對(duì)象拆分的時(shí)候,常常需要填充或者補(bǔ)足新對(duì)象的內(nèi)容;而對(duì)象合并的時(shí)候,常常出現(xiàn)內(nèi)容減少的情況。

      • 對(duì)象或者屬性類型的變化

      出現(xiàn)對(duì)象屬性類型的變化在VO到BO的轉(zhuǎn)換中比較常見,比如把用戶輸入的生日轉(zhuǎn)化為一個(gè)真正的DateTime類型。

      • 屬性名稱的變化

      屬性名稱在轉(zhuǎn)換過(guò)程中會(huì)有變化,一般這種情況應(yīng)該盡可能不要出現(xiàn),但是在項(xiàng)目重構(gòu)的時(shí)候出現(xiàn)的概率較大。

      除了DO不同形態(tài)之間的轉(zhuǎn)換規(guī)律之外,不同形態(tài)內(nèi)部還有不同的工作要做:

      • 校驗(yàn)

      “不 要相信任何用戶的輸入”,這是設(shè)計(jì)程序跟用戶進(jìn)行交互操作時(shí)候永遠(yuǎn)需要遵守的一個(gè)原則。也就是所有的外部輸入都需要進(jìn)行正確性的校驗(yàn)。校驗(yàn)器是分為兩個(gè)層 次,一個(gè)是屬性層次的校驗(yàn),比如“年齡”只能0到150之間有效。另外一個(gè)是對(duì)象層次的校驗(yàn),或者說(shuō)跨屬性層次的校驗(yàn),比如“年份輸入閏年的時(shí)候,2月可 以有29日”等。

      校驗(yàn)并不是一個(gè)單純的問(wèn)題,幾乎所有的業(yè)務(wù)邏輯校驗(yàn)基本都需要一次完整的貫穿所有層次的調(diào)用。代價(jià)頗大。這個(gè)也是為什么我們?cè)陲@示層做很多事先校驗(yàn),而一旦進(jìn)入業(yè)務(wù)邏輯層的時(shí)候,校驗(yàn)就經(jīng)常會(huì)被“事后校驗(yàn)”代替了,人們會(huì)使用拋出異常的方法來(lái)代替“事前檢查”。

      突 然想起來(lái)有一句閑話要講。這個(gè)分析過(guò)程其實(shí)在一年前就完成了,那個(gè)時(shí)候正好沸沸揚(yáng)揚(yáng)的SOA滿天飛,當(dāng)把這個(gè)DO形態(tài)分析完畢之后,回頭看SOA發(fā)現(xiàn)它并 不屬于表現(xiàn)層,而是屬于業(yè)務(wù)邏輯層,換句話說(shuō)它使用的DO必須是BO而不是VO。而所謂的SOA也不過(guò)就是分布的業(yè)務(wù)邏輯層而已。

      因?yàn)橐韵碌牟糠忠ㄙM(fèi)較多的時(shí)間查找,bigtall怕文章擱久餿了,也怕各位看官等得太久,就分兩部分發(fā)吧。下篇我們著重分析現(xiàn)net平臺(tái)和java平臺(tái)的幾個(gè)架構(gòu)在DO形態(tài)上的對(duì)比,還要談一個(gè)實(shí)用的問(wèn)題,是不是需要對(duì)象ID的問(wèn)題。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多