欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

一堂如何提高代碼質量的培訓課 之 領域驅動設計

系統 1608 0

終于到了該說說領域驅動設計的時候了。我們在這場關于代碼質量的討論中,從代碼可讀性開始,討論了代碼復用性、設計模式,然后探討了職責驅動設計。代碼可讀性是對代碼質量最基本的要求,可惜我們仍有做得不夠的(即使那些開發程序很多年的老程序員)。代碼復用是提高代碼質量的最初級階段,但是在一個多人開發的項目團隊中,圍繞代碼復用值得討論的問題依然非常多,它依然是一個非常復雜的問題,甚至有時它不再僅僅是一個技術問題,而是一個管理問題。唉,提高代碼質量的道理漫漫兮同志們要上下而求索。一個比較成功的保證代碼質量的管理模式就是代碼復查。讓一些有經驗的程序員定期去復查那些初級程序員的代碼,指導他們的開發,被認為是成功的,但也代價巨大的。

然而,在這場關于代碼質量的討論中,我認為,最終的終極目標毫無疑問應當是“領域驅動設計”。領域驅動設計可以快速而根本地提高我們的代碼質量,舉一個最近發生的一件事情也許可以深刻地說明這一點。前不久,我將一個開發任務交給了我的一個手下。一周后,當我對他的代碼進行復查的時候,我驚呆了。我甚至不能提出任何的建議來優化他的代碼。隨后,我花了半個小時的時間與他一起進行了一次領域模型分析,將他開發的這個模塊用領域模型繪制了一個草圖。隨后的數日,他照著這個圖紙重新進行了編碼。當我再次復查他的代碼時,我忍不住笑了。在短短的一周時間內能讓一個人的代碼質量判若兩人,這不得不說是領域驅動設計帶給我們的震撼。

但是,在領域驅動設計之前,我用大量篇幅講解了職責驅動設計。職責驅動設計是領域驅動設計的理論基礎,領域驅動設計是職責驅動設計的最佳實踐。領域驅動設計要求我們以領域模型作為我們分析與開發的核心,為什么?因為我們的設計應當與現實世界保持“低表示差異”。領域驅動設計強調所有的領域對象應當以現實世界作為模板,為其定義和分配行為,為什么?因為我們的設計應當以職責為中心,按職責分配行為,分配行為的原則可以參照“信息專家”模式。領域驅動設計并不是橫空出世的,而是在職責驅動設計的基礎之上發展的。理解職責驅動設計可以促進我們對領域驅動設計的理解,然而非常遺憾的是,它卻長期游離于我們的視線之外。

?

低表示差異與領域模型

我在前面的“職責驅動設計”部分已經討論了“低表示差異”。用一句簡短的話說,在我們的分析設計中,軟件世界始終應當與現實世界保持“低表示差異”。如何保持低表示差異呢?答案就是領域模型分析。

領域驅動設計,其名稱中,將“領域( Domain )”這個詞放在了最顯著的位置上,為什么呢?因為它的理論核心就是領域。在需求分析和設計階段使用領域模型與客戶進行軟件需求的討論。在這個階段,領域模型是最重要的一個驗收成果,沒有完成領域模型分析,這個階段就永遠不算結束。在軟件開發階段采用領域模型作為核心設計圖紙指導設計開發。領域模型怎樣設計則我們的軟件系統就怎樣設計,軟件系統中的最主要軟件類都是源自領域模型中定義的領域對象。在運行維護及二次開發階段,領域模型就如同房屋建筑中的設計圖紙,它成為運行維護人員和二次開發人員熟悉和理解軟件系統的核心線索。總之,在領域驅動設計中,領域模式成為最最核心的內容。所以我們應當首先理解什么是領域模型。

領域模型是對現實世界中某個業務領域的抽象。我們設計的軟件不是對所有現實世界的模擬,而是對某個領域的模擬,譬如財務領域、稅務領域、企業管理領域等等。這個領域我們稱之為“業務領域”,而在這個領域里工作,并熟悉掌握這個領域中所有知識的人我們稱之為“領域專家”。我們的分析和設計人員對業務領域的熟悉和理解的程度,往往決定我們的軟件是否滿足客戶需求,也往往就決定了我們的軟件是否成功。領域驅動設計理論要求我們在需求分析階段必須非常深入地理解業務領域,采用的方式就是領域模型分析。同時,在這樣一個過程中,應該有領域專家參與,甚至成為分析設計中的一個成員。

過去我們使用用例模型與領域專家交流,直到現在我們依然還在這樣做。用例模型分析是我們分析設計的方法之一,但現在我們又有了一個新的強有力的工具,那就是領域模型分析。與用例模型比較,領域模型更加直觀,可以更加立體地描述現實世界。如果說過去的需求設計文檔是二維世界,用例模型只是二維半,領域模型才是真三維世界。領域模型是一大堆的類圖,它描述的是業務領域中的各個事物,以及事物與事物之間的關系。

從業務領域中獲取知識

說了這么多東西,現在讓我們來點兒實在的東西吧:如何進行領域模型分析?建立領域模型需要從業務領域中獲取素材。獲取領域模型所需素材通常有兩個途徑:與領域專家的現場交流會中獲得,和從用例模型的各個流程中提取名詞或名詞短語獲得。我們將這些獲取的素材經過加工,形成我們在領域模型中的一個又一個的類,這些類我們稱之為概念類。現在的問題是,哪些應當成為領域模型中的概念類呢?如果我引用一堆定義和準則,并不能讓你清楚明了,也許一個生動的比喻更能夠讓你理解深刻。需求分析有時候就像一部部動畫劇,而那些枯燥乏味的概念,紛繁復雜的流程,在這些動畫劇中似乎都突然活了,個個都有語言有性格。在這些動畫劇中扮演的所有角色,就是我們需要的概念類。而他們做的所有動作,就是用例模型中的所有流程。

1 )在業務討論會中繪制領域模型

運用我曾經一篇文章中的實例來更加生動地描述這樣一個過程吧:

在一個陽光明媚的下午,我們一個個西裝革履、精神抖擻地來到了客戶的辦公現場。在一個明亮的會議室里,寬大深褐色的橢圓木桌旁已經聚集了十來個業務人員。看到我們進來,大家握手問候。相繼就座后,互相介紹,往來寒暄,嘮嘮家常。共同的家鄉,或熟或不怎么熟的某個人,都可能成為拉近彼此關系的理由。逐漸,一切開始進入正題。客戶開始絮絮叨叨的描述自己的需求,而我們則在緊張的做著記錄,時不時問一些問題,表明我們的立場,抒發我們的建議。在這樣一個過程中,客戶會描述他們的每一個業務,會講解每個業務的流程,他們會講出一些業務領域的專業詞匯(盡管有些你當時還不太懂)。在這樣一個過程中,作為需求分析員,你應當非常注意業務流程中的一些關鍵詞匯,你應當(在當時或者過后)將它們提取出來,通過詢問客戶,弄清楚他們的定義,以及相互之間的關系。而這些詞匯就是建立領域模型的開始。

這樣的討論會不可能是一次兩次,而是數次。在這樣的討論會中,也許一支筆和一摞白紙會非常有用。在這樣的討論會中,你可以迅速將從客戶那里理解的各種概念和知識,立即在白紙上畫出一個又一個的草圖。那些關鍵詞匯被繪制成了一個個的概念類和它的屬性(如果確實需要),用線條迅速標注出相互之間的關系。在你繪制的時候,客戶會在不斷地給你指正,或者說出了更多的業務知識。一張張的草圖成為了你與客戶交流的工具,也是最初始的領域模型。

這是一個財務軟件的業務討論會,一個業務人員正在跟我講付款單是怎樣制作成憑證的。 每張付款單都有一個商品明細,每個商品明細都有它的價格、數量和金額。 他指著一張付款單向我解釋著。從這句話,我可以提出一些關鍵信息:付款單、商品明細、價格、數量和金額。付款單與商品明細是一對多關系,并且商品明細聚合在付款單中。每個商品明細都有價格、數量和金額,也就是說,價格、數量和金額是商品明細的屬性,這都很清楚。緊接著,他下面的講解就不是那么清楚容易了。 如果按照一張單據生成一張憑證,那么每張付款單生成一張憑證。單據中的每個明細在憑證中生成一條借方分錄和一條貸方分錄。將付款單中的付款科目作為借方科目,將付款單結算方式對應的結算方式科目作為貸方科目。現結的付款單在采購發 票中已制作憑證了,因此不再單獨制作憑證。非預付的付款單不制作憑證,而是其執行付款核銷以后,在核銷單中制作憑證。 經過對以上語言的分析,我們可以繪制以下關系:一張憑證包含多個分錄,是內聚關系。分錄分為借方分錄和貸方分錄兩種。一條商品明細對應一條借方分錄和一條貸方分錄。借方分錄中包含“借方科目”屬性,對應付款單中的付款科目;貸方分錄中包含“貸方科目”屬性,對應的是付款單中的一個什么科目。在這里,你可能對客戶的某些描述不明白,因此要他做出解釋。原來客戶預先制訂了一個規則,付款單中的結算方式分布對應了一個結算方式科目。 OK ,你在繪制的圖形中,把結算方式科目作為關聯類,將結算方式和貸方科目進行了一個關聯。這樣, 付款單生成憑證 這樣一個場景的領域模型就繪制出來。

?

2 )歸納和整理領域模型

在現場討論會中,可能一些關鍵的概念被你忽略掉了。也可能一些關鍵性的關系被你忽略,或者在草圖上并沒有很好地表達,甚至存在謬誤和矛盾。隨著你事后的分析和整理,你從用例模型的流程描述中提取出了更多的概念。同時,隨著你對問題的一步一步深入理解,你開始重構你起初的領域模型。在 Evans 的《領域驅動設計》中,他用大量的篇幅和實例描述和講解了這樣一個過程。另外一個重要的概念是,深入理解和重構領域模型不僅僅是在軟件需求分析的階段完成,它貫穿了整個軟件開發的周期。按照迭代軟件開發的思想,我們絕不能企圖在需求分析階段完成所有的分析(那是瀑布的思想)。隨著我們對業務領域的深入理解,重構和精化領域模型貫穿整個“開發—維護—再開發”的過程中。而這也正符合了現代軟件開發業的發展需求(我參與的項目已經經歷了快 5 個年頭,每年都在經歷著新的開發)。

經過了這樣的、有領域專家參與的、反復討論與整理的過程,我們對業務領域理解將越來越深入,而我們設計的領域模型將越來越貼近現實世界中事物的本質。運用這樣的領域模型圖紙去開發我們的軟件,毫無疑問我們已經成功了一半。(制作領域模型的更多細節見我的相關博客,我也會寫更多的文章討論)

運用領域模型開發軟件

曾經有個笑話是這樣說的:大師們站的高度都是非常高的,高到什么程度?他們都是生活在太空中的。追隨大師是一個高風險的職業,為什么?一不小心就能讓我們因缺氧而死掉。這個笑話非常深刻的道出了追隨大師的關鍵,那就是怎樣“著陸”,也就是如何“落地”。一個高深的理論,如果不能指導我們的實際工作,那么這個理論是沒有價值的,領域驅動設計也是一樣。下面我們來討論一下如何運用領域模型指導我們的軟件開發。

1 )領域模型在我們的軟件框架中扮演的是什么角色

首先第一個要解決的問題是,領域模型在我們的軟件框架中,特別是時下最常見的 Spring+Hibernate 框架中扮演的是什么角色。我們不妨先看看 Evans 是怎樣分層的。在書中, Evans 將系統分為用戶界面層(表示層)、應用層、領域層(模型層)和基礎結構層。從他對各個層的表述我們不難看出,用戶界面層(表示層)就是前端界面,應用層即是 Service 層,基礎結構層即是 DAO 、工具類,以及其它的技術支持類。從這個角度來說, Evans 在他的書中所說的領域層,在我們的框架中就應當是業務邏輯層( BUS ),但事實并不是這樣簡單。在我們現在的框架中,數據與業務邏輯處理被分離了,舉例說吧:

在一個員工信息管理系統中,領域模型可能包含了一個員工類,并且在該類中包含了那些諸如員工編號、姓名、性別、職務等屬性。除此以外,一個員工類肯定也包含了諸如“新增員工”、“修改員工資料”之類的行為。領域模型如此,那么軟件設計時會是怎樣呢?

?

?


一堂如何提高代碼質量的培訓課 之 領域驅動設計
??

在設計一個員工信息管理系統時,它必然包含一個“員工 BUS ”的類,用于執行諸如“新增員工”、“修改員工資料”之類的行為。那么,那些員工的相關屬性被放在哪里呢?它們并沒有放在“員工 BUS ”類中,而是“員工”值對象中(注意:這里的值對象不是 DDD 中的那個值對象,而是 ORM ,或者說 hibernate 中的那個值對象)。領域模型的員工類,在軟件系統中被分離為了“員工 BUS ”類和“員工”值對象類。

正是因為這種數據與業務邏輯處理的分離,令一些人產生了誤解,錯將領域類對應成了 Hibernate 對象(希望他正在看這里)。沒錯,領域模型對應的是 BUS 層,但部分內容被分離到了值對象中。

記得數年前還有 PO VO 的爭論,但現在再也沒有了。按照現在軟件設計的思想,從 UI 一直到數據庫,數據格式變得合成一體了。什么意思呢?頁面上的表單是什么樣子,提交到后臺的值對象就是什么樣子,最后持久化成數據庫表就是什么樣子。按照這樣的設計思想,頁面上表單中的控件 ID 、值對象中的屬性、數據庫表中的字段,都命名成了一致的名稱。這樣的設計大大簡化了程序代碼,但因為表單與值對象長得一個模樣,也使得一些人誤以為領域類對應的是 UI

2 )運用領域模型開發的軟件系統應當是這樣的

不論怎樣,我認為,運用領域模型開發軟件,應當是以領域模型為中心,即以領域模型為藍本進行開發,就如同建筑圖紙與蓋樓一樣。領域模型中的某個概念類,在軟件設計時應當映射成對應的 BUS 和值對象。同時,為了讓開發人員更加專注地去思考那些領域問題,而不為其它技術細節所分析,也許以下方式不失為一個最佳實踐之一:

a. ?????? 領域模型被映射到了軟件框架的 BUS 層中。領域模型中的每個概念類,在 BUS 層中都有對應的 XxxBus ,并且包含了這個概念類中的所有行為(函數)。

b. ?????? 領域模型中的每個概念類都映射成了軟件系統中的一個值對象。這個值對象包含了概念類的所有數據(即那些屬性),以及各概念類之間的關系。但是一個值對象不一定完全對應一個數據庫中的表(比如具有繼承關系的值對象)。特別注意,《領域驅動設計》中提到的值對象與 ORM 中的值對象并不是一個概念,書中的實體也與這里的實體不完全是一個概念。

c. ?????? 軟件系統中的 UI 盡量與值對象保持一致,即,頁面上表單中的控件 ID 盡量與值對象中的屬性保持對應,并通過諸如 DWR 的技術,將 UI BUS 能夠直接交互,簡化過去繁雜的 service 層操作。

d. ?????? 使用 BasicDao 這樣的通用代碼來處理數據庫持久化操作,將值對象直接扔給 insert() update() delete() load() 函數,摒棄了過去為每個業務設計 DAO 的設計;采用 hql 配置文件的方式,將系統需要查詢的語句全部放在配置文件中,然后使用統一的 find() 函數執行查詢,滿足各種各樣的查詢要求。

采用這樣一個設計框架好處多多。首先它大大簡化了軟件開發的內容,過去繁雜的 service 層和 DAO 層統統被砍掉,僅僅保留下 BUS 層和 UI 層(當然必須有諸如 DWR 的強大框架和諸如 BasicDao 自開發的超輕量平臺的支持)。我始終認為,每增加一段代碼,就增加了一份程序出錯的機會。因此我總是不遺余力地試圖簡化代碼,甚至到了發指的地步。

其次,系統的層次劃分會非常清晰。 UI 層就是前端的一堆 jsp html js BUS 就是一堆業務邏輯操作程序(不包含任何諸如 hql 的數據持久化代碼), hql 配置文件可以支持多配置文件,因此被分為了“員工管理”配置文件、“部門管理”配置文件、“薪金管理”配置文件。。。。。。

此外,我不得不說,世界終于變得清靜了。因為這樣一個框架,程序員從那么多羈絆中解脫出來了,他們終于可以全心全意地、以領域模型為中心、仔仔細細地開始考慮那些領域問題了。

在這樣一個框架中,每個 BUS 都有它們自己的職責,這種職責被清清楚楚地標注在各自的注釋中。從此,系統開始以職責為中心設計系統了。

?

3 )運用領域模型開發的一個簡短實例

也許一個實例是最說明問題的,讓我們來舉一個項目評審系統的例子吧。

在進行一次評審前首先要制定一個評審計劃。在這份計劃中,要詳細定義此次評審的評審人、評審材料。顯然,在領域模型中,評審計劃是一個重要的概念,而評審人與評審材料是聚合在評審計劃下的。隨后是在評審過程中制作評審表。每個評審人都要對評審材料制作評審表。最后,評審組織者根據評審人的意見制作評審報告。

在這樣一個需求下,我們應當怎樣設計“制作評審表”的業務呢?在領域模型中,“制作評審表”應當是“評審表”的職責,也就是它所擁有的行為。因此,我們創建一個“評審表 BUS ”,并包含“制作評審表”的函數。隨后,我們開始編寫“制作評審表”的代碼。在這里,我們首先要獲取“評審者”和“評審材料”。由于這兩部分是聚會在評審計劃下的,毫無疑問我們應當調用“評審計劃”獲取“評審者”和“評審材料”(這里的“評審計劃”即可以設計成“評審計劃 BUS ”,也可以設計成“評審計劃”配置文件)。然后,我們通過前端與用戶交互,最終從前端獲得用戶填寫的評審表,利用 dwr 直接形成“評審表”值對象,在“保存評審表”中調用通用 DAO ,持久化“評審表”。

在這樣的設計過程中,首先當然是設計領域模型了。在完成了領域模型的設計以后,應當是按照領域模型設計 BUS 和生成值對象(實際工作中可以先生成數據庫再生成值對象)。隨后開始編寫 BUS 中的各個方法。在編寫過程中,應當將某個方法合理地進行分解,根據職責去調用其它類中的方法(正如評審表去調用評審計劃獲取評審人和評審材料一樣)。通過這樣,功能被合理地分配到 BUS 的各個類中,保證了功能組織的高度內聚。

另一個開發中可能出現的問題這里不得不提。按照理想的領域驅動設計的流程,首先應當是需求分析人員分析和設計出領域模型,然后由開發人員照著領域模型設計開發。但是,由于各種各樣的原因,實際情況可能并不總是這樣。很多時候,開發人員可能沒有得到領域模型而僅僅只有需求文檔。這樣的情況并不意味著開發人員可以摒棄領域模型而直接開始編碼。在編碼前,一個簡短的領域模型分析和繪制領域草圖,就是如同砍柴前的磨刀,是一個必不可少的步驟(這也是領域驅動設計與以往開發模式重要的不同點之一)。

領域模型維護與二次開發

前面,我分別講述了分析人員運用領域模型分析和開發人員運用領域模型設計。在這兩部分,我不斷強調運用草圖快速進行領域模型分析。開發過程總是忙碌而緊湊的,運用草圖快速進行領域模型分析可以大大簡化我們分析的過程,提高設計開發的效率。但是,這并不意味著我們可以隨意處理這些分析草圖。正如建筑設計圖是建筑設施運行維護的重要資料,領域模型以及其它資料也是軟件系統運行維護的重要資料。因此,我認為,這些分析設計草圖應當妥善保管,并且在設計開發完成以后,應當專門進行歸納整理,為今后的運行維護和二次開發提供幫助。

另外,前面我提到, Evans 的領域驅動設計,一個非常重要的思想就是持續地精化。 Evans 認為,我們對業務領域的認識是一個逐漸深刻的過程。隨著認識的逐漸深刻,我們應該在一些合適的時機去重構我們的設計,甚至軟件系統已經設計完成并交付使用以后。這當然要求我們拿出我們的勇氣與魄力。在完成一次重構以后,相應的設計文檔也應當同步更新。

當我們完成了以上這些領域模型的維護工作,一旦有新的開發工作,有新人參與項目的時候,快速熟悉系統并適應工作就應當是順理成章的事情了。而我在《軟件開發的輪回》中提到的那些痛苦的經歷就將不再會出現。

?

也許以上的描述還不夠直觀,表述得還不夠清晰。后面我會通過一個實例詳細闡釋這樣的一個開發過程。

一堂如何提高代碼質量的培訓課 之 領域驅動設計


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 免费一级欧美性大片 | 免费福利视频在线观看 | 免费的黄色网 | 免费日韩视频 | 欧美手机在线观看 | 99久久亚洲精品日本无码 | 日韩视频专区 | 国产98在线传媒在线视频 | 蜜桃网在线观看 | 成人免费在线 | 美女91| 亚洲高清在线看 | 日韩欧美亚洲国产 | 天天色综合色 | 一区二区三区视频在线观看 | 日韩精品一区二区三区中文3d | 国产精品一区在线观看你懂的 | 日韩中文字幕在线播放 | 久久久99精品久久久 | 成人一区二区在线观看视频 | 美国一级特黄 | 亚洲经典在线中文字幕 | 久久精品二 | 日韩欧美国产精品第一页不卡 | 四虎tv在线观看884aa | 久久爱伊人 | 欧美 videos粗暴 | 性夜影院爽黄A爽免费动漫 日韩精品在线一区二区 | 日本在线观看视频网站 | 国产综合精品一区二区三区 | 日韩黄色在线视频 | 国产精品成人自拍 | 青青青青久久久久国产的 | 久久久久久99精品 | 国产精品久久99 | 人人爱天天做夜夜爽 | 99久久久无码国产精品 | 精品亚洲综合在线第一区 | 亚洲欧美色国产综合 | 色婷婷av久久久久久久 | 国产美女精品 |