|
我研究領(lǐng)域驅(qū)動設(shè)計已經(jīng)近4年時間了,在這4年里,我從了解領(lǐng)域驅(qū)動設(shè)計的基本思想開始,系統(tǒng)地學(xué)習(xí)了與領(lǐng)域驅(qū)動設(shè)計相關(guān)的概念、開發(fā)模式以及應(yīng)用系統(tǒng)架構(gòu)風(fēng)格,并將其運用在了實際的項目架構(gòu)與開發(fā)中。在此之前,我一直被一些應(yīng)用程序架構(gòu)設(shè)計上的問題所困擾,比如:在數(shù)據(jù)持久層,如何讓數(shù)據(jù)持久化機制能夠支持不同的數(shù)據(jù)庫類型,甚至是非關(guān)系型數(shù)據(jù)庫;如何能夠讓開發(fā)人員將關(guān)注點放在領(lǐng)域模型上,而在更改領(lǐng)域模型的同時,不用去關(guān)心數(shù)據(jù)持久化的細節(jié)內(nèi)容;如何將應(yīng)用程序的視圖模型部署在服務(wù)器端,而客戶端可以通過不同的用戶界面代理產(chǎn)生不同的視圖展示機制,等等。為了實現(xiàn)設(shè)計思想,我于2008年開發(fā)了一套基于類似XUP協(xié)議的應(yīng)用框架原型,在客戶端通過WCF技術(shù)與服務(wù)器進行通信,以支持服務(wù)端事件的響應(yīng)與處理,而數(shù)據(jù)訪問部分則采用NHibernate的Schema Tools,在服務(wù)每次啟動的時候比對領(lǐng)域模型與數(shù)據(jù)庫的差異從而動態(tài)調(diào)整數(shù)據(jù)庫結(jié)構(gòu)。整個系統(tǒng)的運行機制有點類似ASP.NET,但它可以支持諸如Windows Forms、WPF等多種用戶界面機制(如圖一)。在完成了第一階段的原型開發(fā)后,我在《計算機工程與應(yīng)用》期刊上發(fā)表了一篇題為《基于XML的松耦合UI架構(gòu)的設(shè)計與實現(xiàn)》的論文,闡述了這個應(yīng)用框架的設(shè)計與開發(fā)的要點與細節(jié)。
遺憾的是,我并沒有真正地完成這個框架的開發(fā)。首先,在基礎(chǔ)結(jié)構(gòu)層,使用NHibernate的Schema Tools來完成數(shù)據(jù)庫的同步過程,會產(chǎn)生很多限制,比如:自動化的數(shù)據(jù)庫結(jié)構(gòu)變更會出現(xiàn)很多冗余信息,數(shù)據(jù)庫必須采用關(guān)系型數(shù)據(jù)庫,框架本身需要依賴于一套特定的機制才能實現(xiàn)其功能,ORM具有一定程度的性能損耗,于是應(yīng)用程序就會產(chǎn)生性能調(diào)優(yōu)的瓶頸;其次,沒有對領(lǐng)域模型的設(shè)計與開發(fā)做出很好的支持,整個框架更多地是在技術(shù)層面為應(yīng)用程序的開發(fā)提供便捷,忽視了領(lǐng)域模型的重要性,這就使得整個框架沒有一個清晰的思路去解決數(shù)據(jù)映射與傳輸方面的問題;再次,雖然框架已經(jīng)實現(xiàn)了基于XML的界面描述、事件綁定、事件樁與事件路由等基本特性,但與成熟的框架相比,還是有很大的差距,而彌補這樣的差距還需要花費很大的努力,比如:資源管理系統(tǒng)、基于角色的權(quán)限管理系統(tǒng)、商業(yè)許可證的授權(quán)方式與支持系統(tǒng)、報表管理系統(tǒng)、基于LUA或Javascript的客戶端事件處理系統(tǒng)等等,而這所有的內(nèi)容都不是光靠我一個人所能完成的。總之,從技術(shù)架構(gòu)上看,除了能夠支持多種用戶界面機制外,整個框架跟ASP.NET很相似。
然而在設(shè)計與實現(xiàn)這個框架原型的過程中,我思考了很多,也學(xué)到很多。隨著領(lǐng)域驅(qū)動設(shè)計思想的引入,我慢慢地在思考:領(lǐng)域模型能否以DTO的形態(tài)出現(xiàn)在應(yīng)用層?倉儲是領(lǐng)域概念,但如果真正將其實現(xiàn)在領(lǐng)域?qū)觿t明顯不合適,因為它需要與外部技術(shù)架構(gòu)打交道,但如果設(shè)計在基礎(chǔ)結(jié)構(gòu)層,由于倉儲是直接對領(lǐng)域?qū)ο筮M行操作的,那么從.NET的開發(fā)上來看,基礎(chǔ)結(jié)構(gòu)層的程序集就必須引用領(lǐng)域模型的程序集,于是,領(lǐng)域模型就無法去引用基礎(chǔ)結(jié)構(gòu)層的程序集,因為會產(chǎn)生循環(huán)引用,因此也就無法去使用基礎(chǔ)結(jié)構(gòu)層的服務(wù)了,像這樣的問題又如何解決?在領(lǐng)域模型中,領(lǐng)域?qū)ο竽苤苯硬僮鱾}儲來完成業(yè)務(wù)邏輯嗎?應(yīng)用層的作用是任務(wù)協(xié)調(diào),而任務(wù)又包含哪些內(nèi)容?協(xié)調(diào)又是怎樣的一個過程?應(yīng)用層與用戶界面層通信是通過數(shù)據(jù)傳輸對象(Data Transfer Object,DTO)實現(xiàn)的,那么是否需要為每一個領(lǐng)域?qū)ο笤O(shè)計一個DTO,如果是的話,那豈不是開發(fā)過程會變得非常繁雜,而且會降低應(yīng)用程序的可維護性,比如今后如果領(lǐng)域模型發(fā)生了更改,那么也需要相應(yīng)地更改DTO。更進一步,是否在領(lǐng)域?qū)优c基礎(chǔ)結(jié)構(gòu)層的數(shù)據(jù)訪問組件之間也需要引入類似DTO的概念,以便解耦領(lǐng)域模型與數(shù)據(jù)模型?但如果的確如此的話,那系統(tǒng)中豈不是充斥著各種各樣的數(shù)據(jù)對象?這是基于領(lǐng)域驅(qū)動設(shè)計的軟件架構(gòu)的最佳實踐嗎?
只有真正地實踐,才能很好地回答這些問題。于是,我開始結(jié)合ADO.NET Entity Framework來實踐領(lǐng)域驅(qū)動的軟件架構(gòu),并結(jié)合自己的收獲總結(jié)了《Entity Framework之領(lǐng)域驅(qū)動設(shè)計實踐》系列文章,發(fā)表在了博客園上。該系列文章獲得了博客園社區(qū)讀者的廣泛關(guān)注,很多朋友紛紛參與討論,并提出了不少針對性很強的問題,我也盡我自己的最大努力,盡量做到有問必答。于是通過反反復(fù)復(fù)的討論與相關(guān)知識的慢慢積累,一種面向領(lǐng)域驅(qū)動的軟件架構(gòu)設(shè)計方式已經(jīng)在我腦海里成型了,并且在實踐過程中,自己總結(jié)了一些“哪些方式是可行的、哪些方法是不合理的”基于領(lǐng)域驅(qū)動的軟件架構(gòu)設(shè)計最佳實踐。
之后,我開始著手把我所總結(jié)的這些內(nèi)容實現(xiàn)在一個應(yīng)用程序開發(fā)框架上,使得軟件人員能夠非常方便快捷地開發(fā)出基于領(lǐng)域驅(qū)動的軟件架構(gòu)的應(yīng)用程序。我將這個框架取名為Apworks(Application Development Framework and Tools的縮寫,取名其實也是來源于我之前提到的那個未完成的框架名稱)。在2009年底到2010年初,我在微軟的開源網(wǎng)站codeplex上簽入了Apworks的第一份代碼,而在2010年底,成功完成了Apworks的Alpha版本,與此同時,Apworks Alpha版的第一個演示案例TinyLibrary CQRS(tlibcqrs)也在codeplex上發(fā)布,社區(qū)不少朋友對Apworks以及tlibcqrs都非常關(guān)注,有朋友甚至希望能夠?qū)pworks整合到他們的項目中,在此,我對這些朋友們的支持表示衷心感謝。
基于.NET的框架的設(shè)計與開發(fā)更不是一件容易的事情,這與“領(lǐng)域驅(qū)動設(shè)計”相比,它又屬于另一個領(lǐng)域:我們需要考慮的不是通用語言,不是4+1視圖,不是用例,不是角色,不是DCI,不是領(lǐng)域建模;我們需要考慮的是如何搭建一個高效的、穩(wěn)定的、安全的、可擴展的、基于.NET的應(yīng)用程序開發(fā)框架。而這些,就是本文所要重點討論的內(nèi)容。
本文將分為兩大部分,第一部分重點討論基于.NET的框架架構(gòu)設(shè)計的設(shè)計指南與最佳實踐,這部分內(nèi)容都是我在設(shè)計與實現(xiàn)Apworks框架的過程中,結(jié)合一些理論知識總結(jié)出來的,比如如何使用分離接口模式以減小框架本身與第三方組件之間的依賴,如何提高框架的可測試性等;這部分內(nèi)容還將給出幾個常用的設(shè)計模式、體系結(jié)構(gòu)模式和語言慣用法的.NET(C#)實現(xiàn),以便讀者們在構(gòu)建自己的應(yīng)用程序開發(fā)框架時,可以在需要的時候直接引用本文給出的模式實現(xiàn)方式,提高開發(fā)效率。當然,這些內(nèi)容都是我的經(jīng)驗總結(jié),或許會因為我能力有限而出現(xiàn)疏漏或不合理的現(xiàn)象,這就需要讀者朋友們給出意見給予指正了,我也會跟進這些反饋信息而不定期地修訂原文。第二部分將以Apworks為例,詳細講解Apworks框架中某些組件的設(shè)計構(gòu)想,例如,在設(shè)計外部事件存儲(Event Store)的時候,我是如何考慮并實現(xiàn)存儲機制的技術(shù)無關(guān)性的,又比如,“快照提供者(Snapshot Provider)”是如何支持可擴展的基于不同策略的快照功能實現(xiàn)機制,這些內(nèi)容將在這部分進行討論。
總之,本文將主要討論基于.NET的應(yīng)用程序框架架構(gòu)設(shè)計實踐,在此過程中會引用Apworks框架作為案例進行講解,選用Apworks作為案例,首先是因為本文所討論的所有內(nèi)容都來源于該框架的設(shè)計與開發(fā)過程中,其次,Apworks已經(jīng)是一個現(xiàn)成的框架了,讀者朋友在學(xué)習(xí)的過程中可以有個成品作參考,以便更好地理解本文所討論的內(nèi)容。希望讀者朋友不會誤認為本文是Apworks的廣告而對之產(chǎn)生反感,我真心希望本文能夠給愛好企業(yè)級應(yīng)用系統(tǒng)架構(gòu)的朋友帶來一定的參考價值。
it知識庫:.NET應(yīng)用框架架構(gòu)設(shè)計實踐 - 概述,轉(zhuǎn)載需保留來源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。