談DotNet解決方案下分層和子項目的劃分

分層在英文裏面有Tier和Layer兩方面的含義。Tier主要是隻硬件上的分層,如客戶端,應用服務器和數據庫服務器。而Layer主要是指軟件系統結構下的分層。而這裏談的主要還是軟件體系結構上的分層。
  
最近經常看到的DotNet多層架構,七層架構等詞語。歸根到底其核心還是數據資源層,邏輯層和表現層三個層次。其它層次基本上都是基於這三個層次所做的擴展。在做一個軟件系統的時候,具體如何分層跟要採用的系統架構有密切關係,而要採用何種系統架構又和業務需求密切相關。因此,是業務需求在驅動具體解決方案的分層,分層和獨立新的子項目都絕對不是越多越好,而應該有充足的需求來支持。
  
1.高效開發的分層方案(數據庫存儲過程+DA數據訪問層+UI層)
是否應該使用存儲過程或者說業務邏輯是否應該放在存儲過程中一直是爭論的一個焦點問題。但不可否認的是使用存儲過程,並將業務邏輯放在存儲過程中是一種值得推薦的高效開發模式。存儲過程的可移植性和可維護性一直是一個問題,但只要我們注意了包,函數和子存儲過程的劃分,存儲過程一樣是很容易維護的。
  
從2001年開始使用DotNet開始,我們就一直借鑑了IBuySpy的案例採用這種開發模式,開發的僅存儲過程代碼可能就超過50萬行,2003年後臺數據庫要移植到Oracle數據庫是遇到的最大一次挑戰,整個項目組花了3個多月的時間完成了遷移。但經過實踐證明,這種簡潔的開發模式和分層方式是完全值得中小型項目推廣和使用,以獲得最大化的開發效率。
  
由於業務邏輯放在存儲過程中,因此沒有專門的業務邏輯層,僅僅保留了數據訪問層,而且採用存儲過程這種方式的時候整個DA層都完全通過代碼生成器或數據訪問組件來實現。對於數據處理和傳輸也沒有使用專門的DTO對象,而直接使用DataSet和DataTable等來實現,因此也沒有專門的數據實體層。UI層除了處理UI操作和數據展現外,還做簡單的數據完整性等方面的校驗。
  
開發的公用類,公用組件或異常日誌的處理仍然需要單獨建立一個公用項目來實現。
  
這種分層方案最大的缺點就是可移植性,當出現數據庫需要遷移或移植,或需要支持多數據庫的時候往往造成極大的麻煩。
  
2.是否獨立專門的DataEntity層存放數據實體
在微軟的Duwamish或PetShop等範例程序種都有專門的DataEntity層來存放數據實體。這裏首先要討論的是否要使用數據實體,當我們使用DataSet或DataTable來作爲數據傳輸對象的時候,DataSet其實已經起到了數據實體的作用,但當這個DataSet是非類型化的DataSet的時候完全沒有必要建立單獨的DataEntity項目。
  
當使用Typed DataSet或Custom Entity來做數據實體的時候,一般就需要考慮建立單獨的DataEntity項目,這個項目基本上完全獨立的項目而不會依賴於其它項目,但DataEntity項目卻會被DA層,邏輯層或UI層的多個項目引用。將數據實體獨立爲項目的時候就解決了項目間由於要訪問數據實體而引起的循環項目依賴問題。
  
我們經常因爲性能問題而拋棄了採用Typed DataSet作爲DTO的這種高效的模式,而自己建立相關的對象類和類集合來處理這些記錄集。到了客戶端又要進行相關的轉換以滿足數據綁定的需要。DataSet決定可以算得上是ADO.net中的一個值得稱道的對象,有了DataSet後可以大大的簡化我們對記錄集的處理和綁定。如果我們老把Java或J2EE中的一些架構和分層思路生搬硬套的往DotNet上使用,而不去考慮DotNet和ADO.net自身的很多優質特性,那就很難真正得到一個高效的分層架構。
   
3.業務邏輯層
如果不在存儲過程中存儲業務邏輯,則建立獨立的業務邏輯層是完全有必要的。在這裏談到的業務邏輯層更多是業務控制類,因爲業務實體類已經單獨分離爲DataEntity項目。這和RUP裏面談到的實體類和控制類個人認爲是有點類似的。
   
對業務邏輯層的錯誤使用主要來自兩方面的內容。一方面是將對數據表的裝載或保存等數據操作做爲業務邏輯,而這個應該是放到數據層的內容;另外是將本身屬於業務邏輯的內容放置到了UI層。所以我們觀察很多實際的軟件項目的時候會發現業務邏輯層往往形同虛設,裏面基本都是一個簡單的Wrapp和轉發代碼,而無實際的業務邏輯代碼。UI層僅僅是將獲取的數據顯示到界面上,或者將界面數據整理後傳遞到邏輯層,以及界面流程的跳轉,簡單的數據完整性校驗等,跟這些無關的都應該放到邏輯層進行處理。
   
試想一下對於將某一類別產品的最近兩個月銷售量差別>10%的數據顯示爲紅色的業務邏輯是什麼呢?
   
4.關於需要同時支持BS和CS兩種模式的問題
應用系統往往有需要同時提供Web和CS的兩種訪問模式。對於BS應用而言一般不存在分佈式部署的問題,而對於CS模式則一般要實現爲分佈式的應用,需要考慮分佈式部署的問題。對於分佈式的考慮將在後面進一步描述。
   
當同時支持BS和CS兩種客戶端的時候,我們的期望是僅僅是WinUI和WebUI兩個項目存在不同,而其它各層的相關項目都可以實現完全的重用。爲了最大化的實現這種重用,原來放在UI層中做的UI數據完整性校驗等內容也需要抽取出來做爲單獨的Facade層,這樣UI層僅僅處理完全跟UI相關的操作,當一個功能要由CS轉BS的時候僅僅編寫最小化的WebUI層代碼即可。
    
5.對系統支持分佈式應用和部署的考慮
爲了讓系統支持分佈式部署,我們一般需要增加服務代理,服務接口,WebService的相關層和子項目。一個系統爲了實現對分佈式的支持往往多增加了2,3個子項目而增加了系統的複雜性。在2004年開始的一個應用系統架構設計中,經過充分的考慮決定了採用Remoting+http+Binary來實現分佈式應用,但整個系統的分佈式不增加任何的子項目和分層,僅僅是在客戶端和服務器端增加相應的配置文件,所有的分佈式都是通過分佈式部署來自動實現的。
   
採用配置文件來實現分佈式的方法很好了解決了應用要同時支持BS和CS兩種模式的問題。因爲在整個解決方案中不會存在僅僅CS纔會使用的服務代理或服務接口層的問題。所有的代碼除了UI層外BS和CS都是公用的,實現了很好的複用。從實際運行效果和開發效率來看這都不失爲一種好方法,至少不會出現爲了增加一個簡單的功能都要修改7,8個項目,增加相關的代碼才能夠實現的問題。
   
6.對系統複用而建立的公用項目和公用組件
這是無論採用哪種分層架構下都必須考慮的問題。對於公用類和組件必須建立單獨的項目來進行管理,這樣公用項目既可以實現很好的專人管理,也可以方便被其它各層的項目引用。
   
公用項目應該保護常用的字符串,日期和集合的處理,對DataSet的輔助處理,常用的算法,常用的基礎數據的獲取等相關內容。而對於公用的組件更建議以黑盒dll的形式來實現複用。對於嚴格基於組件和構件開發的系統,複用率可以達到70-80%。因此對於一般的軟件系統至少應該達到40%以上的軟件複用。
   
7..架構對異常,日誌,安全,緩存,異步等方面內容考慮而增加的獨立項目
異常,日誌和安全等都是一個系統必須要考慮的非功能性需求。但具體的每個系統要實現到哪個程度,控制到哪個級別則完全是跟具體的業務需求相關的。例如對於異常日誌我們可能僅僅需要的是能夠捕獲內部異常而給用戶提供友好的提示信息但又能夠記錄在相關異常信息方便分析錯誤,我們的異常日誌功能能夠有針對性的滿足到此就足夠了。
   
當我們實現一個軟件系統不加思索的將微軟的Enterprise Library的10多個dll一股腦的全部加入到項目中去後並不一定會給項目帶來多少好處,爲了實現一個小需求而用這些面面俱到的工具只會增加整個系統的複雜度。我們爲何一定要去用微軟的Updater App Block呢?獲取我們需要的僅僅是自己手寫的不超過100行的一個簡單的Loader程序。
   
我們完全可以僅僅建立一個獨立的項目就可以實現關於異常,日誌和安全等所有的項目需要的非功能性需求。一個解決方案下的項目過多隻會增加系統的複雜性和管理上的困難。做軟件系統需要考慮系統的可擴展性,但我們絕不應該要那種項目根本不需要的擴展作爲系統的裝飾品。
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章