什么是架構
- Rolph Johnson認為:架構是一種主觀上的東西,是專家級的項目開發人員對系統設計的一些可共享的理解
- 架構中包括一些決定,開發者希望這些決定能盡早作出,因為在開發者看來它們是難以改變的。
- 如果你發現某些決定不像你想象中的那么難以改變,那么它就不再與架構相關
- 理解: B/S (SmartClient、C/S) 架構, DotNet 架構, J2EE架構
企業應用的特點
- 涉及到持久化數據
- 很多人同時訪問數據
- 含有大量操作數據的用戶界面
- 與散布在企業內部或周圍的其他的應用集成
- 各種異構系統的概念含有不一致性
- 業務邏輯通常是最沒有邏輯的東西
- 企業應用并非都是大型的,但可能都為企業提供巨大的價值
· 性能:很多時候,增加更多的服務器比增加更多的程序員便宜;如果增加服務器對性能的提升較大,則說明應用的伸縮性好
· 分層:上層是用下層定義的各種服務,而下層對上層一無所知;分層的缺陷是不能封裝所有的東西,因此可能帶來級聯更改,過多的曾影響性能;Layer和Tier的區別是Tier可能更多的意味物理上的分離
Brown分層模型
表現層>>控制層>>領域層>>數據映射層>>數據源層
Core J2EE分層模型
客戶層>>表現層>>業務層>>集成層>>資源層
MS DNA分層模型
表現層>>業務邏輯層>>數據訪問層
Marinescu分層模型
表現層>>應用層>>服務層>>領域層>>持久層
·
領域模型:使用不同職責的對象來聯合解決業務問題,而不是通過事務腳本來處理數據
· 阻抗不匹配:對象模型和關系型數據庫之間的不匹配,通常通過對象-關系映射(ORM)解決
· 軟件事務的四個特性
1. 原子性:要么全部成功,要么全部會滾
2. 一致性:事務開始和完成時,資源都不應該被破壞
3. 隔離性:事務成功完成之前,其影響不應該被看到
4. 持久性:事務不會因為任何崩潰而丟失更改
· 事務的隔離級別(由高而低)
1. 可串行化:完全隔離,并發執行的結果與以某種順序依次執行的結果相同
2. 可重復讀:允許幻讀,更新者向集合中插入了一些元素而讀的人只能看到其中一部分
3. 讀已提交:允許不可重復讀,所有已經提交的數據都可以讀
4. 讀未提交:允許臟讀,允許讀未提交的數據
· 會話狀態:無狀態對象是一種不良設計;用無狀態的服務器可以實現有狀態的會話;如果有很多會話空閑,可以考慮用數據庫存儲會話;如果需要頻繁訪問會話,則應該使用服務器會話
· 分布策略:分布對象的第一定律:不要使用分布對象;分布對象的第二定律:節約使用分布對象
領域邏輯模式分為 事物腳本、領域模型、表模塊和服務層四種模式
很多設計者喜歡把業務邏輯分成兩類:領域邏輯和應用邏輯,前者只與問題領域有關、而后者有時被稱為工作流邏輯
1. 事物腳本
通過使用SQL語句或者存儲過程返回記錄集,記錄集在系統的各層之間傳遞,在必要的時候可以通過更新記錄集、使用SQL語句或者存儲過程的方式更新數據庫
事物腳本勝在簡單,通常應用在小型的項目和系統中,但業務邏輯越來越復雜,使用這一模式就越來越難以保持良好設計,因為在程序里面充斥了大量的SQL語句和命令,一旦數據結構發生更改或者需要對系統進行修改,可能會出現許多難以發現的問題
2. 領域模型
領域模型是合并了行為和數據的領域的對象模型,領域模型創建了一張由互聯對象組成的網,其中的每個對象都代表著某個有意義的個體,可能大到一個公司或者小到訂單的一行
簡單領域可以使用活動記錄,即簡單的單條數據記錄和單個對象對應的模式,一個對象對應數據庫中的一個表
復雜領域模型需要使用數據映射器,它可能使用繼承、策略或者其他的設計模式,是一張由互聯的細粒度對象組成的復雜網絡,我們經常會看到:多個類通過交互來完成很簡單的任務
在面向對象技術中,通過從一個對象到另一個對象的連續傳遞可以把行為傳遞給最有資格處理的對象,它同時消除了很多條件判斷行為
領域模型的要點在于隱藏數據庫的存在
3. 表模塊
表模塊是處理某一數據庫表或視圖中所有行的業務邏輯的一個實例
表模塊通過強類型或弱類型的數據集與對象結合使用,使用主鍵查詢數據,是.Net中使用的很多的一種模式,主要使用主鍵、半對象化的操作數據---之所以說是半結構化,是因為所用的對象基本上只具有行為,通過傳入參數執行特定的操作或者查詢記錄集,而幾乎不承載任何數據
在.net中,這種模式因為其容易和UI進行綁定和交互,所以倍受歡迎
4. 服務層
通過一個服務層來定義應用程序邊界,在服務層中建立一組可用的操作的集合,并在每個操作內部協調應用程序的響應
服務層是一種組織業務邏輯的模式,有點類似于業務外觀;WEB SERVICE通常擔任著服務層的角色
服務層可以通過領域外觀方法和操作腳本方法實現,領域外觀方法中,服務層以領域模型之上的瘦外觀集合方式出現,負責實現外觀的類中不不包含業務邏輯;而在操作腳本方法中 ,服務層由一組相對復雜的類組成,這些類直接實現應用邏輯,但將領域邏輯委托給封裝好的領域對象類
服務層的類的接口是粗粒度的,適合于遠程調用。但是,在開始時,我們應該僅設計一個本地調用的服務層,在需要遠程調用時,再在服務層上增加一個遠程外觀。
并發管理的正確目標是盡量增加對數據的正確訪問,同時減少沖突
離線并發模式有兩種:使用樂觀離線鎖、使用悲觀離線鎖
離線鎖可以理解為一種非服務器管理的鎖,或者說是自管理的鎖,應用在適當的地方注冊鎖,獲取數據,然后離線,并對數據進行離線的操作;其他的應用通過檢測已經注冊的鎖來決定是否進行并發操作
1. 悲觀離線鎖
悲觀離線鎖假設會話沖突的可能性很大,從而對系統的并發進性進行限制
在對不一致讀的要求不高時,第一選擇是使用獨占寫鎖(不可以再添加任何讀鎖,當然寫鎖也不能);如必須讀出最新數據,而不在乎是否要修改,則應使用獨占讀鎖(不可以再添加任何寫鎖,但讀鎖是允許的)。結合以上兩種,提供互斥讀鎖的限制,又有互斥寫鎖的并發性的鎖稱為 讀/寫鎖---讀/寫鎖互斥不能同時加,但并發的讀鎖是允許的
構建悲觀離線鎖的步驟:決定使用哪種鎖>>構建一個鎖管理對象>>定義業務事務使用鎖的過程
讓鎖管理對象在鎖不可用時拋出異常而不是等待鎖釋放,可以免除死鎖
悲觀離線鎖作為樂觀離線鎖的補充,只在真正需要的時候才應該使用
2. 樂觀離線鎖
樂觀離線鎖假設會話沖突的可能性很小,從而使得多用戶對一份數據進行處理成為可能
通過沖突檢測和事務會滾來防止并發事務中的沖突
本質就是通過將會話中的版本號與當前記錄數據的版本號相比較,事務成功提交以后版本號增加;或者在更新的SQL語句中包含對所有字段的檢查,可以不需要為數據庫增加版本字段,但可能導致性能損失
樂觀離線鎖必須自定檢查以防止不一致讀
一個高效的合并策略能使樂觀離線鎖變得非常強大,當沖突發生時,合并策略可以合并更改并重新提交