談DDD前,咱們先思考一個問題,什麼是好的代碼?面試
易於維護,邏輯清晰,健壯,可擴展性強…對於這個問題每一個人都有本身的答案,但至少有一點好的代碼必定是易讀的。不妨在寫每一個函數前想一想若是交付測試,可否作到見名思意,若是存在過多的溝通成本或多或少是存在一些問題的。回到設計上也同樣,好的設計也應當便於理解,能讓人抓的注重點。編程
DDD想必你們也都聽過,domain-driven design領域驅動設計,也是最近幾年炒得火熱的名詞,相關的博客和書籍也有不少(推薦閱讀下《領域驅動設計》)。這裏不過多掃盲DDD是什麼,但從與小夥的交流來看,僅僅經過書本仍是很難理解DDD的精髓的(初學者剛開始看不懂《領域驅動設計》是很正常的,不要着急)。這裏我談下我對DDD的理解,但願對對你們有所裨益。設計模式
咱們須要認識一點DDD不一樣於23種設計模式有標準的實現,換句話說DDD不是以工具化(框架)的方式直接應用於咱們項目中的(不要抱着過於功利化的心態去學習DDD),DDD更多的是一種編程思想或者說是對OOP落地的工程化指導。OOP所倡導的高內聚低耦合,也是咱們使用DDD所要達到的最終目標(微服務的改造也是要作到服務的高內聚低耦合,這也是爲何領域可以最終以微服務的形式存在的緣由,由於他們本質上解決的是共同問題)。安全
大部分人都學過OOP,一樣不少人並不知道OOP該如何在咱們的實際項目中落地。題外話,我以爲這個問題和咱們的高等教育和如今行業發展示狀是有關的,沒有維護糟糕的系統的經驗想讓一個初學者理解理解面向對象的意義不現實,而且在工做要求上這一塊也是被輕視的(我想畢業後的面試應該不多有人會被問到面向對象了吧,更多的會被問到對框架原理的理解使用),愈加成熟的技術框架的應用也從某種程度上掩蓋了技術人員在這方面的缺失。這裏的改變,第一點我想說的是思想的轉變,對面向對象(或DDD)的理解的重要程度應當不啻於咱們對於高級語言底層知識的重視度,高級語言底層知識的掌握是技術技巧的基礎,而面向對象是工程化技巧的基礎。框架
再回到項目開發落地上,使用DDD咱們須要做出什麼樣的變化。首先咱們談談不用DDD的開發過程,通常而言咱們都繞不開MVC(我指的MVC不只限於MVC框架,SOA中的對外API從某種程度上說也是VIEW的一種體現),在這個思想的指導下咱們通常的開發過程是對外設計API、對內設計存儲層(DB)以及系統間交互流程。這個過程當中咱們每每聚焦的是對外的API實體及存儲的實體設計,而API實體、存儲層實體他們自己解決的是數據傳輸的問題,沒法去承載過多的業務意義(試想一下你的業務邏輯被寫到了API實體內運行在其餘人的服務進程中,這豈不是反服務化?而存儲層的實體中加入過多的邏輯,很容易致使存儲層的邏輯穩定性出現問題)。在這個前提下,作的好,咱們能守住MV(model&view)對外來隱藏好內在邏輯,但對內卻將複雜易變的C(control)至於混沌之地(每每咱們會採用過程化的方式去實現,將」數據」的生命週期的管理分散到了不一樣的函數中)。使用DDD最重要的就是改變咱們原有的過程化的數據爲驅動的編程模式,而是以實體爲核、事件驅動來響應數據變化(談到這裏,想必會有人質疑,以爲「虛」)。那麼先談談DOMAIN-DRIVEN的好處?dom
傳統的數據驅動的編程模式的缺陷是什麼?上面也談到了,「數據生命週期」的控制是被分散在不一樣的函數中,而一旦產生了這種分散是很難再作到高內聚的,想必你們也常常遇到數據在某些不該該被修改的狀態下卻產生了變化。因此在使用DDD的過程當中咱們首先聚焦的是領域實體的創建,並嘗試經過領域實體去解釋上面談到的「數據生命週期」(怎麼創建領域實體能夠參考《領域驅動設計》中第五章的介紹,在結合項目去體會一下)。數據是沒有生命週期的,但實體是有的(這也是如何識別實體和值的最關鍵區別),在這個前提下,咱們徹底可以控制讓實體在什麼樣的狀態響應什麼樣的事件(安全性、惟一性)。函數
另外咱們經過實體來驅動業務的過程,實際上實體也是對應用層邏輯與存儲層的隔離,而且這個過程當中咱們創建的是充血模型,這就給避免後續業務的變化去過多的影響存儲設計或者應用層設計,能將變化約束在模型中。給實體賦能帶來的另一個好處是讓單元測試變得更容易落地,由於這個過程當中隔離了外部數據依賴、存儲依賴,避免過長的數據鏈條,方便將咱們的測試重點聚焦於對實體的職能(這也是咱們核心邏輯所在)。微服務
說到這裏,DDD應該是咱們落地微服務、MVC的一個補充,從實踐經驗來講,咱們不妨先忘掉接口、忘掉DB結構設計,先去嘗試創建模型,去想一想每一個需求對應到這個模型的什麼職能(這個過程甚至只須要是一些僞代碼或者功能草稿)。創建完模型,再經過系統間的交互流程去驗證模型是否正確,進而向上去設計接口、向下去設計存儲結構。工具
未完待續...單元測試