1. 程式人生 > >領域驅動設計,讓程序員心中有碼(二)

領域驅動設計,讓程序員心中有碼(二)

導致 很多 集成 努力 設計模型 思考 思想 內聚 單反

           引子,軟件工程沒有銀彈

   上一篇博文,拋出了一個問題,領域驅動設計真的是萬能的良方嗎?對於這個問題,大家的答案無疑是一致的,作為一種非常受軟件行業歡迎的軟件思想,領域驅動設計固然有很多優點,卻並非萬能。

   回到十年前,第一節軟件工程學的課堂上,我們的老師就告訴了我們一句真理,軟件工程沒有銀蛋,這句話說的是,軟件工程領域,從來沒有一種思想或理論能夠帶來成倍的效率提升。不知不覺,十年過去,我們大概可以看到,軟件開發新技術日新月異,新語言層出不窮,但是無論哪種技術,都不見得相對於其所對標的技術取得了成倍的提升。技術尚且如此,理論就更不用說了。

領域驅動設計,近年來受到技術圈的廣泛追捧,主要得益於微服務技術的發展。一千個讀者有一千個哈姆雷特,而不同的人往往對這種理論有不同的看法。如果問一個.net開發者領域驅動是什麽,大概他會說是abp架構。ABP架構作為完全按照領域驅動設計思想構建的技術架構,目前得到了社區的廣泛追捧。然而,領域驅動架構和領域驅動設計,依然是道和術的區別,開發者在學習領域驅動架構的同時,也應該了解領域驅動設計。那麽領域驅動設計究竟是什麽的東西?由於時間和篇幅有限,我無意通過代碼介紹如何實現一個領域驅動的功能,而是希望把領域驅動設計的基本思路進行梳理,期待能通過我的梳理,拋磚引玉,給大家帶來啟迪

    一,領域驅動設計,不錯的選擇  

  作為現代軟件工業發展的產物,敏捷開發和極限編程,實現了生產力的解放,通過拋棄傳統研發模式中留下的臃腫的設計文檔,實現了勞動生產力的提升,無數互聯網公司,依靠靈活的開發手段,為產品插上了快速開發的翅膀。開發者們不用加班,分分鐘就把代碼擼完,然後把產品質量關把好,發布,嗯,早早的就回家休息了。然而,隨著產品功能的逐漸增加,團隊自然而然也需要擴展。可是,團隊成員越來越多,代碼質量成為一個難以把控的問題。如何保證產品功能的一致性?如何保證功能符合產品的需求?管理者們不厭其煩,每天開會必須提開發質量,必須強調變量命名,註釋,設計原則,設計模式,然後每天一次集成,代碼審查估計已經不現實了。於是,作為面子的產品質量尚且有測試把關,而作為內臟的代碼質量本身,成為上帝的骰子,好與壞全靠開發者們的自覺性和經驗。

技術分享圖片

    冰山,在軟件產品華麗外表之下,究竟深藏著多少問題?
技術分享圖片

一個復雜的數據庫關系模型圖

  領域驅動設計在這樣的場景下推出來的一種理念。軟件系統的復雜度是開發者們沒辦法避免的客觀情況,而根據領域的實際情況,建立模型是解決問題行之有效的方法。在實際過程中,我們需要領域專家與開發者一起,共同努力,以一種特殊的方式來進行溝通,並通過模型將實際生活中的問題抽象化。 
  領域驅動設計的核心是建模,實際上對於大部分開發者而言,建模是一個基本技能,卻並非每個人都能熟練的掌握。技術人員都普遍對他們工作領域有關的知識不感興趣,而更願意從事精細的框架工作,例如通過技術手段解決實際問題。而學習業務領域和領域建模的工作往往留給別人去做。然而,實際上,軟件核心的復雜性,既包括需要直接面對的技術問題,而客觀存在的業務問題卻也是不可忽視的,過份重視技術,輕視建模,只會導致工作重心的偏離。甚至可以說,過份的重視領域驅動架構基礎設施本身,而忽略了建模過程,在後期執行過程中可能會導致不可控制的風險。對於這一點大家都是容易理解的,以前的架構,簡單反而容易維護,而系統架構復雜了,反而提高了學習成本導致不容易維護。
  軟件設計的基本原則是“高內聚,低耦合”。作為一個復雜的軟件工程,依靠領域驅動建模,將緊密聯系在一起的業務設計成一個領域模型,讓領域模型內部隱藏細節,這樣讓領域模型與領域模型之間的關系變得簡單,將極大的降低復雜業務之間千絲萬縷的耦合關系。
  

技術分享圖片

                        面向領域設計的模型圖 
             二,領域設計的要素,統一語言和建模及文檔
   在進行設計之前,我們有必要建立基本的原則,那就是統一語言,模型,和設計文檔。
  1 統一語言
  在日常討論過程中,我們需要跟領域專家討論,往往大家都是自己行業內的專家,也意味著大家都有自己的表達問題的方式和自己的理解,這有可能導致需求支離破碎。例如對對方表達的術語不了解,會形成雞同鴨講的情況。因此,需要建立一個能夠互相溝通理解的語言環境,例如,互相的交流雙方的術語,並試圖利用雙方都能理解的詞語進行問題的分析。也許在最開始這樣共同語言並不能很好的運作,但是卻可以在後期逐漸完善。我們的開發者應該定期的了解領域所在行業的業務知識,擴充自己的知識面,這也有利於我們與領域專家的交流。
  2 建模和畫圖
  在我們工作過程中模型無處不在,不管是在紙上繪制的簡單模型,或者使用專業軟件繪制的各種模型,都是模型。領域驅動設計本身,依然依賴於模型驅動設計。學會建模對於廣大開發者來說,都是一項基本技能。可以說,代碼語言是為了與其他開發者進行溝通交流,那我們建立的各種軟件設計模型將極大的方便不同領域的人員進行交流。建模也可以稱之為語言的一部分利用uml建立類圖,是一種可以比較易於接受的方式。我們可以采用以下手段來建立領域模型。
  1)建立一個與實現綁定的模型。初版的模型也許很簡陋,但是它可以成為一個基礎,然後在後期逐漸完善。
  2)建立一種基於模型的通用語言或表達形式和機制。通過通用語言讓參與項目的所有人理解模型。
  3)開發一個蘊含豐富知識的模型。模型不是單純的數據結構,它更是各類知識的聚合體。
  4)提煉模型,模型應該能在項目過程中動態改變,發現新的概念就加進來,過時的概念就適時移除,避免臃腫。
  5)頭腦風暴和實驗。模型在於實踐和應用,它需要項目參與者共同的努力,而頭腦風暴是發揮集體智慧的良好方式。對模型進行實驗或者進行場景的模擬,有利於讓模型更符合需求。
  當然,對於領域專家而言,不同類型的模型也許無法理解,例如類圖可能過於復雜,可以使用畫圖的形式,通過解釋性的圖形或者模型,可以讓不同層次的人都能獲得一致的理解。
  3 設計文檔
  設計文檔依然是不可拋棄的重要資料,雖然設計文檔可能不利於維護,卻仍然不可拋棄。畢竟開發過程中,通過代碼和模型,有可能會導致關鍵信息的丟失,而且有的不能直接參與討論的領域專家需要通過文檔才能了解之前討論的情況,甚至可能畫圖會形成很多歧義,這也需要解釋性的文檔才能說清楚。為了讓文檔變得更加有效,不建議重復贅述已知的信息,而關鍵信息更改後,應該盡量保持最新。
完全依賴代碼或架構的自解釋特性目前似乎已經成為大家的普遍習慣,但是代碼可能存在歧義,或者有的方法本身就無法表達方法的本質含義,最終導致代碼成為無法理解的神之領域,這種問題已經不是一個單純的領域驅動架構能夠解決的。如果為了讓代碼來解釋模型,我們所有人必須時刻抱著一絲不茍嚴於律己的態度,才能寫出完全符合領域模型的代碼,問題是這種方式現實嗎?
  4 概念總結:
  1)領域就是問題域,有邊界,領域中有很多問題;
  2)任何一個系統要解決的那個大問題都對應一個領域;
  3)通過建立領域模型來解決領域中的核心問題,模型驅動的思想;
  4)領域建模的目標針對我們在領域中所關心的問題,即只針對核心關註點,而不是整個領域中的所有問題;
  5)領域模型在設計時應考慮一定的抽象性、通用性,以及復用價值;
  6)通過領域模型驅動代碼的實現,確保代碼讓領域模型落地,代碼最終能解決問題;
  7)領域模型是系統的核心,是領域內的業務的直接沈澱,具有非常大的業務價值;
  8)技術架構設計或數據存儲等是在領域模型的外圍,幫助領域模型進行落地;
    三、問題思考

  掌握建模和基本的步驟,意味著一切剛剛開始。道阻且長,行則將至,領域驅動設計,不僅僅是一種簡單的建模思想或技術架構,更是一種挑戰。在選擇之前,是否需要思考一下,這一套體系,真的適合在你的團隊中運行麽?如果要切實的運行,還需要付出多少代價?尤其是對於領域模型而言,如果缺乏合理有效、而且持續叠代的設計,你難道不覺得最終所有的模型僅僅只是一種數據結構設計嗎?
參考資料:
1.《領域驅動設計-軟件核心復雜性應對之道》
2.https://blog.csdn.net/three_bird/article/details/51336834
3.https://blog.csdn.net/heweimingming/article/details/78661540


領域驅動設計,讓程序員心中有碼(二)