DDD理論學習系列(1)-- 通用語言

1.引言

在開始之前,我想我們有必要先了解以下DDD的主要參與者。因爲畢竟語言是人說的嗎,就像我們面向對象編程一樣,那通用語言面向的是?
DDD的主要參與者:領域專家+開發人員
領域專家:精通業務的任何人。
開發人員:開發+測試。
領域專家擅長某個領域的知識,專注於交付的業務價值。
開發人員則注重於技術實現。
開發人員總是想着類、接口、方法、設計模式、架構等。以面向對象的編程思想進行思考,思考如何進行抽象、封裝、繼承、多態等。而領域專家對軟件中的框架、持久化、數據庫等沒有概念,而這也就導致了他們之間交流的困難性。

那怎麼解決交流障礙這個問題呢?

2. 通用語言

拋開DDD而言,單從字面意思來理解,我們首先肯定先聯想到作爲世界使用最多的語言--英語。
英語之所以能成爲通用語言,我想無非是以下幾方面:

  • 簡單易學

  • 使用率高

  • 國際通用

那DDD中通用語言又是怎樣呢?
首先它也同樣要擁有【簡單】的特性,這樣才便於理解和傳播。
其次,它也要有【通用】、【使用率高】的特性,因爲只有在軟件開發的過程中,團隊範圍內所有的參與人員廣泛使用,才能準確傳遞業務規則。

通用語言是團隊交流的基礎上建立起來的,代碼則是基於通用語言來進行業務表達的。

3. 舉個例子

項目經理安排了一項任務給我:
聖傑這個補丁處理下【可銷控制】這個需求。
聽後,真是一臉懵逼,【可銷控制】是什麼鬼?

這明顯是專業術語,我不懂的專業術語。
按照DDD對通用語言的定義,【可銷控制】就不算通用語言。
因爲只有領域專家知道它的含義,開發人員一臉茫然。

但通用語言是領域專家和開發人員一起創建的,所以我們開個需求會議,來梳理下專業術語背後的含義。

可銷控制的應用場景是:
在ERP中,在做單時對銷售員負責的客戶進行範圍控制。比如,A客戶是銷售員小李發展過來的,小李希望僅能自己負責對A客戶的業務。

這麼一解釋,是不是明白不少了。但是不是還有幾點疑惑?

  • 可銷範圍如何配置?

  • 做什麼單據時進行可銷範圍控制?

  • 如何進行可銷控制?

  • 可銷控制需不需要參數控制?

經過討論,得出以下結論:

  • 提供專門的【銷售員-客戶可銷控制】界面進行銷售員-客戶映射數據配置。

  • 做銷售訂單單據時進行可銷範圍控制

  • 在錄入銷售員後,做單員在選擇客戶列表時,客戶列表中僅顯示可銷範圍配置的客戶數據。

  • 提供【銷售員-客戶可銷範圍控制】系統參數,勾選後才進行可銷範圍控制。

好了,這下需求理解個七八九了。
原來可銷控制就是銷售員-客戶銷售範圍控制。
咱們用一句話來精簡下這個需求:
可銷控制是指銷售員所負責客戶的範圍控制,當勾選了【銷售員-客戶可銷控制】參數後,在做銷售訂單錄入客戶數據時,客戶列表僅能選擇到在【可銷控制】列表中爲該銷售員配置的客戶。

經過這麼一說明,我們是不是已經理清了【可銷控制】這個需求點。

那這種通過團隊交流達成共識的能夠簡單清晰準確傳遞業務規則的語言(可以是文字、圖片等)即可稱爲通用語言。

4. 通用語言的價值

就像上面所說的那樣,通用語言的最大價值是解決了交流障礙問題,使領域專家和開發人員能夠協同合作,從而能夠確保業務需求的正確表達。
另外,基於通用語言,開發人員能夠開發出可讀性更好的代碼,從而將業務需求準確轉化爲代碼設計。達到DDD的目標代碼即設計,設計即代碼。通俗的講,也就是開發人員寫的代碼領域專家也能看懂。

5.通用語言的代碼表達

既然開發人員也要基於通用語言進行代碼開發,那代碼如何體現通用語言呢?
在《實現領域驅動設計》書中有一個簡單的例子(P238),我們一起來看一下:

  • 系統必須對User進行認證,並且只有當Tenant(租戶)處於激活狀態時才能對User進行認證。

上面這個用例就是基於通用語言的用例,簡單清楚的說明了業務規則。
我們先看第一種代碼實現:

bool anthentic = false;
User user = _userRepository().FindUserByTenantIdAndUserName(tenantId, userName);if(user!=null)
{
    authentic = user.IsAuthentic(password);
}return authentic;

這段代碼完全不能反應通用語言,主要存在以下問題:

  1. 這段代碼先查找user,再對user進行密碼匹配來完成認證。其中user.IsAuthentic(password);表示的是“用戶是否被認證”的意思,而沒有表達出“認證”這個過程,即“對用戶進行認證”。

  2. 未體現“檢查Tenant是否處於激活狀態”這個前提條件。

知道問題後,我們可以講代碼略做改動:

bool anthentic = false;
Tenant tenant = _tenantRepository.FindTenantById(tenantId);//檢查租戶是否激活if(tenant!=null&&tenant.IsActive){
User user = _userRepository.FindUserByTenantIdAndUserName(tenantId, userName);if(user!=null)
{
    authentic = tenant.Authenticate(user, password);//租戶對用戶進行認證}
}return authentic;

以上代碼雖然也不是最終結果,但至少對通用語言進行了體現。通讀代碼,就能明白業務用例,體現代碼即設計這一思想。

閱罷此文,如果您覺得本文不錯並有所收穫,請【打賞】或【推薦】,也可【評論】留下您的問題或建議與我交流。 
你的支持是我不斷創作和分享的不竭動力!

作者:『聖傑』

出處:http://www.cnblogs.com/sheng-jie/

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,否則保留追究法律責任的權利。

分類: 


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