




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、 用領域驅動設計實現訂單業務的重構 大家好,我是來自羅輯思維得到app的韓宇斌,很榮幸能有機會和大家分享我的一些心得,我分享的主題是DDD戰略建模在重構業務系統時的實踐。我分享的內容分為三部分:第一部分是:用領域驅動來把握真正的業務需求;第二部分:領域驅動設計指導架構設計與建模;第三部分:用限界上下文來保護領域。一、用領域驅動來把握真正的業務需求如果把我今天的分享比作一個故事的話,那么故事的主線是:領域驅動設計幫助我解決了工作的難題。這個難題表現在兩個方面,首先無路可退 :入職第一個任務,做不成就意味著回家。其次是左右為難 :實現技術重構的目標,滿足不了業務需求!不去實現,又不知道該做什么?在
2、進入到主題之前,我們先來從商家視角了解一些電商業務的背景知識。一個商家想要賣自己的商品,不管是在線下實體店面,還是線上電商,至少要有賣貨,收錢,發貨三個環節,如果我們從網上找一個開源的商城系統,也會包括這三部分的功能。然而,對于商家來說,只有這三個環節是不夠的,還需要有一個非常重要的環節就是算賬。我分享內容,就是和收錢,發貨,算賬相關的。我們再來看一下得到APP電商業務涉及的組織和系統。我所在的聽書屬于業務后端,主要負責賣貨和發貨環節,而收錢環節需要由交易平臺組和基礎平臺組提供的服務來完成,算賬相關的由財務平臺組負責。大家先對紅框的三個系統有個印象,后面會頻繁的提到。得到app目前如何確認收入
3、呢?財務部門在算賬交稅前,首先要確認收入,賣了多少商品,收了多少錢,實收賬款和應收賬款能不能對上。用戶在APP內下單后生成訂單記錄,收到錢后生成支付記錄,發貨生成權益記錄。虛擬商品的發貨不需要快遞,就是我們在表里面寫一條數據。財務部門需要把三張記錄表中的每條數據都用訂單號關聯起來,并且狀態含義嚴格匹配,才能確認為是收入,否則就會成為壞賬或者呆賬,需要人工處理。然而,開始的時候,并不是這樣的。用戶在APP中購買虛擬商品,我們沒有生成訂單記錄,只有支付記錄和權益記錄。當出現數據不一致時,就給財務確收帶來了問題。主要分為兩類,只有支付記錄沒有權益記錄數據,是有支付無交付,我們收了錢沒發貨;而只有權益
4、找不到對應的支付記錄的數據,是有交付無支付,發貨了沒收到錢。每個財務結算周期,兩個開發組的人,幾乎都要去排查問題數據。你也許會好奇,一個電商平臺居然沒有訂單?我相信“存在即合理”,當時這么做肯定有當時的原因和背景,說白了一切都是為了快速上線,快速驗證得到app的商業模式,活下去對于創業公司來說,比設計實現一個完美的系統優先級更高。我們看下沒有訂單的情況下,系統之間的調用關系。為了說明核心問題,我挑選了流程最簡單的節操幣購買的方式,節操幣是得到APP內的虛擬貨幣,節操幣系統是由我們的基礎平臺組負責的。以購買聽書的內容為例,APP去請求聽書系統的購買接口,然后由聽書系統調用節操幣系統完成扣款,扣款
5、成功后寫入已購。這張圖是沒有訂單時,聽書業務實現全部售賣方式的調用關系,從圖中我們可以看到,聽書系統需要直接與許多外部系統交互,系統間的依賴和耦合是比較高的。我們再回到財務結算的場景。由于沒有訂單,給財務核算工作帶來很多問題,財務就要求必須記錄訂單及交易狀態。于是各業務系統就花時間去改造,用戶購買時先調用訂單系統的CreateOrder來生成訂單記錄,支付完成后要調用PayOrder來標記訂單的支付狀態,發貨后調用SignOrder來把訂單簽收,我們內部把增加訂單的這幾個動作叫做“訂單化”。實現了訂單化以后,財務就可以按照訂單記錄、支付記錄、權益記錄的嚴格匹配來進行核算與確認收入了。我們看一下
6、實現了“訂單化”后的調用關系,聽書系統需要增加3個請求去調用訂單系統,而原來的每個接口都要傳遞訂單ID。例如創建完訂單以后,在扣除節操幣的環節,要告訴節操幣系統是為具體的哪筆訂單扣除余額的。實現了訂單化后,業務系統對外部系統的依賴和耦合有些加劇,增加了對訂單系統的三次調用,同時要給別的系統調用請求中傳遞訂單號。上線后沒多久,原系統架構帶來的痛點很快就出現了。財務要求在訂單加個“簽收時間”字段,據說20多天才上線!為什么需要20多天,因為所有的業務系統都要修改相關的代碼,而測試人員要把所有業務的購買都要回歸測試一遍,在需求開發時間非常緊張的情況下,投入與財務又提了需求,要求盡快把所有交付的內容實
7、現“訂單化”,因為我們除了有資金往來的購買,還有很多用戶免費領取的方式,這些也是要核算成本和交稅的。如果再來一次前面那樣的修改,可要命了。于是團隊思考該怎么辦?結論是內部實現個系統,代理全部訂單相關的功能,這樣再有修改,只改這個代理服務就行了!實現隔離變化!這就是我接到的重構任務:訂單代理(訂單化)系統。實現 一個代理服務,對接 交易平臺組的訂單系統和基礎平臺組的支付系統,推動若干個業務系統改造,改成調用新的代理服務。我們看下訂單代理系統是如何隔離了變化的。從圖中我們看到,業務系統不在直接依賴外部系統的了,訂單相關的參數由代理系統去組織,如果再有訂單相關的修改,只改這個代理服務就行了。還以增加
8、“簽收時間”的字段為例,業務系統就不需要關注這個字段了。表面看,我們的設計方案, “同時滿足”了業務需求和技術目標。業務需求:所有的商品都實現“訂單化”:技術這邊不光都實現“訂單化”,還實現個“訂單化的代理系統”,應對外部系統的變化。這張圖很多人一定都看到過,他描述的是對用戶需求理解偏差造成的軟件項目的失敗,在我這個場景,方案確定了!但這是業務的目標嗎?我讀了些代碼并做了系統分析后,帶著掌握的內容,滿懷信心的去和合作部門交流,卻感覺大家關注的點甚至方向都常常不一致!在需求理解上,我們和業務方存在認知的偏差。開發最關心的是,完成全部商品的訂單化,實現訂單代理系統,降低業務系統與外部系統的耦合。而
9、業務關心的是,一定要正確的交付(面向現在),能夠高效準確的算賬(面向未來),把過去的賬給解釋清楚(面向過去),我給總結為三個面向。訂單代理系統的目標在財務那里只是個過程!他們甚至絲毫不關心我們是不是要實現一個訂單化的代理系統。真正的目標需求是什么?如果一個系統還沒有開始做,你就知道即使做完也達不到業務的目標,那種心情是很糾結的。這就是前面說的,我面臨的挑戰。首先是無路可退,入職的第一個任務。第二是左右為難:實現“訂單代理系統”,滿足不了業務需求!如果不去實現“訂單代理系統”,那該做什么?思考了沒有把握到真正需求的原因。技術人員理解到的所謂“需求”是一種內部視角,是有局限性的。而業務方是外部視角
10、,看到的要比我們全面。領域驅動設計,它能讓技術人員和業務都能從外部視角也就是領域來看問題。DDD思想指導的開發過程,是一個全程強調領域的過程,開發人員和領域專家,從業務需求中提煉出【統一語言】,基于統一語言建立【領域模型】,用領域模型指導設計及編碼實現。從財務的訴求中,我們把握到了需求的問題域是:電商的發貨與算賬,而業務的期望是精確交付。前面說了很多訂單相關的,也做了很多分析,但是我所要實現訂單代理系統,在整個羅輯思維這個電商業務平臺中,是個什么地位呢?帶著問題我去找業務溝通。下面的圖,是一次找財務方向的產品經理溝通討論時給我畫的,產品經理說第一次有技術主動和她聊財務相關的業務,一高興就給我講
11、了很多。為了讓自己的理解和產品經理想要表達的不產生太大的偏差,當天結合這個草圖,趕緊畫了一個自己理解的圖,第二天又去給產品經理講了一遍。反述的過程,自己明白訂單化在全局的位置,雖然貌似不起眼但是卻擔負著得到所有虛擬商品的交付。經過繼續深入調研后,把“訂單化”要完成的內容,劃分成了支付和交付兩部分,而所在的得到后端,應該關注得到商品的交付部分。和業務的充分溝通與協作,漸提煉出來了一些“統一語言”,成為了我們的交易領域內的業務語言。例如,訂單完整的生命周期:下單,支付,交付,簽收。而確收的內容指的是:已購權益和時間權益。在領域驅動設計思想的指導下,我們找到了真正的業務需求,并不只是開始的,實現一個
12、訂單代理系統那么簡單,而是要實現“財務核算級別的精確交付”。二、領域驅動設計指導架構設計與建模在第一部分,我們找到了真正的業務需求,第二部分,來介紹一下“領域驅動設計指導架構設計與建模”。在這部分,業務的真正需求將會落地。我們再來看一下電商業務的基本模型。我們在電商平臺所完成的的購買行為,其實就是買賣雙方,圍繞著交易物,以雙方認可的價格簽訂合同后,展開的履約行為。簽約生成的合同,就是訂單,買方付錢后合同開始生效,賣方收錢發貨,買方收貨簽收后,合同結束。賣方還要具備賣貨,算賬等能力。我們想一下,當一個人或者一個組織具備了電商業務的全部功能后,他是不是就可以成為“個體戶”或者“小商販”了呢。“個體
13、戶”和“小商販”用自己勞動換來回報,值得我們尊敬。但是在一個電商平臺中,每個業務系統都把自己做成“小商販”系統,并不是件好事。我們再來看下訂單代理系統架構的弊端。首先,每個業務都是個“小商販”,相同功能的代碼依然會重復。即使業務系統把原來直接調用外部系統的方式改成調用訂單代理系統,交付數據的準確性依然達不到財務要求,因為無論是業務系統的開發還是產品經理,對于交付領域和交付數據都缺乏足夠的敏感度,畢竟術業有專攻。小商販模式能夠不那么優雅的解決技術的問題,但卻不能滿足業務“財務核算級別的精確交付”的需求,因為交易領域中缺少一個專注交付的子領域。于是,我們重新理解和確定了領域問題。在前面的概念模型中
14、,我們得到了幾個概念:交易是基于合同的行為,訂單是合同,交付是履約。得到后端的核心子領域問題:是“履約”是交付,到此,一個訂單交付系統就呼之欲出了。在我們這個場景中,業務系統實現了交易的全部功能,就是個“小商販”。每個小商販都賣貨收錢發貨,而和現實中小商販不同的是,每個商販都不對賣貨產生的賬務數據負責,而賬務卻是由一撥人算的。我們通過DDD的限界上下文劃分來分析,就會發現,應該把每個業務上下文中和交易相關的功能獨立出來,把自己變成一個商品的供貨商,入駐超市賣場,讓專業的人去做專業的事,業務系統自己變為“超市賣家”。由訂單交付系統接管業務的交易行為,原來聽書商品的購買,變成了這樣的調用關系。我們
15、的訂單交付系統前置,直接和app對接,創建訂單和交付統一由交付系統負責完成,原業務系統只需要提供一個返回商品價格、上下架狀態的接口,就可以完成售賣。我們用這樣的方式,讓訂單交付系統從所有的業務方接管了售賣交付行為,而業務方幾乎不需要做什么開發,甚至感覺不到訂單的存在。最終,訂單交付系統滿足了業務和技術的目標。業務方不再是“小商販”,入駐“超市”成為“賣家”,交付的數據達到財務精準核算的要求。綠框部分,就像一個超市,業務系統將自己的商品上架后,就不需要關注收錢、交付和算賬了,可以把更多的精力投入到自己業務產品的研發中,三、是用限界上下文來保護領域首先,我們來認識一下,強調上下文的重要性。我抽象了
16、一個乘客到飛機場登機的例子。機場,為了維護自己的秩序,是要采取許多措施來保護這個領域的。而我們識別了領域后,也要保護領域。保護是手段,目標:邊界內的“完美世界”不可侵犯,完美世界是什么,我們想一下架構優良,職責單一,代碼整潔等等讓人感覺到美好的詞語。保護的依據:就是識別了限界上下文后劃分的邊界,以及限界上下文內的規則。在訂單交付系統開發和推進的過程中,采取了一些保護這個領域的措施,我按照上下文之間和上下文內部總結為如下的分類。上下文之間,第一、規范可以進入上下文內的對象模型,第二、用領域事件解耦合與其它上下文的關系,第三、把握領域的職責,第四、隔離上下文間的業務內涵。上下文內部,保護業務抽象行
17、為的一致性。后面我們結合實例,來看一下具體的行動措施。1、保護領域的行動:規范可以進入上下文內的對象模型。領域驅動設計一書中解釋限界上下文時,Eric Evans 用細胞來形容限界上下文,認為“細胞之所以能夠存在,是因為細胞膜限定了什么在細胞內,什么在細胞外,并且確定了什么物質可以通過細胞膜。”當進入機場上下文的時,“人物”要變為“乘客”;當進入訂單交付上下文的時,“業務對象”要變為“商品”。為什么要這么做,因為在之前,進入各業務上下文的模型是由業務自己決定的,客戶端結算臺是根據許多的ifelse來判斷該請求哪個業務系統的接口。而由于缺乏領域規范,這些參數形態各異,業務端的實現也是各不相同,導
18、致出現問題排查排查困難。所以,在新的訂單交付系統推廣的第一步,就是通過統一參數來規范進入交付領域的對象。App開發新的功能和我們對接時,我們要求不管原來是什么類型的業務對象,進入訂單交付領域,必須轉換為商品,必須傳遞ProductID + ProductType。而對于老版本的業務,我們通過直接在網關轉發時,把接口轉到我們的防腐層,轉換為商品再去調用交付邏輯。2、保護領域:用領域事件解耦與其它上下文的關系。由于購買數據有很多系統會關注,所以在之前,每記錄一條用戶權益,就會至少給四個相關上下文推送格式大同小異的消息供相關方消費,浪費資源不說,維護成本也高,還被外部的上下文業務規則所綁架。磐石,關
19、心商品sku和價格,勛章關系價格和數量,已購只關心數量,大數據方面關心商品和價格。4個需求方,不同時間段提的需求,由于沒有之前沒有領域,就都是定制開發。在重構新的訂單交付系統時,我們認為交付結果推送的消息是一個領域對外提供的服務,應該統一由領域來提供標準外部去適配,而不是外部提要求我們來定制開發。于是,就在記錄用戶權益后,發布統一的領域事件,由外部系統的上下文來訂閱和適配。3、保護領域:把握領域的職責,領域之外的事少管。在之前,用戶的充值工作完全是由得到后端來全權負責的,要反復和訂單系統和支付系統交互,前后至少要經過9次調度和響應,極易出現問題,所以在財務對賬中,充值也是被財務吐槽比較多的一個
20、地方。前面分析過,交付的節操幣這個商品其實不屬于得到后端的商品,我們做了那么多,是出力不討好。交易中心是我們中臺化的一個產物,這個系統接管了包括訂單和支付的所交易行為,所以在和交易中心對接時,我認為既然節操幣不屬于得到后端,就不應該由我們來負責交付,于是我們就把節操幣充值的交付,“讓”給交易中心。充值行為變成了這樣的調用關系,我們的訂單交付系統比原來少做了很多事情,全局的充值結果卻更有保障了,因為減少了不必要的調用。紅線部分,是完成同樣的充值行為,我們訂單交付系統需要做的事情,連訂單的支付和簽收也不需要我們關心了。4、保護領域:使用上下文隔離相同事物的不同內涵。之前,用戶在得到商城內購買一個課
21、程,要先產生一個商城訂單,然后再推送給得到后端,會再生成一個得到的訂單并交付簽收。在財務審計和對賬中,這個邏輯也帶來了很多的問題數據,因為兩筆訂單的對應關系是很不穩定的。一次購買,產生兩筆訂單,并不符合我們這個場景。一次購買,產生兩筆訂單的適用用場景,適用于兩個商家彼此之間是完全獨立核算的場景。我之前有個同事,開了個網店,但是她一點貨都不存。她是怎么玩的呢?從網上把別的商家的圖片商品信息抓過來,在自己的網店上加10100塊錢不等就上架,當用戶在她的網店下單后,她再去別的網店下個同樣商品的訂單,收貨人填買家。由真正的賣家發貨。這個場景下,雖然看著是同一個東西,但內涵上其實是兩個不同的事物,如果嚴
22、格點,肯定是兩個不同的sku。而我們這個場景,只收了一份錢,內部也沒有再次產生資金流水行為,商城上下文和我們訂單交付上下文應該是合作關系,一起接力完成一筆訂單的交付。雖然在不同的上下文中,表現為訂單和交付單兩個不同的東西,但內涵上是同一個事物的不同狀態。于是,在對接這部分業務時,我們打破了原有規則,說服大家接受商城購買是一種下單途徑,流轉到得到這邊,是訂單履約的方式,就是一個訂單。這樣做以后,商城同步售賣的訂單核算,可以和其它支付類型購買的商品采用一樣方式核算了,技術人員再也不用給財務導兩筆訂單的對應關系了。5、保護領域:保護業務抽象行為的一致性。我們先看一下訂單交付系統實現層面的設計。使用了橋模式,一邊抽象了支
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 計算機二級MySQL觸發器應用案例試題及答案
- 計算機網絡安全風險評估試題及答案
- 如何進行嵌入式技術創新試題及答案
- 前沿嵌入式技術試題及答案
- 華能電廠缺陷管理制度
- 醫院智慧門診管理制度
- 單位合并人員管理制度
- 化工園區蒸汽管理制度
- 了解公路工程招投標中的法律風險試題及答案
- 公司醫療器械管理制度
- 2024年湖北省鶴峰縣事業單位公開招聘輔警考試題帶答案分析
- 醫院后勤考試試題及答案
- 《中國的科技成就》課件
- -小學英語人稱代詞與物主代詞講解課件(共58張課件).課件
- (正式版)JBT 9229-2024 剪叉式升降工作平臺
- 七年級英語下冊閱讀理解專項練習題100篇含答案
- 2023版押品考試題庫必考點含答案
- 建筑公司組織關系架構圖
- 褲類統一單價表-服裝工序工價表
- 我們是共產主義接班人歌詞--拼音版本
- 麥凱66客戶檔案管理表格
評論
0/150
提交評論