主頁 > 軟體設計 > DDD實踐反思

DDD實踐反思

2021-04-29 09:20:58 軟體設計

某大型互聯網公司于2019年開始在XX中臺財務域進行DDD實踐,事后回顧,整體并沒有達到預期的效果,個人也做了很多的反思和總結,形成此文,

1. 背景

為什么當時要實踐DDD?其中的緣由比較復雜,可以從外部和內部兩個視角來看,

首先,從外部也即整個BU的視角來看,最先開始實踐DDD的是A域,并在該域誕生了一套在公司現有RPC框架之上的業務SPI框架(以下簡稱為【N框架】),相較于dubbo這樣純技術的服務框架,它有以下特點:

  • 標榜serverless,自身提供了代碼托管和運行容器,可以直接進行服務的開發、部署及運維,也可以將現有docker應用的服務以SPI的形式注冊到這個框架上并發布,實作“服務市場”的效果
  • 可以進行服務的熱插拔,不停機升級回滾不同版本的服務
  • 業務SPI管控,可以將SPI按照業務域劃分到不同的路徑下,方便管理和業務發現、服務編排

在BU內部推行N框架時,對于現有的應用,需要將核心服務用SPI的方式注冊上去;對于新接入的業務,則推薦使用serverless形式的bundle提供服務,對于哪些是“核心服務”,這些“核心服務”是否足夠標準化,亟待一輪梳理甚至重構,

其次,從本域來看,在組織架構調整后,線上同時運行的多套系統已經日漸成為瓶頸,由于歷史原因,XX中臺財務域對接多個業務域時,往往會新搭一套系統,造成了當時一共有五套財務系統運行在線上,系統間相互依賴,系統內又有大量的if...else硬編碼來處理定制化的需求,在這種情況下,無論對于新業務、新需求的支持,還是對于現有業務的運維,都需要付出巨大的人力成本,并且存在著很多隱患,多版本歸一化迫在眉睫,

因為供應商發票在整個財務域的最下游,相對比較獨立,并且對于現有的系統業務方也有開票流程線上化的訴求(原先的流程存在大量的人工步驟:是將對賬單匯出為excel,匯入到開票系統,然后再將開票結果資料導回系統),所以選定了供應商發票這個子域作為第一個試點,目標是新建一套銷項發票系統,發布可擴展的SPI,并將已有的業務線流量逐步切過來,降低運維成本,提高研發效率,

2. 實踐

2.1 布道

對于DDD,其中有很多的概念和方法,需要所有開發認知達成一致,這里就不重復那些經典的概念了,

這里想稍微聊一下”六邊形架構“,為什么是六邊形,不是正方形、五邊形、八邊形?我思考了很久,得出的結論是:六邊形比較好看,而且也好畫,具體這六個邊除了表示邊界,并沒有什么實際的含義,比如六大金剛什么的,使用”六邊形架構“,一是為了和傳統的分層結構進行區分,二是為了表示這個系統不是孤立的,而是在一個大網格中的一個節點,

對于物體,最初我的理解是現實中存在的物件,在DDD里則被定義為”有識別符號來區分的物件“,從哲學的角度,則是”是客觀存在并可相互區別的事物“,這樣理解思路就開闊多了, ”訂單“是物體,”抽獎活動“也可以抽象為物體[1]

需要注意的是,一定要遵守現有的或形成一套統一的命名規范,比如DO,一般指的是DataObject,但是DomainObject也能縮寫成DO,是不是很神奇?

2.2 建模

首先使用用例分析法,分析現有系統+短期未來中需求的用例,“發票”這一物體在現實世界中相對固定,所以建模相對比較簡單——實際上并不完全正確,在子域劃分中可以看到,不僅僅只有一個發票物體,

但是僅通過用例分析,又顯得比較單薄——甚至很多業務場景都能套進這個模板中,因此需要在后續的環節(分析流程中缺失的物體)中豐富一些細節進來,

至于當時為什么沒有考慮四色分析法和事件風暴法,事后回想這個問題,可能原因是:老系統的代碼和場景比較復雜,新系統可以按業務線維度做進行遷移的時候再進行擴展,第一版不需要考慮大而全的所有場景,因此只需要梳理好SOP即可,而四色分析法,事件風暴法對于老系統的分析成本過高,即使將所有開發集中到一起也難以將所有事件羅列出來,

建模的結果簡單表示如下:

各域職責如下:

  • 費用域:對接上游不同形式的單據,統一轉化成可以用來開票的賬款單
  • 開票申請域:抽象開票的程序資訊,包括發票待填充欄位和單據拆分規則
  • 開票執行域:對接不同的開票ISV,提供統一的開票能力,

把發票域再劃分成更細的子域,是出于以下考慮:

  • 限界背景關系更清晰,一個聚合根就是一個子域
  • 將高內聚低耦合、單一職責原則極致化,外部應用可以自由選擇呼叫哪個子域的服務,從而決定自己的應用邊界
  • 后續團隊的擴張,更加專人專職,在需求迭代時降低并發度,避免十幾個人同時修改一個系統的局面

2.3 編碼

  1. 按照應用邊界劃分以后,按子域分別建立應用、申請主機實體、DB資源等,
  2. 由于充血模型的repository注入會導致寫測驗用例比較麻煩,采用了貧血模型,發票本身也沒有什么領域方法,再加上子域已經拆到最細了,跨子域操作都需要通過RPC來互動,當時只抽取了業務校驗和計算金額的方法出來,

實踐期間遇到的最大問題是,原先面向DO的CRUD程序式編程(當然其中也有一定的抽象和封裝),要轉到不關注存盤結構、所有物件都在記憶體中的DDD,會很不適應,并且,你會發現如何處理底層存盤又是繞不開的,諸如模型轉換和事務處理,不可能完全照搬DDD,也不能重回CRUD的老路上去,非常的別扭,只能做一定程度的折中,

3. 問題

  1. 在建立領域模型時,產品側很少參與,業務方則基本沒有直接參與,整個用例分析和建模的程序技術團隊反復的開會討論,耗費了很多時間,但是對于使用者來說并沒有相應的體感,實際上這違反了DDD的一大前提:需要技術團隊和業務團隊__共同__建立一套領域語言,才能減少后續的交流溝通成本,這導致了后續的需求溝通仍停留在原先的水平上,沒有提升什么效率,更嚴重的是,有的需求上線了,但是業務發現并不好用(甚至不如老系統好用),舉一個例子:業務方想知道哪些賬單開了哪些發票,開票狀態是什么,老系統直接就能展示(當然這也和老系統實際開票鏈路是人工的,系統層面很簡單有關);新系統卻要先找到當時的申請單,申請單上找到對應的發票,可是業務方視角下完全是沒有申請單的概念的,他們也不關心申請單ID,只要把發票開出來就行了,
  2. 拆分出子域過多,并沒有帶來其好處,反而帶來了一些副作用:
    1. 專案聯調成本比較高,特別是專案剛上線時問題比較多,和有新人加入需要上手,由于開票流程至少跨越了子域的三個系統,出問題時為了定位,可能要在這三個系統之間來回穿梭,查看日志、反復debug,效率很低
    2. 由于人員變動,原先規劃的每個應用2人互為backup,在相當一段長的時間變成了1人同時需要負責5個系統的運維和需求,嚴重擠占了個人時間
    3. 分布式系統的一致性問題被放大,核心的三個域既要各自進行的冪等,又要做跨系統核對來保證最終一致性,
    4. 額外的RPC開銷使得業務失敗幾率變大,在單據數目較多的情況下提交開票很容易超時,只能進行限制,
  3. 上游系統的域也在做DDD實踐,他們的模型變了好幾版,導致發票域的待開票單據模型很多欄位都廢棄了,因為是大而全的模型,欄位不夠用倒是未出現,
  4. 不同子域使用了不同的分庫分表規則,增加了問題的排查難度,
  5. 由于不同子域牽頭的開發不一樣,對于技術選型在架構組也沒有給出結論,自由發揮的空間很大,有的子域用了一些事后發現有坑的技術,舉幾個例子:
    • JPA,之前全組慣用的是mybatis,JPA”看上去“更適合直接系結領域模型,但是其門檻比較高,需要花很多的時間去學習,同時,在分庫分表的環境下,想寫定時任務處理,只能用entityManager來寫原生SQL拼接分表名
    • Guava EventBus(實際是上游域用的),場景是用于發送領域事件,Guava EventBus實作了觀察者模式,可以將流程解耦,同步或異步地進行后續處理,看上去很適合做領域事件的載體,但是它是單機JVM范圍內的,如果發生宕機或重啟,未處理的事件直接丟失,【思考:如果仍然想用Guava EventBus來發送領域事件,如何防止這個問題?答案是先將領域事件持久化,】
  6. 照搬現實世界的物體,帶來了一些意想不到的問題,如上圖的發票模型,并沒有保存business_parnter_id,畢竟現實中是不存在的,如果需要查詢,直接從申請單的invoice_id去查即可,但是當需要做鑒權時,也即需要判斷這張發票是否屬于該用戶時,無法直接從發票物體上判斷,不得不繞道到發票申請域,
  7. 預想的用來方便擴展的設計,實際上并沒有用到,比如開票執行域,預期能夠對接不同的開票ISV,但是該系統上線近兩年都只接入了一家ISV,并且在可預見的一年以內,都沒有接入其他ISV的需求,又如CQRS,除了OpenSearch和MySql這兩個資料源,沒有其他資料源,并且所使用的MySql實體的主從結構目前對于開發是透明的,所謂CQRS只不過是代碼層面寫操作繼續走repository,讀操作繞過repository直接查詢DAO而已,
  8. 另外一個預想的讓業務接入方/行業研發來撰寫防腐層、直接呼叫下層服務,則基本沒有影子,畢竟業務方開發資源也有限,平臺還沒有發展到那么強大的程度,
  9. 與現有技術框架是否能相容,這個看上去不像是DDD的問題,因為DDD更關注業務,實踐中遇到的問題是:兩個物體有回圈參考(就像Father和Son兩個類相互持有對方一樣),在通過自定義日志攔截器打日志時,由于使用的是fastjson做序列化,回圈參考直接stackoverflow了,【思考:除了去除回圈參考外,如何解決這個問題?答:可以關閉fastjson的回圈參考功能,更好的實踐是手寫物體的toString()方法,選擇要列印的資訊】

4. 反思

  • DDD最關鍵的一點是和產品、業務保持溝通,才能形成共識也即領域語言,不能僅僅是技術自high和閉門造車,這樣是無意義和浪費的,此外,除了自己的域也要關注上下游,才能讓模型高內聚低耦合,

  • DDD不能教潭訓,需要因地制宜,其實很早之前業界推行的分層架構本身已經有DDD的影子了,不要為了拆分出更多的應用而劃分子域,同一個應用是可以包含多個子域的,是否需要進一步拆分要由業務現狀和發展來確定,

  • 在發票域這個具體的場景里,可以看出領域模型本身并不是易于變化的,經常變更的是規則和接入層,那么基于這個來擴展規則的配置和運轉、以及接入層的校驗和填充,會取得更好的結果,

  • DDD是一個持續的程序,不能一蹴而就,要隨著業務的發展而持續迭代,

5. 再談......

5.1 再談CQRS

CQRS全稱是Command Query Responsibility Segration,即命令與查詢分離,一般架構圖如下:

(圖源: https://zhuanlan.zhihu.com/p/115685384)

最最簡化的實作方式,是代碼層面繞過Repository,直接查詢DAO,然后轉化成VO傳給呼叫方,這樣做初看并沒有什么卵用,但是結合到具體的業務場景來看,就有用處了,舉幾個例子:

  • 應用使用了多個資料源,如MySql+ES/opensearch,在分庫分表場景下,如果需要查詢”所有用戶+狀態為未開票 的 所有對賬單“,直接走MySql是無法查詢的,只能使用搜索引擎預先創建的索引,這是一種讀寫不分離也得分離的情況,

  • 資料源的拓撲結構,MySql的讀寫分離是透明的,假如要自己造輪子,在應用層面指定寫庫和讀庫,并自己提供同步機制,那么此時就可以分別對寫庫和讀庫做操作,”強行“讀寫分離,

  • 保持領域物件和Repository的純潔性,有很多讀操作,都是領域方法和Application層的業務邏輯用不到的,僅僅是提供給外部系統做查詢,如果在Repository中加入了大量的查詢方法,會增加維護成本,同時,領域物件之間操作時,加載的物件一般是完整的;但是對于外部查詢,考慮到領域物件和DB表結構并不完全一致,需要進行定制化的簡化和組合,如下圖中如果只查商品基礎資訊,是沒必要加載整個領域模型的

【思考】如果一個領域物件A需要操作另一個領域物件B,那么加載B是否走的讀操作?

【個人見解】否,應該通過Repository加載,

5.2 再談架構分層

img

不管是三層架構,還是六邊形架構,其核心總是Application-Domain-Infrastructure,這并不意味著代碼的組織形式必須完全照搬,我們仍可以使用更細的劃分方法和層次結構,以下提供一種劃分和命名方式作為參考:

  • User Interface,一般命名為client/facade,包括對外暴露的服務介面和DTO,雖然從分層的視角來看User Interface屬于Application層,但是為了打二方包提供給外部使用,只能單獨拆分出來

  • Application

    • assmbler,用于DTO和domain model的轉換
    • service,應用服務,編排領域服務,可以提供事務等,不包含業務邏輯
  • Domain

    • core-service,領域服務,完成跨多個領域模型時的操作
    • core-model,領域模型,用來承載聚合根、物體,如果包含多個子域,可以用包路徑來區分
  • Infrastructure

    • common,通用工具,包含一些常量、相對獨立的工具(如PDF轉換、MD5加解密等)、通用的類(自行封裝的Exception)、通用配置等
    • message,對接訊息中間件
    • dal,對接DB持久化層
    • 其他基礎設施

在邏輯上分層之后,實際編碼中也會遇到一些問題,需要采取折中,比如:

  • 首先也是最關鍵的一點:在Maven專案中,代碼分層是通過pom的組織關系實作的,如果想按照更明顯的依賴關系,如Application bundle包含assmbler和service兩個bundle,會發現配置起來很麻煩也很容易出錯,其他層bundle跨層依賴時也很難受,方便起見,可以僅僅通過命名(甚至是約定俗成)來體現哪個bundle屬于哪一層,bundle之間的依賴通過pom解決,

  • DO和Domain Model的Convert放在哪里?假如Repository介面放在Domain層,實作放在Infrastructure層,會發現Repository操作的是Domain Model,強行讓Infrastructure的dal層不得不依賴Domain Model層,破壞了上層依賴下層的關系,因此只能將Convert放在Domain層,直接對DO的操作顯得很刺眼,單獨再抽一層又十分的冗余,

6. DDD最佳實踐?

DDD真的有最佳實踐嗎?就目前來看,沒有,DDD不能只靠閱讀就能充分理解,需要通過真正的實踐,也會遇到挫折和懷疑,需要及時回顧和反復的學習,即使是聚合邊界和聚合根的尋找,也是一件有難度的事情,

一種直覺性的實踐方法是,看看代碼是否有”壞味道“,舉例幾個例子:

  1. 一個物體持有了大量的其他的物體,比如School類中包含了一個的List<Student>,那么這個物體是不是會顯得很笨重?即使用lazy-load來處理Student,仍然是反模式的,那么不如在領域模型層面將二者的參考關系解除掉,當需要操作這個School的所有Student時,在School類的領域方法中再進行處理,
  2. 如果DDD后的代碼可讀性變差了,那么這和DDD的初衷也是背離的,
  3. 對某類物體A批量操作(如果沒有關聯到另一個和A有關系的物體B上去)不得不在A中完成也是一種”壞味道“,Evans建議,當你在懷疑是否應該在一個類中放入”壞味道“的方法、其原因是你覺得它不屬于這個類時,用一個ServiceFoo類來放這個方法,
  4. 貧血模型和充血模型,究竟選哪個,這兩種模型的最大區別是Repository是否屬于領域物件,充血模型需要走點彎路去注入Repository,并且測驗起來會難一些,其實領域驅動在建模時更關注的是如何提取領域方法并和領域模型整合

個人認為DDD的最佳實踐是,不斷的重構,尋找模型中有問題或蹩腳的地方,如物件應從關聯導航還是倉儲獲取?聚合設計是否正確?模型性能是否OK?然后停下來重構,

但是重構和滿足業務當前需求在時間上是有沖突的,大規模重構會帶來回歸測驗的作業量和一定的風險,如何平衡也是個問題,小心過度設計,

7. 新知

在撰寫本文的同時,也讀了一些其他文章,補充了現有的認知,

  • 不應該給物體定義太多的屬性或行為,而應該尋找關聯,發現其他一些物體或值物件,將屬性或行為轉移到其他關聯的物體或值物件上,
  • 跨物體的互動放在領域方法里,
  • 為什么Repository層不應該使用insert、update等作為方法命名?因為這些名稱和SQL是強系結的,而對于快取如Redis,SET就是插入或更新,因此使用更加通用的命名如find、save、remove,再在實作里選擇具體的DAO方法做處理,
  • “用戶需求”不能等同于“用戶”,捕捉“用戶心中的模型”也不能等同于“以用戶為核心設計領域模型”, 《老子》書中有個觀點:有之以為利,無之以為用,在這里,有之利,即建立領域模型;無之用,即包容用戶需求,舉些例子,一個杯子要裝滿一杯水,我們在制作杯子時,制作的是空杯子,即要把水倒出來,之后才能裝下水;再比如,一座房子要住人,我們在建造房子時,建造的房子是空的,唯有空的才能容納人的居住,因此,建立領域模型時也要將用戶置于模型之外,這樣才能包容用戶的需求,[2]
    • 我們設計領域模型時不能以用戶為中心作為出發點去思考問題,不能老是想著用戶會對系統做什么;而應該從一個客觀的角度,根據用戶需求挖掘出領域內的相關事物,思考這些事物的本質關聯及其變化規律作為出發點去思考問題,
    • 領域模型是排除了人之外的客觀世界模型,但是領域模型包含人所扮演的參與者角色,但是一般情況下不要讓參與者角色在領域模型中占據主要位置,如果以人所扮演的參與者角色在領域模型中占據主要位置,那么各個系統的領域模型將變得沒有差別,因為軟體系統就是一個人機互動的系統,都是以人為主的活動記錄或跟蹤;比如:論壇中如果以人為主導,那么領域模型就是:人發帖,人回帖,人結貼,等等;DDD的例子中,如果是以人為中心的話,就變成了:托運人托運貨物,識訓人識訓物,付款人付款,等等;因此,當我們談及領域模型時,已經默認把人的因素排除開了,因為領域只有對人來說才有意義,人是在領域范圍之外的,如果人也劃入領域,領域模型將很難保持客觀性,領域模型是與誰用和怎樣用是無關的客觀模型,歸納起來說就是,領域建模是建立虛擬模型讓我們現實的人使用,而不是建立虛擬空間,去模仿現實,
  • 聚合根如何設計?關于領域驅動設計(DDD)中聚合設計的一些思考

其他參考文獻


  1. 美團技術團隊:領域驅動設計在互聯網業務開發中的實踐 ??

  2. 領域驅動設計之領域模型
    阿里盒馬領域驅動設計實踐-InfoQ ??

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/281185.html

標籤:其他

上一篇:“一學就會,一做就廢”微服務的架構模式:一個服務一個資料庫模式

下一篇:架構師成長記_第七周_04_CAS單點登錄系統構建(一)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more