輕鬆學DDD之一:模型驅動設計

輕鬆學DDD之一:模型驅動設計

  我是2012年開始接觸到DDD(領域驅動設計)的, 後續陸陸續續研讀過幾遍Eric的大作《領域驅動設計:軟件核心複雜性應對之道》,也使用DDD重構過一個項目。總的感受是DDD的一些概念比較晦澀難懂,很難掌握,因此想寫個系列短文,希望能用通俗易懂的語言幫助大家更輕鬆更深入地理解DDD。文章很多都是我個人體會和理解,難免有錯誤,希望大家能及時指正,共同提高。
  本文是系列短文第一篇,介紹DDD的起始概念模型驅動設計

1. 軟件開發方法回顧

  軟件開發可以看做是一個把用戶需求轉換爲可正確運行的程序的過程,其中最關鍵部分是把用戶需求轉換成代碼。我們要學習的DDD實際上就是一種軟件開發方法,它相比之前的軟件開發方法,能更好地應對軟件的核心複雜度。爲了能更好的理解它,我們先回顧下之前的軟件開發方法及其存在問題。
  在上世紀60年代,由於需求簡單,軟件開發以作坊式開發爲主。但是隨着硬件的飛速發展,軟件複雜度也迅速激增,終於在70年引發了軟件危機。爲了應對危機,業界借鑑成熟生產製造管理方法,發展出以“過程爲中心”的瀑布式開發方法。

1.1 瀑布式開發

  瀑布式開發把整個軟件開發過程劃分爲需求分析、方案設計、編碼、測試等階段,希望以這種類似工業流水線的作業分工方式來控制軟件開發的風險和成本。

  1. 需求分析:通過需求分析我們需要明確用戶想要的功能,會怎麼來使用這些功能,通過這些功能能得到什麼價值;消除用戶需求中的二義性、相互矛盾的地方;細化各種正常/異常功能場景,驗收準則,性能、可靠性等非功能性約束。
  2. 設計:在設計階段需要根據需求分析結果決定軟件的總體實現方案。在系統設計階段會確定子系統劃分,進行開發、運行平臺、數據庫等關鍵技術選型;在方案設計階段則會明確模塊劃分,模塊內部架構,協作流程,關鍵算法等。
  3. 編碼:根據設計完成代碼編寫。
  4. 測試:測試軟件是否滿足用戶需求。
    輕鬆學DDD之一:模型驅動設計
      上圖展示了應用瀑布式開發方法的軟件開發流程,我們可以看到這種方法可以通過專業分工和流水作業來分解複雜度和提升效率,這在在一定程序上緩解了軟件危機。但是與工業生產不同,軟件需求和開發過程存在很多不確定因素,因此這種方法在應用過程中也發現了很多問題。
  5. 每個需求的各階段由不同的人依次完成,階段之間用文檔傳遞知識,各階段之間缺乏溝通和反饋,錯誤和理解偏差不能及時糾正,往往影響軟件的正確交付。
  6. 每個需求輸出各自的分析、設計文檔,沒有整合。隨着軟件規模增長,分析和設計會喪失對軟件整體性的把握,進而影響分析和設計的全面性和正確性。
  7. 由於缺乏反饋,分析、設計和代碼之間的差異會越來越大,耗費大量人力編寫的分析設計文檔會逐步失去價值,協作會越來越困難,軟件也越來越難以按期正確交付。

  爲了解決瀑布式開發的開發效率低下、響應需求速度慢的問題,輕量級的,更能適應變化的敏捷軟件開發方法被普遍認可並迅速流行起來,極限編程就是其中的一種。

2 極限編程

輕鬆學DDD之一:模型驅動設計
  XP主要由13個實踐構成,是一種近螺旋式的開發方法。它將複雜的開發過程分解爲一個個相對比較簡單的小週期;通過積極的交流、反饋以及其它一系列的方法,開發人員和客戶可以非常清楚開發進度、變化、待解決的問題和潛在的困難等,並根據實際情況及時地調整開發過程。
  爲了與瀑布式開發做對比,我們把XP簡單理解爲下圖:
輕鬆學DDD之一:模型驅動設計
  通過上圖我們可以看到,XP沒有劃分分析、設計、編碼和測試等階段,需求可以在一個週期爲1~2周的迭代中快速交付。XP之所以能做到快速交付,有如下幾個原因:

  1. 客戶、業務專家、開發、測試大家坐在一起完成需求開發,面對面溝通取代了文檔,節省了文檔編寫、維護的工作量。
  2. 通過簡單設計、TDD、ATDD、CI等工程實踐保證分析、設計、編碼、測試之間更快速的反饋和充分的並行化,有效縮短了開發週期。
  3. 通過不斷重構代碼來保證代碼更加簡潔,能更好地反應軟件的核心複雜度。
  4. 通過結對、代碼集體所有權、系統隱喻、編碼規範、完整團隊促進了技能和知識的共享。

  XP非常反對做預先設計,需求分析與設計會被拆分到用戶故事乃至TDD的小步迭代中去做,在每個小迭代中代碼只會根據當前需求簡單實現;當在後續迭代過程中發現代碼難以滿足新需求時,需要通過重構來增加代碼對新需求的適應性,以便能夠快速實現新需求。這種做法固然能帶來很多好處,但是也存在一些缺陷:

  1. 如果軟件複雜度高,需求之間有着複雜的關聯,開發在沒有很理解業務邏輯就貿然開始寫代碼,會帶來非常大的重構成本,甚至於需要重寫。
  2. 只有代碼承載業務共識,維護業務共識的成本高,最終導致難以維持業務共識。大家交流的共識除了存在於頭腦中外,只存在於代碼中,這對於代碼的業務表達力和專家/客戶的代碼理解能力都提出了非常高的要求,最終可能導致大家對於業務的理解的差異會越來越大。

3. 模型驅動設計

輕鬆學DDD之一:模型驅動設計
  爲了彌補XP在應對軟件核心複雜度的缺陷,eric在2003年提出了一種新的方法,他認爲我們需要引入領域模型並圍繞它來做需求分析和軟件設計,這就是模型驅動開發。這一論述有以下幾個要點:

  1. 模型是統一的,它反映了領域的核心複雜度,而不是領域內每個需求面面俱到的細節。一些不涉及軟件核心價值且不影響全局的細節可以在放在迭代中考慮,相關知識沉澱在代碼中即可,就像XP做的那樣;但是涉及軟件核心價值,或者影響全局的業務邏輯需要納入領域模型中做統一細緻的分析,並在軟件生命週期內不斷地演進精煉。
  2. 模型是交流和協作的中樞。客戶、業務專家、開發、測試等各種角色一起參與構建模型的,大家基於共同的模型來做交流和協作。
  3. 模型與代碼是綁定的。代碼修改能方便地同步到模型,模型修改也能方便地同步代碼。這要求模型不只體現問題域的知識和約束,也能體現實現域的知識和約束;涉及業務邏輯的代碼需要不斷提煉,剝離技術實現細節,以便能很好地表達模型。

  最後總結下,模型驅動設計通過對軟件核心複雜度的統一建模,解決了瀑布式開發在需求分析、軟件設計上的溝通、反饋和知識整合上的缺陷,也解決了XP極簡主義設計存在的缺陷。
  文本重點敘述了我們爲什麼需要領域模型,領域模型構建需要注意的幾個基本原則,但是具體要怎麼來構建領域模型呢?請看下一篇《輕鬆學DD之二:如何高效消化知識》

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章