|
前言:
本篇之所以稱為草稿設(shè)計(jì),是因?yàn)樵O(shè)計(jì)的都是在紙上完成的。反映了一個(gè)思考的過程。
本篇的議題如下:
1) 第一個(gè)數(shù)據(jù)層草圖的提出
2) 對(duì)數(shù)據(jù)訪問層的思考
3) 第二個(gè)數(shù)據(jù)層草圖的提出
1.數(shù)據(jù)層草圖的提出
Richard開始著手設(shè)計(jì),一開始他沒有就立刻在自己的計(jì)算機(jī)開始敲代碼。而且采用筆+紙開始構(gòu)思。
因?yàn)樗J(rèn)為:寫程序不是什么時(shí)候都得上機(jī),腦子里面想什么的才是最重要的,往往很多時(shí)候,在設(shè)計(jì)程序時(shí),首先在頭腦中就已經(jīng)把整個(gè)功能已經(jīng)實(shí)現(xiàn)了,甚至代碼的詳細(xì)編寫都已經(jīng)在頭腦中走了一遍,并且在頭腦中運(yùn)行,調(diào)試了。
開始設(shè)計(jì)了,因?yàn)檫@次Richard想要提出一個(gè)比較好的架構(gòu),一個(gè)比較強(qiáng)大的企業(yè)級(jí)的架構(gòu),所以參看成功的一些案例是很有必要,Richard也想到了微軟best practice的那些推薦的架構(gòu)組織方式和建議(大家對(duì)best practice不熟悉也要緊,不會(huì)影響閱讀)。
之后,Richard的第一個(gè)草圖就出來了:
一個(gè)架構(gòu)組織方式的提出,不是隨隨便便就提出的,新的架構(gòu)的設(shè)計(jì)和提出首先必須要明白你要解決哪些問題,而且也不要過度設(shè)計(jì)。(這個(gè)過程很難,很多時(shí)候需要權(quán)衡,所以作為架構(gòu)的設(shè)計(jì)者,權(quán)衡的思想很重要:在時(shí)間,資源,資金等都要考慮)。可能在起初會(huì)參看一些別的設(shè)計(jì)架構(gòu),甚至是模仿它們,但是隨著思考的深入,那些表象的東西就會(huì)逐漸的被拋除。
同時(shí)也開始設(shè)計(jì)的時(shí)候,沒有說一定要立刻就要設(shè)計(jì)出一個(gè)很強(qiáng)大的東西出來,對(duì)架構(gòu)設(shè)計(jì)的能力也是在慢慢的演化和思考過程中提升的。
2. 對(duì)數(shù)據(jù)訪問層的思考
在解釋為什么架構(gòu)要像上面那副圖進(jìn)行設(shè)計(jì)之前,我們首先來討論一些之前項(xiàng)目問題:
對(duì)于數(shù)據(jù)訪問層(DAL)的問題:
1. DAL很依賴Linq生成的實(shí)體。可以說在之前的項(xiàng)目中,在數(shù)據(jù)訪問層能夠使用的技術(shù)就已經(jīng)釘死在了Linq上。這里不是說Linq不好,而且強(qiáng)調(diào)在DAL的訪問技術(shù)的選擇的余地已經(jīng)沒有了,不靈活。
a) 在架構(gòu)的設(shè)計(jì)過程中,就需要考慮到以后技術(shù)的轉(zhuǎn)變和更換,可能在項(xiàng)目A中采用Linq to sql,但是在項(xiàng)目B中就采用Entity Framework。因?yàn)槲覀兊哪康木褪且_發(fā)一個(gè)比較靈活的通用架構(gòu),能夠支持不同就數(shù)據(jù)訪問技術(shù)。可能以后的項(xiàng)目都只是用一種訪問技術(shù),但是最為架構(gòu)的設(shè)計(jì)者,特別是希望從架構(gòu)最后能夠演化到Framework, 那就要為更換技術(shù)預(yù)留接口。
2. 在DAL中沒有很多的異常處理等底層機(jī)制。
a) 在項(xiàng)目設(shè)計(jì)的過程中,有些底層的機(jī)制是幾乎每一個(gè)邏輯都要用到的:異常處理,日志跟蹤,緩存機(jī)制,事務(wù)機(jī)制,安全驗(yàn)證機(jī)制。當(dāng)時(shí)在之前的DAL中是沒有的。可能現(xiàn)在你認(rèn)為有些機(jī)制不是需要的,或者不明白為什么需要。
因?yàn)橐粋€(gè)強(qiáng)大的軟件,不能隨隨便便就因?yàn)槟承┊惓;蛘咤e(cuò)誤就崩潰了,也不可能就是一大堆代碼的堆砌。上面所提到的有些機(jī)制:如異常,日志,它們的價(jià)值很多時(shí)候在軟件維護(hù)的時(shí)候體驗(yàn)出來。根據(jù)日志記錄,可以查處軟件哪里出了問題,如是數(shù)據(jù)庫斷了,還是哪個(gè)操作流程導(dǎo)致了問題。 而有些機(jī)制是在運(yùn)行時(shí)體現(xiàn)價(jià)值,如緩存,驗(yàn)證,事務(wù)。
但是在使用這些底層機(jī)制的時(shí)候也要權(quán)衡,綜合的考慮,如緩存機(jī)制,就得明白那些數(shù)據(jù)要緩存,緩存在哪里,緩存數(shù)據(jù)時(shí)候要加密,緩存多長時(shí)間,如何刷新過期了的數(shù)據(jù)。等等,很多東西要考慮。
3. 數(shù)據(jù)來源僅僅只是考慮了數(shù)據(jù)庫。其實(shí)這個(gè)問題不是之前的項(xiàng)目的一個(gè)問題,但是這里有必要提出。
a) 一般在我們開發(fā)項(xiàng)目的時(shí)候,數(shù)據(jù)的來源很多時(shí)候都是數(shù)據(jù)庫,我們直接操作數(shù)據(jù)庫就行了,但是還得考慮一個(gè)問題:如果我們的項(xiàng)目沒有自己的數(shù)據(jù)庫,我們的數(shù)據(jù)來源是來自其他的公司或者服務(wù)接口,怎么辦?作為架構(gòu)的設(shè)計(jì)者,是需要考慮這些的。NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之二 草稿設(shè)計(jì)
可能在項(xiàng)目敲定那天就已經(jīng)清楚是自己設(shè)計(jì)數(shù)據(jù)庫還是從其他地方獲取數(shù)據(jù)。但是一個(gè)通用的一個(gè)架構(gòu)的就要能夠?yàn)槠渌臄?shù)據(jù)源預(yù)留接口。
這里,可能就有了一點(diǎn)過度設(shè)計(jì)的味道了,起初在項(xiàng)目A中所使用的架構(gòu)沒有考慮其他數(shù)據(jù)源的問題,但是如果在項(xiàng)目B中出現(xiàn)了,怎么辦?那么架構(gòu)就要演化,改進(jìn)來適應(yīng)這種情況。
之前也提過,沒有必要一上來就設(shè)計(jì)強(qiáng)大的就架構(gòu),而是在項(xiàng)目中改進(jìn),演化。開始時(shí)候沒有考慮到,以后慢慢的加嘛。(比較的糾結(jié))。
上面只是緊緊的從數(shù)據(jù)層DAL的角度進(jìn)行了思考,DAL最終還是為業(yè)務(wù)層BLL提供數(shù)據(jù)的,所以就考慮DAL以何種方式來被BLL調(diào)用,鑒于之前的一些考慮,可以得出一點(diǎn):不讓BLL直到DAL的實(shí)現(xiàn)細(xì)節(jié),所以接口似乎是個(gè)不錯(cuò)的解決辦法,Provider的模式也似乎可以排上用場(chǎng)。
于是,Richard就決定在DAL和BLL之前加上接口層來解耦。
3. 第二個(gè)數(shù)據(jù)層草圖的提出
這個(gè)圖和之前的第一個(gè)圖基本上是一樣的,只是做了一修改,而且加上了之前談?wù)撝猩婕暗囊恍﹩栴}。
因?yàn)殡S著思考的深入,逐漸的發(fā)覺:數(shù)據(jù)源的來源可以很多—數(shù)據(jù)庫,普通文本,XML等等。不同的數(shù)據(jù)源提供不同的Provider,其實(shí)從其他的服務(wù)接口獲取數(shù)據(jù)也是一種來源,上面的圖之所以單獨(dú)的把Service Agent分出,主要是因?yàn)楸容^特殊。
而且圖中的那些基本功能:Log, Exception等,是到處都用到的。
此時(shí)Richard也在頭腦中閃現(xiàn)了一些要處理的,可以出現(xiàn)的異常:
1.Data Source is not exits:數(shù)據(jù)源不存在,因?yàn)檫@個(gè)問題很常見,比如在項(xiàng)目運(yùn)行過程中,數(shù)據(jù)庫斷了,或者遠(yuǎn)程的服務(wù)無法訪問,等等基本都屬于這個(gè)問題的。所以這個(gè)異常肯定是要處理的。
2. Time out:超時(shí)。這個(gè)異常很常見,獲取的數(shù)據(jù)過大,或者遠(yuǎn)程數(shù)據(jù)源連接超時(shí),等,都可以引發(fā)一些問題。
3. 如果數(shù)據(jù)源是其他服務(wù)接口提供數(shù)據(jù),那么在數(shù)據(jù)獲取時(shí),可能要轉(zhuǎn)換數(shù)據(jù)格式,如果格式出錯(cuò),。或者發(fā)送的數(shù)據(jù)不符合一些規(guī)則,這個(gè)異常一定要處理,因?yàn)檫@些數(shù)據(jù)可能涉及到安全的問題了:是數(shù)據(jù)真的不正確,還是被篡改了。
程序就必須對(duì)這些異常進(jìn)行處理:是把原生的異常拋出,然后有業(yè)務(wù)層決定如果處理;還是決定把異常包裝稱為另外的一個(gè)異常,再拋出;還是最后干脆再DAL就執(zhí)行自己處理,然后給業(yè)務(wù)層一個(gè)友好的提示,等等。如果數(shù)據(jù)源是遠(yuǎn)程的服務(wù),那么如果服務(wù)斷了,在異常過程中,采用什么樣的策略:簡(jiǎn)單的處理,如拋出異常,記錄日志,還是做一些恢復(fù)性的操作,如嘗試重新連接,等。
之前第一張圖中,在DAL上定義一個(gè)接口,用來接耦,但是在第二張圖有做了一些修改--把DAL做為服務(wù)提供出去。之所以做了這個(gè)修改,因?yàn)樵陂_始思考的時(shí)候,只是認(rèn)為底層設(shè)計(jì)的DAL只是給BLL使用。可以發(fā)覺到一點(diǎn):在DAL中,數(shù)據(jù)可以從遠(yuǎn)程的服務(wù)中獲取,那么可能我們這里的DAL也可以作為服務(wù)給其他的人設(shè)計(jì)的DAL使用,也就是說,我們的這里的DAL成了遠(yuǎn)程服務(wù)的數(shù)據(jù)源。所以做了上面的修改。但是這個(gè)思考到還會(huì)改進(jìn),因?yàn)檫@里面問題(讀者朋友可以先自己思考是什么問題)。
相關(guān)文章:.NET分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之一 故事起源
.NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之三 數(shù)據(jù)訪問深入一點(diǎn)的思考
.NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之四 構(gòu)建從理想和實(shí)現(xiàn)之間的橋梁(前篇)
NET技術(shù):.NET 分布式架構(gòu)開發(fā)實(shí)戰(zhàn)之二 草稿設(shè)計(jì),轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。