18.清晰架構(02): 超越同心圓分層(譯)

原文:https://herbertograca.com/2018/07/07/more-than-concentric-layers/

這篇文章是軟件架構編年史()的一部分,這部編年史由一系列關于軟件架構的文章組成偎箫。在這一系列文章中溉苛,我將寫下我對軟件架構的學習和思考,以及我是如何運用這些知識的娇唯。如果你閱讀了這個系列中之前的文章寂玲,本篇文章的的內容將更有意義。

我之前的這篇系列文章()中拓哟,我發(fā)表了一幅信息圖,展示了用來理解代碼單元類型之間聯(lián)系的心智地圖流纹。

然而漱凝,我始終覺得有一部分內容并沒有得到很好的體現(xiàn),但我不知道應該如何更好地將它展示出來茸炒。這個部分就是共享內核壁公。

而且,我還發(fā)現(xiàn)了一些新內容紊册,在這篇博客中我將記錄下所有的內容湿硝。

觀察上一篇博客中發(fā)表的信息圖润努,我們發(fā)現(xiàn)共享內核位于圖的中心,看起來好像在領域層內部痢畜,疊在代表領域上下文的同心圓之上鳍侣。

盡管將共享內核放在這個位置倚聚,但我要表達的并不是共享內核會依賴其余部分的代碼,它也不是領域層內部的另一個層次惑折。

什么是共享內核?!

共享內核由 DDD 之父 Eric Evans 定義白热,它是多個限界上下文之間共享的代碼粗卜,由開發(fā)團隊決定:

[...] 兩個團隊同意共享的領域模型的子集。當然攻臀,和模型子集一起共享還包括代碼的子集,還有和這部分模型有關的數(shù)據(jù)庫設計百匆。這部分明確要共享的內容有著特殊的狀態(tài)呜投,而且在沒有和其他團隊達成一致的情況下不應該修改。

Shared Kernel, Ward Cunningham 的 DDD wiki

所以基本上雕拼,它可能是任何類型的代碼:領域層代碼粘招、應用層代碼、庫辑甜,隨便什么代碼袍冷。

然而胡诗,在我的這份心智地圖里,我將它當做一些特定類型的代碼的子集骇陈。在我的心智地圖里瑰抵,共享內核包含的是領域層和應用層的代碼,這些代碼會在限界上下文之間共享婿崭,讓這些上下文可以互相通信习贫。

這意味著,例如颤绕,一個或多個限界上下文觸發(fā)的事件可以在其它的限界上下文里被監(jiān)聽到。需要和這些事件一起共享的還有它們用到的所有數(shù)據(jù)類型物独,例如:實體 ID氯葬、值對象、枚舉官研,等等闯睹。事件不應該直接使用像實體這樣的復雜對象,因為將它們序列化到隊列中或是從隊列中反序列化時都會遇到一些問題始花,所以共享的代碼不應該太寬泛孩锡。

當然,如果我們手中的是一個由不同語言開發(fā)的微服務組成的多語言系統(tǒng)浇垦,共享內核必須是描述性的語言斩披,格式是 json、xml、yaml 或者其它厕倍,這樣所有的微服務都能理解贩疙。

因此,共享內核就完全和其余的代碼以及組件完全解耦了组民。這樣很好悲靴,因為這意味著盡管組件耦合了共享內核,但組件之間不再耦合耸三。共享代碼可以被清晰地識別出來,并輕松地提取到一個獨立的庫中憨颠。

如果我們決定將一個限界上下文從單體中分離出來并提取成一個微服務积锅,這也會很方便。我對共享代碼了然于心淫茵,可以輕松地將共享內核提取到一個庫中蹬跃。而這個庫即可以安裝到單體中蝶缀,也可以安裝到微服務中。

所以回顧一下翁都,在我的心智地圖中柄慰,應用核心依賴共享內核,共享內核包括了在限界上下文之間共享的領域層和應用層代碼藏研。

當語言不夠用時…

這樣概行,我們得到了包含同心圓層次的應用代碼,而應用核心依賴著支撐所有這些代碼的共享內核业踏。

我們還可以說所有代碼都依賴它們所使用的編程語言涧卵,但我們對這樣顯而易見的事實熟視無睹。

然而我要拋出這個事實伐脖,原因是還有一個問題“當語言結構不夠用時我們該怎么辦晓殊?认烁!”。顯然我們會自己創(chuàng)造語言結構嘹承,來填補這些語言的瑕疵撼港。隨后我會提出下一個重要的問題“我們如何傳遞這些代碼之所以存在地背后原理?我們把它放在哪里?我們如何清晰地表達使用它的時機懒震?使用方法个扰?”

我見過做法的是,我自己也是這樣做的,將代碼放在一個名為 Utils 或 Commons 的包里土榴。但它最終會變成一個筐子赫段,當我們不知道代碼該放在哪兒時,就會一股腦兒全扔進這個筐子里!不同類型的代碼额获,不同用途的代碼抄邀,還有不同用法(包裝在適配器里使用,或是直接使用...)的代碼最后都被扔在這里奥喻,這個包沒有概念性的含義读宙,沒有一致性,沒有內聚性,一點也不明確蔫耽,到處充斥著歧義。

我想拋棄 Utils 和 Commons 包黑毅!

每一個包都必須在概念上內聚钦讳!何時使用包以及如何使用包必須是明確的潮秘!不能有任何歧義!

因此买猖,舉個例子玉控,如果我們的應用有一些特殊的和 CLI 交互的方式高诺,我們可以把相關代碼放在“Acme/App/Infrastructure/Cli/SpecialCli”命名空間下,而不是放在“Acme/Util/SpecialCli”命名空間下牡拇。前一個名字告訴我們這個包和 CLI 有關,它是“Acme”公司的應用“App”的“Infrastructure”(基礎設施)的一部分剔蹋。既然它是應用基礎設施的一部分,也就是說應用核心中還應該有一個端口矫付,它必須遵循這個端口。

另一種情況是而叼,如果我們發(fā)現(xiàn)包是這種語言自己應該/能夠具備的一些東西,我們可以把它放在可以體現(xiàn)出這層含義的命名空間之下脱篙,比如“Acme/PhpExtension/SpecialCli”。這個名字告訴我們這個包應該被看作是語言自身的一部分,因此其中的代碼應該被其它代碼像語言結構一樣直接使用笔喉。但是作谭,如果其它公司依賴這個包時折欠,顯然不會傻傻地直接依賴它,而是為它創(chuàng)建端口/適配器,這是更妥善的處理方法斤葱,這樣他們可以換掉它。然而,如果這個包是我們自己來負責幔烛,我們就可以決定把它當成語言的一部分來對待饿悬,因為出現(xiàn)尋找替代品的風險的幾率要小得多狡恬。這里總有一些權衡。

另一個我們可以認為是語言的一部分的例子是 PHP 中的 UUID兔乞。我可以不把它想成是語言的一部分熊榛,因為每隔一段時間就會有一個新版本并造成一些維護的負擔玄坦;但它卻是一個通用、廣泛和一致的概念喻喳,足以成為語言的一部分。

所以慷丽,為什么不創(chuàng)建一個 UUID 的實現(xiàn)纲熏,把它當成 PHP 自身的一部分來使用呢勺拣?就像我們使用 DateTime 對象一樣宣脉?只要實現(xiàn)還在我們的掌控之中谈跛,我覺得沒有什么壞處。

那么 Doctrine Query Language (DQL) 呢? (Doctrine 是 Hibernate 在 PHP 中的移植) 我們能把 DQL 當成 SQL嫂沉、Elasticsearch QL 或 Mongo QL 嗎?

總結

所以總結一下,我在宏觀層面發(fā)現(xiàn)了四種主要的代碼類型蜀漆,而且我認為在代碼組織中將它們清晰地展現(xiàn)出來确丢,是我們避免最終形成大泥球的關鍵。

于我而言,不能質疑的真相是架構就在那里,唯一的問題是:它在不在我們掌控之中益缠?基公!

因此胰伍,讓我們清晰地組織好代碼骂租,來幫助我們表達架構渗饮,全盤或者部分遵循我的心智地圖互站,遵循你自己的心智地圖胡桃,或者遵循其他人的心智地圖都可以标捺,但是請使用一致的推理思路來組織代碼亡容,讓項目可以使用結構和代碼組織來清晰地表達架構闺兢。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末屋谭,一起剝皮案震驚了整個濱河市龟糕,隨后出現(xiàn)的幾起案子桐磁,更是在濱河造成了極大的恐慌,老刑警劉巖讲岁,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件我擂,死亡現(xiàn)場離奇詭異衬以,居然都是意外死亡,警方通過查閱死者的電腦和手機校摩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門看峻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人衙吩,你說我怎么就攤上這事互妓。” “怎么了坤塞?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我伐厌,道長轩猩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任焦影,我火速辦了婚禮舶担,結果婚禮上,老公的妹妹穿的比我還像新娘狱意。我一直安慰自己镐作,他們只是感情好,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布曙寡。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上刃泌,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天俗扇,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛护蝶,可吹牛的內容都是我干的堤魁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼逢慌,長吁一口氣:“原來是場噩夢啊……” “哼鉴象!你這毒婦竟也來了傍睹?” 一聲冷哼從身側響起吮炕,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤迎膜,失蹤者是張志新(化名)和其女友劉穎簸呈,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蜕便,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡轿腺,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年仿荆,在試婚紗的時候發(fā)現(xiàn)自己被綠了庐冯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出油湖,到底是詐尸還是另有隱情巍扛,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布乏德,位于F島的核電站撤奸,受9級特大地震影響,放射性物質發(fā)生泄漏喊括。R本人自食惡果不足惜寂呛,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望瘾晃。 院中可真熱鬧,春花似錦幻妓、人聲如沸蹦误。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽强胰。三九已至,卻和暖如春妹沙,著一層夾襖步出監(jiān)牢的瞬間偶洋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工距糖, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留玄窝,地道東北人牵寺。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像恩脂,于是被迫代替她去往敵國和親帽氓。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內容