本文的部分內容最先出現在Scott Millett和Nick Tune的《領域驅動設計的模式,原理和實踐》(Wrox 2015)一書中。

本文所能提供的最重要的一條建議(除了別忘記抹防晒霜[1]),就是不局限於理解自己所在的領域,而是要對齊業務願景、目標、戰略以及約束。應該與業務方分擔同樣的憂慮:是否會超出預算?如何在新領域中成功展示自己的價值主張?如何消除實施過程中的瓶頸?如果能對自己的業務有更基本的理解,不僅能更深入地了解領域,提出有效解決方案,還可以主動識別出真正具有商業價值的產品和機會。

軟體正在「吞噬」世界,IT已是所有組織的關鍵能力,這些已經成為共識。不過,大多數技術團隊似乎對其所從事的工作領域只有一個淺薄的理解。根據我的經驗,相對於整體戰略和業務需求而言,這些團隊更多地只關注技術本身。技術進步為業務發展和演化所提供的大量機會,大多數公司都沒能抓住。這不是因為業務同事們對技術缺乏悟性,而是因為他們沒能與技術人員進行對齊。而這種業務與技術的對齊,恰恰就能創造出讓步的藝術[2]。缺乏這一點,他們就看不到機會。

現代企業中,非技術人員和技術人員之間的界限開始變得模糊。我看到在一些更加進步的公司里,技術人員會參與公司業務的決策。而這種決策權,正是由於技術人員運用「讓步的藝術」而獲得的。「讓步的藝術」讓技術人員找到了技術的機會,從而消除了生產環境的約束,創造了更大的商業價值。他們對齊了業務的實際需求,並且可以自主提供滿足這些需求的解決方案。

本文是關於我的故事,其中包含了 DDD 如何幫我更多地學會怎樣解決問題,並幫助人們重新關註解決方案的產生方式,人們是如何溝通和協作的,以及技術人員如何提供解決方案,並識別超出業務同事預期的機會。

1. 免責聲明

「不具天賦,唯有早起。」 - Henry Rollins

這篇文章都是從我自己的角度出發,因此僅限於個人經驗。我不是顧問,也不曾作為合同工工作過,所以我的經驗僅限於電子商務領域。但是在我看來,這些領域已經足夠複雜,從而可以從領域驅動設計的實踐中受益。我不是領域驅動設計藝術的絕地大師[3],也沒有參加過 Eric Evans 的「淑女學堂」[4](有這種學堂嗎?如果真的有,請發給我詳細信息),所以除了說些經驗教訓,我實在給不出其它的金玉良言。

我很慶幸,自己的職業生涯始終處在這樣一個行業,裡面有全世界最慷慨的人。軟體社區非常擅長提供意見、建議和經驗,不過這些都需要放在特定上下文中去理解,當然也要根據其所應用的上下文進行調整。

因此,雖然不能保證我的經驗之談能解決你所有的問題(或任一問題),但希望你能在我多年來的經驗教訓中找出一些東西。這些東西或許可以在你的 DDD 實踐之旅中,起到催化劑的作用。不過,請謹記,這些完全取決於上下文,而本文只描述我個人的上下文。

2. DDD的基本概念

領域驅動設計既是一種思維方式,也是一系列已按優先順序排序的事項,旨在加速處理複雜領域的軟體項目的開發進程。 ——Eric Evans《領域驅動設計》(2003年)

在談論有關 DDD 的心得,以及對 DDD 的首要原則的看法之前,我想快速回顧一下領域驅動設計的基本概念。因為在我看來,這些概念看似簡單,但經常被誤解。因為細節是魔鬼。

深入淺出DDD:

  • 將較大的問題域,提煉為較小的子域。
  • 識別核心子域,以明確什麼是重要的。核心域是對業務更有價值的域,需要付出更多的關注、精力和時間。
  • 與領域專家合作,來發現一種分析模型,以提供解決問題或開拓機會的解決方案(尤其是在核心領域)。
  • 在代碼模型中,要使用在分析模型中所使用的同樣的統一語言。使用戰術模式[5],將技術代碼與領域代碼分離,以避免額外的複雜度。
  • 如果模型中的語言有二義性,或者模型對於單個團隊來說太大,那麼就需要將模型拆分為較小的模型。要將模型封閉在邊界內,以保證完整性。在處理多個模型時,重要的是讓人們在上下文中能理解它們。
  • 保留上下文地圖,以理解所有模型在人際溝通和技術層面的相互關係。
領域驅動設計概覽

2.1. 提煉問題領域以明確什麼是重要的

開發團隊和領域專家使用分析模式和知識消化的過程,將大型問題域提煉為更易於管理的子域。核心子域能在這種提煉中被揭示出來,並能解釋軟體編寫的原因。核心領域是正在開發的產品背後的驅動力。例如,在航空公司定價系統中,演算法可能是軟體成功與否的關鍵。該系統當然也需要身份和訪問控制管理,但這只是為了支撐核心域。在不同的領域,比如政府文件控制,安全和訪問可能是核心領域,而內容管理只起到支撐的作用。這裡的重點是,DDD強調需要將精力和人才集中在核心子域上,因為這才是最有價值的地方,也是軟體成功的關鍵。

2.2. 創建解決問題的模型

在了解需要集中精力的核心領域之後,技術團隊和領域專家可以開始提出一個解決方案,並以分析模型的方式表現出來。這通常以圍繞白板討論的協作方式來完成,其間一般會採用頭腦風暴的形式,與業務專家一起分析具體場景。這個過程會促進所有參與者進行對話,深入洞察,並對領域達成共同理解。其目的是發現並達成對問題域的共識,以便使用統一語言創建模型。該語言可以用來實現業務用例,消除約束並開拓機會。

當發現有用的分析模型時,代碼模型也就隨之出現。切記,這個過程並不像在這裡解釋的那樣簡單。通常在模型探索過程中,代碼模型就已經出現了,以用於構建原型來驗證可行性。代碼模型通過使用共享的統一語言的方式,綁定到代碼分析模型上的。統一語言能確保兩種模型保持同步,這在模型演化的過程中十分有用。在任一模型中所獲得的洞見都是共享的,兩邊的知識也會彼此疊加,這有利於更好地解決問題,並使業務和開發團隊之間的溝通更加清晰。

戰術模式用於保持代碼模型的適應性,並將領域代碼與基礎設施代碼相隔離,從而避免了在綜合考慮技術和業務問題時所導致的意外複雜度。

2.3. 拆分大模型以避免二義性和腐壞

可以將大模型拆分為較小的模型,並逐一定義在單獨的限界上下文中,來減少存在二義性的術語。另外避免多個團隊在一個模型內並行工作,以此降低複雜度。限界上下文定義了模型的適用性,能確保其完整性得以保留,並能在模型周圍形成保護邊界,有助於防止軟體演變成「大泥球」。限界上下文的劃分因素,不僅包括編程語言和團隊構成,還包括術語和領域概念的二義性、子域和業務能力的一致性、自治團隊及其辦公地點、遺留代碼庫、需要集成的第三方,以及許多其他因素。

3. 為什麼團隊需要重新調整DDD的首要原則

本文主張,領域驅動設計的實踐重點,應放在技術範圍之外。許多人首次接觸領域驅動設計時所看到的內容,就是戰術設計模式,以及事件溯源或CQRS等技術。他們從未體驗或學會欣賞DDD的真正力量,因為他們不了解或不關注軟體構建的非技術方面的內容。而正是對問題空間的深刻理解,以及對核心領域的不懈關注,才使得有效和協作式的模型驅動設計,能夠產生可行的解決方案。只有到這個時候,才需要利用戰術模式來組織代碼,以減少意外的複雜度。

3.1. 為什麼領域驅動的解決方案往往無法實現

解決方案無法實現的原因,以及需要關注首要原則的原因,不是缺乏編程能力或技術專長,而是因為缺乏理解、溝通和業務知識。我並不是說技術人員懶,以至於總是無法將產出轉化為成效。這種理解的缺乏,源自開發人員捕獲他們所處理的問題領域知識的方式。換句話說,如果開發人員和客戶無法有效溝通,不能對齊首要目標,那麼即使擁有世界上最有成效的程序員,也最終無法收穫有意義的成效。

擁有適當的軟技能,能避免被禁錮在模型的早期版本上,這一點也很重要。例如,當以往的理解被證明是錯誤的,且不能意識到基於此理解所構建的模型將無法勝任工作,那麼即使這個模型在技術上柔性很強,也是枉然。

3.1.1. 過分追求戰術模式的完美

僅關注編寫代碼的團隊,通常會聚焦於DDD的戰術模式。他們會將這些類似「積木」的模式視為聖經,而不會將其視為指南,更不會去想何時可以違反這些規則。他們將精力花費在遵守這些模式的規則上,卻不知道要將這些精力用於理解為什麼代碼需要這樣寫。DDD是一個探索下面事情的過程——需要寫什麼模型,為什麼需要這樣寫,以及應該投入多少精力。從Eric撰書至今,雖然戰略模式[6]依然忠實於該書的原始文本,但DDD戰術模式的演化卻最為迅速,另外如何提煉問題空間的技術也取得了很大進展,這一點稍後會討論。事實上,理解要編寫什麼模型,以及如何在限界上下文中將其開發出來,比起開發團隊如何創建出領域模型更重要。比起如何在代碼中實現模型,理解要解決什麼問題,以及為何要解決這個問題,才是一個需要正確把握的更重要的過程。

3.1.2. 高估示常式序的價值

「我能看一個示例應用程序嗎?」,這是軟體開發論壇中最常被問到的一個問題。確實會有不少很好的解決方案,能展示使用DDD過程後所創建的產品成果。但如果僅研究代碼產出物,是無法揭示DDD所帶來的更大的好處的。用白板討論,喝咖啡時交流,和領域專家在走廊上對話,這些才是DDD大顯身手的舞台。當一些小的重構忽然揭示出一個隱藏的領域概念,從而能啟發更深層次的洞察時,DDD的好處就體現出來了。示常式序既不會揭示領域專家和開發團隊之間的許多對話和協作,也不會展現對問題域的更深入理解的頓悟時刻。

代碼產出物雖然是成年累月努力工作的結果,但只呈現最後一次迭代的樣子。而在此之前,代碼會發生多次變化。隨著時間的推移,代碼將持續演化,以支持不斷變化的業務需求。今天有用的模型,可能會與產品未來迭代中所使用的模型有很大不同。

如果只憑閱讀DDD方法所構建出的方案,就想仿效其原理,那麼就無法體驗其中大量的原則和實踐,並會導致關注點過多地集中在代碼構造塊上。實際上,如果不熟悉該領域,就根本無法感知底層的領域模型是否富有表現力。

3.1.3. 錯失DDD的真正價值

一個過分關注戰術模式的團隊,容易錯失DDD的核心優勢。DDD真正的價值,在於創建特定於上下文的共享語言,使開發人員和領域專家能夠有效地協作,創建解決方案。而代碼只是該協作的副產品。消除對話中的二義性,讓溝通變得輕鬆,才是目標。為了讓團隊能更好地解決問題,在編寫代碼之前,必須要打好上述基礎。問題不僅可以通過代碼來解決,還可以通過與領域專家的協作、溝通和探索來解決。評判開發人員的標準,不應該看他們敲代碼的速度,而應該看他們是如何解決問題的(無論是否使用代碼)。

3.2. 回到首要原則

DDD的首要原則,是強調技術團隊的關注重點應與領域保持緊密一致,並且應該從這個方向推動所有決策,而不僅僅關注技術。畢竟在DDD里,命名揭示線索,領域就是業務,要在「這是否有助實現業務目標?」的啟發下,驅動所有設計決策。如果對目標沒有充分理解,那麼就不太可能做出正確的決定。所有決策都需要置於更廣泛的業務環境中,來拷問是否能產生價值。

後文將介紹我從DDD的非技術方面所提煉出來的這5項首要原則,這些原則幫助我在職業生涯中真正發揮了DDD的威力。

DDD的5項首要原則如下:

1. 就問題達成一致意見

  • 聚焦於解決方案的需求背後的動機,並在更廣泛的業務上下文中理解問題。
  • 在機會把握或約束消除方面,與業務同事產生共情,從而實現真正的業務價值。

2. 通過協作尋求解決方案

  • 瞄準產品願景,以協作的方式進行需求搜集,讓解決方案能解決問題,併產生影響。
  • 為核心問題子域投入更多時間和精力來實現對齊。

3. 確保解決方案解決核心問題

  • 關注成效而非輸出,以防止過度複雜的代碼和不必要的投資。
  • 通過保持簡單和知錯就改,來避免鎖死在某一個解決方案之上。

4. 全局優化系統

  • 所有團隊共擔整個系統和流程的責任,要高於各個孤立團隊的局部優化。
  • 對齊到全局目標,並理解如何貢獻力量。

5. 用積極的方式影響團隊

  • 尊重,耐心,有激情。
  • 對他人謙遜和共情,使整個團隊一起達成解決方案。

補充一點,不管在非技術方面管理得有多好,你仍然需要擁有高超的技術能力。不過,我經常目睹對核心域和問題空間本身的目標的良好理解,能夠驅動出更簡單的解決方案,並僅需更簡單的技術實現方法。(未完待續)

作者:Scott Millett

譯者:ThoughtWorks 鄢倩

校審:ThoughtWorks 伍斌、覃宇、徐培、黃雨青

注釋:

【1】作者的家鄉英格蘭南部海濱城市朴次茅斯,是全英平均日照時間最長的城市,3月底的每日日照時間會長達近13小時,所以要抹防晒霜——譯者注

【2】來自西方的諺語「政治是讓步的藝術」,即實用主義的政治哲學認為,做出讓步而獲得實際成效,要高於毫不妥協卻一無所獲。這裡指業務和技術雙方應該互相退讓一步,主動理解對方,從而創造更多價值——譯者注

【3】絕地,是美國著名導演喬治·盧卡斯拍攝的科幻系列電影《星球大戰》中的重要組織。他們學習、研究和利用一種稱為原力並存在於星戰銀河中的基本力。他們的使命是保衛和維護銀河共和國和銀河系的安定。絕地大師是絕地組織內部的頭銜,通常授予那些強大和富有聲望的絕地成員——譯者注

【4】指富家女子學習上流社會禮儀的學校,這裡是一種幽默表達——譯者注

【5】在DDD中,戰術模式指在一個限界上下文內部進行建模的模式,包括領域事件、領域服務、實體、值對象、工廠、聚合和存儲庫等——譯者注

【6】在DDD中,戰略模式指跨越多個限界上下文進行建模的模式,包括限界上下文、上下文映射圖、核心域、支撐域和通用域等——譯者注


領域驅動設計峰會2019——提案徵集mp.weixin.qq.com/s/D09Z

一票難求:【2019領域驅動設計峰會】瞎鳥票搶購鏈接

mp.weixin.qq.com/s/UO7w


推薦閱讀:
相关文章