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

中興開發者社群發表於2017-12-28

點選上方“中興開發者社群”,關注我們

每天讀一篇一線開發者原創好文

640?wx_fmt=png&wxfrom=5&wx_lazy=1


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

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


1. 軟體開發方法回顧

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


1.1 瀑布式開發

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

  1. 需求分析:通過需求分析我們需要明確使用者想要的功能,會怎麼來使用這些功能,通過這些功能能得到什麼價值;消除使用者需求中的二義性、相互矛盾的地方;細化各種正常/異常功能場景,驗收準則,效能、可靠性等非功能性約束。

  2. 設計:在設計階段需要根據需求分析結果決定軟體的總體實現方案。在系統設計階段會確定子系統劃分,進行開發、執行平臺、資料庫等關鍵技術選型;在方案設計階段則會明確模組劃分,模組內部架構,協作流程,關鍵演算法等。

  3. 編碼:根據設計完成程式碼編寫。

  4. 測試:測試軟體是否滿足使用者需求。

0?wx_fmt=png

上圖展示了應用瀑布式開發方法的軟體開發流程,我們可以看到這種方法可以通過專業分工和流水作業來分解複雜度和提升效率,這在在一定程式上緩解了軟體危機。但是與工業生產不同,軟體需求和開發過程存在很多不確定因素,因此這種方法在應用過程中也發現了很多問題。

  1. 每個需求的各階段由不同的人依次完成,階段之間用文件傳遞知識,各階段之間缺乏溝通和反饋,錯誤和理解偏差不能及時糾正,往往影響軟體的正確交付。

  2. 每個需求輸出各自的分析、設計文件,沒有整合。隨著軟體規模增長,分析和設計會喪失對軟體整體性的把握,進而影響分析和設計的全面性和正確性。

  3. 由於缺乏反饋,分析、設計和程式碼之間的差異會越來越大,耗費大量人力編寫的分析設計文件會逐步失去價值,協作會越來越困難,軟體也越來越難以按期正確交付。

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


2 極限程式設計

0?wx_fmt=jpeg

XP主要由13個實踐構成,是一種近螺旋式的開發方法。它將複雜的開發過程分解為一個個相對比較簡單的小週期;通過積極的交流、反饋以及其它一系列的方法,開發人員和客戶可以非常清楚開發進度、變化、待解決的問題和潛在的困難等,並根據實際情況及時地調整開發過程。
為了與瀑布式開發做對比,我們把XP簡單理解為下圖:

0?wx_fmt=png

 通過上圖我們可以看到,XP沒有劃分分析、設計、編碼和測試等階段,需求可以在一個週期為1~2周的迭代中快速交付。XP之所以能做到快速交付,有如下幾個原因:

  1. 客戶、業務專家、開發、測試大家坐在一起完成需求開發,面對面溝通取代了文件,節省了文件編寫、維護的工作量。

  2. 通過簡單設計、TDD、ATDD、CI等工程實踐保證分析、設計、編碼、測試之間更快速的反饋和充分的並行化,有效縮短了開發週期。

  3. 通過不斷重構程式碼來保證程式碼更加簡潔,能更好地反應軟體的核心複雜度。

  4. 通過結對、程式碼集體所有權、系統隱喻、編碼規範、完整團隊促進了技能和知識的共享。

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

  1. 如果軟體複雜度高,需求之間有著複雜的關聯,開發在沒有很理解業務邏輯就貿然開始寫程式碼,會帶來非常大的重構成本,甚至於需要重寫。

  2. 只有程式碼承載業務共識,維護業務共識的成本高,最終導致難以維持業務共識。大家交流的共識除了存在於頭腦中外,只存在於程式碼中,這對於程式碼的業務表達力和專家/客戶的程式碼理解能力都提出了非常高的要求,最終可能導致大家對於業務的理解的差異會越來越大。


3. 模型驅動設計

0?wx_fmt=png


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

  1. 模型是統一的,它反映了領域的核心複雜度,而不是領域內每個需求面面俱到的細節。一些不涉及軟體核心價值且不影響全域性的細節可以在放在迭代中考慮,相關知識沉澱在程式碼中即可,就像XP做的那樣;但是涉及軟體核心價值,或者影響全域性的業務邏輯需要納入領域模型中做統一細緻的分析,並在軟體生命週期內不斷地演進精煉。

  2. 模型是交流和協作的中樞。客戶、業務專家、開發、測試等各種角色一起參與構建模型的,大家基於共同的模型來做交流和協作。

  3. 模型與程式碼是繫結的。程式碼修改能方便地同步到模型,模型修改也能方便地同步程式碼。這要求模型不只體現問題域的知識和約束,也能體現實現域的知識和約束;涉及業務邏輯的程式碼需要不斷提煉,剝離技術實現細節,以便能很好地表達模型。

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


擴充閱讀

乾貨|漫遊計算機系統之虛擬儲存器

640?wx_fmt=jpeg

相關文章