駭客新聞對DDD的各種吐槽和經驗分享

banq發表於2021-09-28

駭客新聞對DDD的各種吐槽和經驗分享
著名DDD專家mathiasverraes的定義了什麼是領域驅動設計(DDD)?,在駭客新聞引起各種討論
  

LennyWhiteJr 
在這裡看到很多人對 DDD 的仇恨,所以讓我從在我的團隊中倡導 DDD 的人那裡提供另一種觀點。
當我加入時,我的團隊已經為我們應用程式的第一個版本構建後端大約 4 個月。當我加入時,那時程式碼庫是Martin Fowler 定義的“貧血領域模型”。

  • - 在最鬆散的意義上有一個“域模型”
  • - 每個模型型別只是一個 POJO,每個欄位都有原始的 getter/setter
  • - 幾乎所有欄位都是原始型別(主要是帶有一些 int/doubles/dates 的字串)
  • - 所有驗證這些型別的程式碼在應用程式程式碼中完成,並在整個程式碼庫中分散
  • - 內部資料庫識別符號完全暴露在程式碼模型中 - 內部服務型別與外部服務型別自由混合 - 沒有聚合根的概念 - 每個實體都被訪問特別指定


這是一種非常不可持續的方法,我做的第一件事就是嘗試在最痛苦的領域實施戰略性 DDD。這包括
  • - 採用富值物件來表示領域概念而不是原始字串
  • - 在模型類中實施業務不變數
  • - 使用匹配業務行為和執行驗證的方法豐富領域實體
  • - 建立儲存庫,將大部分永續性細節移出應用程式程式碼
  • - 根據我們所需的訪問模式定義聚合,這簡化了我們的資料訪問
  • - 內部域的有界上下文
  • - 將外部服務型別對映到我們自己的內部表示

所有這一切的結果是建立了一個核心“域模型”,它捕獲了我們服務的預期業務行為,最重要的是,最終顯著簡化了應用程式程式碼的其餘部分。如果 DDD 使您的應用程式程式碼更加複雜,那麼您就做錯了。
 

Fiahil 
幾年前我參加了幾次 DDD 聚會,現在為什麼要參與這種架構一直沒有意義。房間裡擠滿了具有深厚企業軟體 (tm) 知識的經驗豐富的 Java 開發人員。
然後,我開始擔任 AI 軟體工程師(軟體工程師 + DevOps + 資料科學家的組合),一切順利。DDD 是與資料科學、人工智慧、機器學習相關的任何事物的絕妙設計模式。為什麼 ?因為您 90% 的問題都是追溯有意義的,組織、排序、過濾、聚合您從最喜歡的資料庫/湖泊/倉庫中獲得的所有資料。DDD 讓您在現有的業務挑戰和正在其上執行的分析之間擁有統一的語言、不變的定義和期望。它非常適合驗證跨資料集的假設,例如:銷售額永遠不能 < 0 ?讓我們檢查一下... 哦,好吧,您忘記了,請返回,所以現在您可以定義它們並明確何時包含或排除它們。
 

softveda
我是從一名程式設計師開始22 年軟體職業生涯,我只見過一次DDD成功且恰當地使用 。所有其他的嘗試都是半成品和過度設計的混亂。
它曾經是一個非常複雜的保單管理領域。它具有高度複雜的業務規則,並且必須維護不變數。最初的開發人員都是諮詢公司的資深開發人員。在交接之前,我作為團隊的永久成員加入了。
問題是,幾年來很難讓新員工快速維護複雜的程式碼並對其進行測試。此外,隨著新任 CEO、中小企業退休、市場變化等,即使是無處不在的語言也開始發生變化。例如,會員成為客戶。現在,您要麼重構整個程式碼庫,要麼使用與新業務術語不同的程式碼。猜猜選了哪一個?隨著時間的推移,它變得難以重構。我現在已經離開公司很多年了,但我假設這段程式碼仍然存在。
然後我在一些企業工作,這些核心系統建立在像 SAP 這樣的龐大單體中,維護著我來自 WITCH 公司的人員隊伍。所有的數字應用程式、入口網站等都是前端、API 和快取層。DDD 的複雜性在 SAP 或 PEGA 或 Dynamics 等的內部。
 

ToJans 
隨著 DDD 越來越流行,出現了很多“初學者專家”和自稱為思想領袖的人……(~= 敏捷運動)
如果您正在學習 DDD,CQRS-all-the-things 通常是您要經歷的一個階段。
在我個人看來,檢測“初學者專家”的一個很好的啟發是他們更喜歡使用大量 DDD 術語,並且專注於更多技術方面,而不是真正嘗試首先了解業務領域。
不幸的是,沒有一個人人都接受的 DDD 定義。DDD 的核心是關於軟體設計的實踐,它把領域——使用者語言和問題——放在首位。沒有技術考慮。
ES (Event Sourcing) 和 CQRS 是人們在做 DDD 時喜歡使用的技術模式,因為各種原因,但它們絕不是實踐 DDD 所必需的。
 

amw
我不提倡 CQRS,我個人從未在專案中使用過它。但是,架構與 DDD 相關聯的原因是 DDD 從根本上是一種哲學或一種想法。某些軟體設計比其他軟體設計更好地實現了這一哲學理想。
例如,DDD 強調“隔離域模型”的想法 - 這有一個非常實際的原因,因為您的業務規則已經足夠複雜,因此混合了資料庫事務、HTTP 快取、響應序列化、授權等。 , 進入您的域邏輯使其更難理解。您希望能夠與客戶/領域專家進行對話,在那裡他們解釋某些內容,並且您可以快速調整程式碼以滿足他們的需求。至少這是理想的目標。
因此,某些模式可以更好地實現該目標。例如,這意味著您需要某種資料訪問層模式,以便關心資料庫的程式碼與關心域邏輯的程式碼分開。嗯,有上百萬種不同的方法來實現這種分離,它們有不同的權衡,就像其他一切一樣,某些模式變得流行。這就是 CQRS 正在發生的事情。人們認為它可以更好地表達領域模型,因為建立資料和查詢資料通常與客戶的觀點截然不同。
這個目標是否實現,我不確定。但正如我所見,這就是人們嘗試這種模式的原因。
 

necovek 
我的經驗是,不幸的是,大多數開發人員要麼沒有足夠的經驗,要麼不夠聰明(這些密切相關),無法阻止抽象蔓延並僅應用有意義的抽象。而其他人根本就沒有足夠的興趣,他們知道他們可以透過以下錯誤判斷的模式獲得 LGTM。
他們還抓住機會使用 DDD 書中的相同術語,然後繼續用每個人都能理解的更通俗的術語來解釋它們:就像社會科學又一次(對不起,社會科學,但它就是這樣)他們發明了術語,所以他們會更“科學”。為什麼不簡單地使用每個人都理解的術語?
準確的說大概是。每個領域都會在某個時候發展出一種行話。它可以用來排除或聽起來很聰明,但大多數時候它只是為了精確。常用術語過於模糊/多義。
 
DDD 有時讓我想到敏捷的軟體版本。背後的想法和哲學很好,但最終被視為靈丹妙藥。如果您這樣做,您將擁有一個良好的架構,並且您的軟體將得到良好的架構。特別是在 .NET 世界中,我看到 DDD 與 CQRS 一起被標記為“乾淨的架構”,實際上它是一堆層和分離。
DDD 與其說是製作軟體,不如說是管理您的業務軟體需求。如果您閱讀“實施 DDD”是一件好事,那麼您應該將精力集中在您的業務核心增值上。這是您將最好的開發人員、架構師和資金投入的地方。這個核心之外的任何東西都將獲得更少的資源,並且通常可以外包。
為了評估這個核心是什麼以及需要什麼,你需要你的技術團隊經常與領域專家交談。使用一些通用語言。
編碼方面本身是敏捷的,因為通常一開始你的技術團隊和你的專家之間會有溝通不暢,給你一個不太好的結果。更多的交流、更多的知識共享和理解會讓你對你的產品和它的架構有不同的看法:那是你重構的時候。
 
DDD 的大部分內容都是常識,它提供的是一種明確的常識。在我看來,重要的因素是明確確保開發人員和利益相關者都擁有對映到相關領域的業務流程的共享心理模型,他們都同意哪些“行話”術語對映到哪些部分該模型以及該模型(具有商定的條款)在程式碼中明確表示。
如果您真正瞭解彼此,與業務領域人員保持密切聯絡是最有用的。我經常看到開發人員和業務人員在討論問題時使用同一個“每天”這個詞,直到很久以後他們才發現他們對這個詞的明顯理解大不相同。
 
DDD 是一個絕妙的想法,我認為應該更廣泛地應用:對問題域的深刻理解,在技術和產品之間共享,可以大大提高質量,減少錯誤,簡化溝通,甚至產生更好的結構化程式碼。特別是,它往往會導致程式碼結構遵循底層問題域的結構,這往往比程式碼更清晰,程式碼只是試圖實現功能而沒有對其目的的潛在理解。
另一方面,傳統上與​​ DDD 相關的設計模式和實際實現非常糟糕,並且往往會導致企業軟體級別的笨拙和/或對 OOP 的過度教條使用。
 

oscarcp 
我們在我現在工作的公司使用 DDD,老實說,我非常討厭它,有時甚至讓我懷疑我是否還想繼續在程式設計領域工作(在它工作了 20 年)。
不要誤會我的意思,DDD 是有意義和目的的,但有些公司將其作為獲得的徽章來應用,而不是思考這個問題,你真的需要在 DDD 之後重寫所有內容嗎?
在我們的例子中,在“常規程式設計”中可能需要幾個 200 行檔案的簡單 CRUD API 在 DDD 中變成了難以管理的噩夢,需要你至少花幾天的時間進行真正深入的調查才能理解,因為它被分成了更多這 25 個檔案最多包含 3 或 4 行程式碼,抽象層太多,我們中的最優秀的人不可能一口氣完成。
現在,您可以提出“您做錯了(tm)”的論點,但由於我只是這個特定計劃中的無人機並且沒有任何迴旋餘地(團隊在這方面非常不靈活)我必須遵循它信。
  

crdrost 
與業務溝通實際上是 DDD 的核心資訊。它可能應該被稱為“人類學設計”,因為“領域專家”是您軟體的非技術使用者的同義詞(領域是業務領域,這是您的軟體試圖為他們做的任何事情)。資訊是你必須在他們的自然棲息地觀察你的使用者。
我不明白為什麼人們發現在 DDD 中很難繪製上下文邊界。所以有界上下文是一種程式設計思想,在程式設計中我們稱之為名稱空間,它們的存在是為了消除兩個相同的名稱之間的歧義。DDD 說我們需要這樣做,因為業務的不同部分將使用相同的詞來指代不同的事物,而試圖讓業務的任何一方使用不同的詞是容易出錯和失敗的主張。所以我們需要名稱空間,這樣我們的領域專家都可以用他們自己的語言說話,我們可以理解他們,因為在這種情況下我們使用這個名稱空間,在那種情況下我們使用那個名稱空間。所以:你在哪裡畫邊界?換句話說,你的模組應該有多大?(或者現在,“模組”改為“微服務”。)
很簡單:根據使用者在與系統互動時似乎關心的事物種類以及他們談論世界的不同方式,將使用者劃分為多個組。有界上下文不是“實體”或“強實體”或服務發現閾值,而是一種人類學構造,就像 DDD 中的其他一切一樣。“運輸部門的人出於一個原因關心這一點,賬單部門的人出於另一個原因關心它,他們通常不會互相交談,但我想有時他們會......”聽起來像你有一個運輸模組/微服務和計費模組/微服務。邊界是人的邊界。
 

orthoxerox
DDD 技術模式是一堆奇怪的東西。
一方面,那裡有很多聰明的概念。例如,每個人都應該知道聚合是什麼。
另一方面,它們中的許多與 DDD 的基本前提幾乎沒有關係。您可以在沒有這些特定模式的情況下使用 DDD。
另一方面,人們開始在任何地方應用每一種模式,就像他們對 GoF 模式所做的那樣。
我建議剛接觸 DDD 的人首先參與瞭解戰略設計部分。使用它的基本原理、優點和缺點等。在您瞭解 DDD 的作用與您想要實現的目標之前,請遠離戰術模式。戰略與戰術是完全不同的關注點。大量 DDD 資訊的問題在於,人們傾向於採用戰術方式儘早引入各種不需要的架構。請注意,戰略分析的結果很可能會得出結論,簡單的 CRUD 設計是最好的前進方式(對於子域甚至整個專案)。非技術領域的理解是最重要的,並且還有助於在整個開發過程中保持(非技術)利益相關者的參與。
 
對我來說,重要的是戰略模式,即你如何思考談論你的領域。許多(微服務)軟體出錯的是有界上下文和 API,可以透過事件風暴(討論您的域中發生什麼樣的事情)和上下文對映(該 [子] 域如何與其他域互動)來改進它們。然後是無處不在的語言,或者說它對業務來說是什麼,
我是一名阿根廷西班牙語-英語雙語程式設計師。我嘗試只用英語程式設計,但在開發與阿根廷系統的整合時,我經常不得不退回到西班牙語程式碼。
一般來說,最好只使用英文,因為程式碼更易讀(因為語言的關鍵字和 API 都是英文的),而且要保持與名詞-形容詞順序、動詞時態等的一致性。一些本地概念可以很容易地翻譯(或者至少看起來是這樣)就像invoice-factura ......但是我不可避免地會得出沒有明顯翻譯的概念(所以我可以彌補,但對其他人來說不夠清楚)或者對於其中翻譯並不完全一致。
 

pydry
我注意到類似的東西。在我們的程式碼庫中引入 DDD 的最小 PR 使程式碼庫膨脹了大約 1,000 行,散佈在整個程式碼庫中。我認為如果我們在任何地方都使用它,它最終總共會增加大約 12-15,000。那本來是蟲子的肥沃溫床。
這些想法對需要頻繁重構的邏輯複雜程式碼有意義,但在大多數情況下,所有不同層之間的嚴格分離只會導致大量程式碼。太多了。
我們也無法就有界上下文的限制真正在哪裡達成一致。在這個問題上的大多數文件是一個單純的handwave說:“你看著辦吧”或者“當你做這些練習與企業,它會變得清晰”(它沒有),這是奇怪給出如何極其重要的是,如何將其損壞是繫結錯誤的東西。
無法就有界上下文的限制真正在哪裡達成一致。這是軟體設計中最難的部分。難怪沒有明確的規則來說明如何做到這一點。您必須既是領域專家又是實施專家,才能在第一次嘗試時確定邊界。
我也不太相信這是您可以透過更好地與“業務”溝通來獲得的東西。
這在一定程度上激怒了我,因為遵循 DDD 模式需要大量的程式碼 - 如果邊界錯誤,程式碼量的 3-4 倍意味著重寫成本的 3-4 倍。
 

bob1029
又一個超載的技術流行語。對我來說,DDD 意味著兩件事:
1. 傾聽您的客戶如何評價他們的業務並將這種觀點內化,就好像您的生活依賴於它一樣(您的職業當然可能)。
2. 找到一種方法來構建您的產品並以類似的方式進行交流。該方法應被理解為特定領域的
任何將哲學擴充套件到這些點之外的東西都是對您的產品做出假設,而這些假設實際上只有您和您的客戶應該做出。
我在這裡做出的唯一具體的技術假設是,如果您要處理大量不同的型別和來自業務的複雜、快速變化的需求,您可能至少需要考慮 SQL 幾分鐘。如果你能找到一種方法讓企業用他們理解的語言編寫他們自己的邏輯/查詢,那麼你就發現了我個人目前所知道的最強大的力量倍增器。
 

sovietmudkipz
我正在努力研究如何將 DDD 應用於影片遊戲上下文,特別是使用 unity3d。這是一場鬥爭,因為我認為遊戲創造者的文化時代精神不喜歡應用來自“外部”影響的軟體模式,比如企業軟體。
我認為遊戲軟體是整個系統,而不僅僅是遊戲客戶端。這意味著任何後端或基礎設施都是複雜整體的一部分。
後端系統的 DDD 很好理解。不同之處在於它需要為遊戲客戶端以及任何其他客戶端提供服務(例如營銷遊戲的網站、釋出遊戲相關的論壇,甚至可能執行聊天機器人的邏輯)。如果您想向您的遊戲客戶端公開線上服務,後端系統是您需要考慮要執行的邏輯和要持久化的狀態的地方。
我喜歡 DDD 用於某些類別的遊戲客戶端程式碼,而不是全部。有一些簡單的遊戲元素是由遊戲引擎物理和碰撞驅動的。有更復雜的遊戲元素可以從更復雜的域建模技術中受益。基本上允許自己為簡單的遊戲元素編寫未經測試/輕微測試的元件。對於複雜的系統,將統一性視為領域特定邏輯的具體實現可能是有益的。用遊戲系統專家的語言對程式碼進行建模,並考慮如何將統一執行時事件(使用者輸入、碰撞)轉換為對該領域有意義的術語。
實際上,統一遊戲物件代表領域實體,遊戲物件之間的互動可以觸發領域邏輯。例如,與戰鬥遊戲物件碰撞的彈丸遊戲物件是執行戰鬥服務邏輯的好地方,這可能會觸發域事件(可觀察行為),然後訂閱者可以監聽這些事件(例如損壞 UI、吐司通知、或任何其他統一使用者介面)。
 

revskill 
我認為領域驅動設計的誕生是為了與資料庫驅動設計區分開來。所以我們在更高的層次上設計,我們的思維過程,詞彙與商業術語聯絡在一起。
我們過去常常使用 UML 設計更高階別的系統:用例圖是一種設計工具,用於與產品所有者討論領域的主題和動詞。序列圖使我們能夠捕獲域級別的任何動態和互動。
 

piaste
在未經驗證的資料和經過驗證的資料之間有一個清晰的、強型別的分離。
未經驗證的資料(DTO)只是輸入、從儲存讀取、從外部服務接收等的原始表示。任何可能的輸入都應該是可接受的,並且可以忠實地表示為 DTO。
然後,透過將 DTO 傳遞給驗證函式,您可以返回一個經過驗證的物件(模型),該物件實際上被限制為僅包含合法資料狀態;或一組可以採取行動的驗證錯誤。
你的業務邏輯應該只在經過驗證的物件上執行,這樣你才能真正依賴你的基本假設,並且可以表達實際的工作流規則(例如“你不能結帳一個空的購物車”)並與瑣碎的驗證(例如。 “數量必須大於 0”)。
 
DDD 是一個軟體工程概念,如果你有100 名十年經驗的軟體工程師,那麼他們中的 30 人會不知道或理解得很差,然後你會有 70 種不同的解釋。


 

相關文章