面向對象與領域建模

板橋里人 http://www.jdon.com 2006/12/6(轉載請保留)


多變且復雜的需求

  如果沒有多變的需求,也許就沒有今天的面向對象軟件,我們曾經試圖通過需求管理、需求跟蹤等等管理方式約束和減少需求頻繁更新帶給軟件的沖擊,可是這樣下去的結果只有一個:使得軟件更加僵化;或者程序員更加 勞累。

  需求不但多變,而且經常是不可能第一次就能掌握,需求反映了某個領域的專業知識,例如數學、管理、財務或 電子商務等等,每個特定案例需求又有其特別復雜之處,幾乎沒有人能夠第一次接觸就可以深入掌握這些專業領域的 需求本質,就是專門的建模專家也不例外。

  既然需求是多變而且復雜的,所以,就不能使用“堵”式方法對其進行控制和管理,只能順勢而為,通過靈活多變的 以及迭代反復的方式逐步抓住需求,并且作為需求的實現軟件系統必須能夠迅速應對需求變化,需求變化有多快,軟件 變化就有多快。

  因此,對于多變的需求,我們的解決之道是:引入靈活多變的架構,面向對象OO架構正是應對多變需求而生,強調軟件的可維護性 和拓展性,OO可能不是最好方式,但是目前是最合適的;對于復雜的需求,我們的解決之道是:委派專門的建模專家跟蹤理解需求, 在需求和需求實現之間搭建橋梁,項目方法上采取多次迭代的敏捷軟件開發方式,逐步了解學習掌握需求。

  在這里稍微說明一下,很多人總是將軟件和數學、管理、財務混為一談,其實軟件本身就是一門獨立的專業,是為 數學、管理。財務等專業領域服務的,不能期望軟件人員也是其他領域專業人員,可是在中國現實中,很多人總是 無法分辨,例如某局長將整個機關考核信息化的任務交給電腦中心,這就是將考核管理專業和軟件專業混同的例子, 在考核管理和軟件之間需要一個領域建模專家,由他來理解或者設計考核管理體系,然后通過模型,表達成 軟件人員能夠看懂的符號,軟件人員通過模型了解領域。

  曾經有需求專家呼吁:最好將需求給所有軟件人員都了解,需求專家和一般軟件人員一起工作,這些想法的本質是 好的,但是不可能實現的,不可能每個軟件人員不但了解軟件架構和OO思想;還能夠掌握另外一個專業領域的艱深知識, 所以,現在我們提出:將領域專家建立的統一領域模型讓所有軟件人員都了解,讓一般軟件人員圍繞領域模型工作,這樣 的方式才切實可行。

需求分析方法演變

  歷史上,對需求分析方法可以說經過三個階段:

第一階段:圍繞數據庫的驅動的分析設計,新軟件項目總是從設計數據庫及其字段開始。這個階段特征就是圍繞數據庫編程,典型的是 DBase/Foxpro,以及后來的Delphi/VB技術。

這種圍繞數據庫分析設計的缺點非常明顯:首先,不能迅速有效全面認識反映需求,世界不只是由簡單的關系數據組成,而且 使用關系數據來反映現實需求,不符合人類自然思維(OO才是),是一種扭曲的分析方法,特別對于初學者,他們接受數據庫分析方法的難度反而可能會大于OO 分析方法,現在很多職業學校和社會培訓,基礎課程從數據庫開始,從某種程度上,是歷史倒退, 嚴重阻礙中國軟件發展的進程。

圍繞數據庫分析極其容易導致過程化設計編程,圍繞數據分析和過程化編程是一對惡魔,數據庫結構確立后,就讓普通程序員寫SQL 語句,SQL語句執行有明顯的先后順序,在這樣順序過程編程思維中,OO思維就難以生存。長此以往,成為習慣后,就很難改變到 OO設計上,所以,傳統編程經驗越豐富,轉變到OO設計就越難。

在運行性能方面:圍繞數據庫分析設計容易導致軟件運行時負載集中在數據庫端,系統性能難于擴展(走上集中式、昂貴的、高風險的大型機模式), 閑置了中間件J2EE服務器分布式集群處理能力,就是使用了集群,也分擔不了負載。

最后,我們必須認識到:對象和關系數據庫存在阻抗,本身是矛盾競爭的,他們是兩種分析看待需求的流派,可以說是水火不容, 要么你采取數據庫分析設計以及過程化編程,要么完全采取OO,現在使用.NET和Java這樣OO語言的人很多,但是70%左右都是使用OO語言
編寫傳統過程化系統,在Java中這樣做,會有極差性能;而這種現象在.NET中又極容易得到縱容,.NET是一個系列陣營,正如Windows系列一樣, 當你和別人說,你在使用Windows,別人可能覺得你沒有落后時代,但是他們哪里知道你在使用Windows 3.1呢?

第二階段:面向對象的分析設計方法誕生后,有了專門的分析和設計階段之分,我們使用UML符號來表達分析設計思想,分析設計進入了一個相對更高的層 次,擁有了自己一套科學且藝術的方法論。但是有一個致命缺點:分析階段和設計階段是斷裂的,互相不能很好銜接,為什么?

首先,我們看看分析人員和設計人員在職責重點工作是什么?
分析人員的職責:是負責從需求領域中收集基本概念。而設計人員的職責:必須指明一組能北項目中適應編程工具構造的組件,這些組件必須能夠在目標環境中有效執行,并能夠正確解決應用程序出現的問題 兩個階段兩者目標不一致,分析人員只管需求分析,至于是否適合設計,或者能夠導出適宜設計的分析結果,這個尺度很難衡量和把握;

而設計人員因為照顧代碼可運行,因此,經常可能會抱怨分析員給出的結果過于粗糙,不適合設計,這樣分析設計兩個階段就導致分裂,項目失敗。

  在這個階段,雖然有UML幫助,但是UML不是思想,打個比喻:會CAD的繪圖員就是建筑師嗎?很顯然,UML就是CAD圖符號,UML不等于分析設計思想。 所以,有人說UML不是銀彈,這些就象說中醫不是科學一樣繞人(中醫就不是西醫,當然就不是科學)。

第三階段:融合了分析階段和設計階段的領域驅動設計(Evans: DDD)。2004年Eric Evans 發表Domain-Driven Design –Tackling Complexity in the Heart of Software (領域驅動設計 )簡稱Evans DDD, 領域建模是一種藝術的技術,它是用來解決復雜軟件快速應付變化的解決之道,所以,從Evans DDD通篇文章中,你找不到科學象征的定理和公式,當然如果 你試圖尋找這樣尋找,你也就陷入了“中醫是不是科學”怪圈了。

  Evans DDD拋棄了分裂分析模型與設計的做法,使用單一的模型來滿足這兩方面的要求。這就是領域模型。 單一的領域模型同時滿足分析原型和軟件設計 ,如果一個模型實現時不實用,重新尋找新模型。如果模型沒有忠實表達領域關鍵概念時,也必須重新尋找新的模型。 建模和設計成為單個迭代循環。將領域模型和設計緊密聯系。因此,建模專家必須懂設計。

領域建模的重要性

  如果你說一個軟件開發需要經過需求、分析和設計三個階段的話,那么可能反映你的思想已經落伍,軟件開發現在是 經過需求、建模階段,混合了分析和設計階段,可以更激進地說:我們國家的系統分析員和系統設計員考試也許應該合并了, 合并成建模專家的考試,否則,這些都是中國軟件落后世界十年的證據,可悲的是:我們自己可能都不知道。

Evans DDD可以說是近期與SOA相提并論的兩大重要技術思想,SOA是著重于軟件集成方面;而EvansDDD才是著重我們軟件開發上, 在大部分情況下,軟件開發重要程度不亞于軟件集成,但是因為軟件開發方面開源力量沖擊,軟件集成上工業廠商利潤最高, 所以,工業廠商在SOA叫得最響,我們參加得各種會議幾乎都是SOA,當心被誤導,工業廠商從來不會告訴你事實得爭相。

   沒有面向對象的分析設計,哪里面向對象的構件或組件?過去經驗不是證明:我們使用大量的構件組件,卻在編制面向過程的體系?

以EJB2為例子,在EJB2過去大部分系統中,我們常常以數據庫為中心,實體Bean因為特殊技術原因,僵硬一塊,變成數據庫 的代名詞,我們圍繞實體Bean編制出大量的值對象Vale Obejct,或稱為DTO(Data Transfer Object),在這樣系統中,從對象 的名稱也可以看出,對象是為數據服務的,對象從屬于數據庫的。

現在,要徹底改變過來,OO就是以對象為主,數據庫是從屬對象設計的,如果說EJB2的實體bean技術讓你不得不走上傳統過程化編程歧路,那么 EJB3已經更正了實體Bean設計缺陷,從EJB發展可以看到一個側面:工業廠商更多關心的是功能,而不是設計?

只有誰才真正關心你的軟件設計和代碼質量?只有你自己。我不是提倡都不要參加工業廠商的會議,而是需要每個人冷靜想想: 到底誰是自己代碼的主人?

  領域建模屬于與具體.NET或Java技術無關的設計思想,有人總是說:.NET比Java簡單,其實這又是一個大誤區,如果都達到同樣設計水準,無論使用.NET或Java,都需要付出同樣的努力;那為什么有人覺得.NET簡單,那是因為設計要求降低了,參見這篇.NET的DDD文章

分層架構

  分層架構是現代OO軟件企業系統的基本架構,只有分層才能達到良好的可拓展性和維護性。基本三層:表現層、業務層和持久層 ;J2EE中表現層和持久層有成熟框架支持,應用重點在業務層。

業務層根據Evans DDD,可以再細分為應用層和領域層兩種,在業務層設計編碼中,大量應用OO設計原則和設計模式。領域層定義:負責表達業務領域概念、業務狀態以及業務規 則,是整個業務軟件核心和重點。 應用層定義:負責完成功能,并且協調豐富的領域對象來實現功能,不能包括業務規則,無業務狀態;

  每個層都是內聚的,并且只依賴它的下層,為了實現各層的最大解耦,IOC/DI容器是當前Java業務層的最好選擇 。

   沒有分層架構的快速開發基本是旁門左道,不如返回Foxpro和Delphi/VB兩層時代。將本屬于業務層的邏輯交由表現層來處理的快速UI方式也是一種旁門左道。快速開發必須基于良好的質量,雖然良好的分層架構帶來開發效率的降低,但是這些也是可以有方法解決。

建模與項目管理

在我們大多數從軟件項目管理上尋找軟件永恒解決之道時,他們可能沒有意識到又在范“緣木求魚”老毛病了, 打個比喻很容易明白這個道理:冷兵器時代(也就是火槍沒有沒有發明之前),各種排兵布陣可能在作戰指揮時 很有效;但是到了火器時代,所有的過去作戰方式就落伍了;當然到了現在信息化戰爭時代,更是天壤之別。

   Evans DDD領域驅動建模的誕生,對過去傳統的項目管理都提出挑戰,當我們還在爭論RUP好還是敏捷好的時候, 誰會想到我們應該采取圍繞統一領域模型的迭代驅動開發呢?

   有人可能還在疑惑?我接到一個大項目,那么我的建模和架構設計時間應該是5個月還是5年呢?當然應該回答他:都不行,需求是多變且復雜的,計劃趕不上變化,現在就應該開始DDD建模。

(以上文字源自板橋本人的第四屆中國軟件技術大會“領域設計建模”演講稿 )

相關文章:

當前Java項目開發中幾種認識誤區

領域建模之建模設計系列

實戰DDD(Domain-Driven Design領域驅動設計)

JavaEE/J2EE面向對象編程之道

Feature-Driven Development特征驅動開發

快速適應需求變化的軟件復用

Java企業系統架構選擇考量

數據庫時代的終結

數學建模對程序設計的影響

兩年的技術經歷,在J2EE上疑惑?

致面向對象技術初學者的一封公開信

貧血和充血模型的比較之我見

更多關于DDD討論

發表討論