不要臉的業(yè)務(wù)構(gòu)件

最近看到一篇微信文章,是建筑師馮果川在一席中的演講,標(biāo)題叫做《我今天講的所有建筑都是不要臉的建筑》,很受啟發(fā)。我覺得拿來比喻我一直在考慮的應(yīng)用架構(gòu)中業(yè)務(wù)構(gòu)件的拆分,是最合適不過的了,因此就果斷盜用了其中的關(guān)鍵詞——“不要臉”,當(dāng)然多少也有點(diǎn)標(biāo)題黨的嫌疑。

1.要臉的建筑

馮果川說,中國(guó)的公共建筑有一個(gè)標(biāo)準(zhǔn)的語(yǔ)法,這個(gè)語(yǔ)法就是建筑一定要有一張臉,然后你必須要跟建筑保持一個(gè)距離來欣賞這張臉。這種房子是不是只有朝街的這一面給你看?而且為了讓你看清楚,它還留了一定的距離,這個(gè)距離可以經(jīng)常被稱作廣場(chǎng)這樣的東西。

比如上??萍拣^,前面有一個(gè)超尺度的方塊廣場(chǎng)。怕你觀賞的距離不夠遠(yuǎn),修了個(gè)這么大的廣場(chǎng)。那個(gè)廣場(chǎng)有人待嗎?門可羅雀。待在那是要接收太陽(yáng)能嗎?


這些建筑都是龐然大物,它擱在這里就是一個(gè)幾百米的障礙物,你要達(dá)到你的目的地必須繞過它,繞得很心煩。

這些高樓落在地上,我們?nèi)四茏叩木褪歉邩侵虚g那點(diǎn)縫隙,所以這個(gè)城市讓我們覺得被排斥了。

2.不要臉的建筑

馮果川要把這個(gè)地塊切碎,讓人能夠走進(jìn)去,所以人的漫游和開發(fā)商的利益兩不耽誤,最后可以形成這樣的一個(gè)效果。你看到這些曲折的路,這些小尺度的庭院,庭院里面很安靜,遠(yuǎn)離了城市的喧囂。


這一類的建筑,前面沒有廣場(chǎng),也沒有一個(gè)正立面,被馮果川稱之為“不要臉”的建筑。

馮果川把要臉的建筑和不要臉的建筑做了個(gè)對(duì)比:



可以看到,要臉的建筑以大塊的空間,阻礙了和人、和自然之間的順暢交流,空間層次單一而呆板,而不要臉的建筑,把整體的單一建筑分割成可以隨意布置的多個(gè)小的建筑,不僅豐富了內(nèi)外的層次和變化,而且也便于和人、和自然的交流。

3.不要臉的業(yè)務(wù)構(gòu)件接口

由此我想到了我們的應(yīng)用架構(gòu)。過去的單體應(yīng)用如和要臉的建筑一樣,龐大的體量,為了和它打交道,需要一個(gè)龐大如廣場(chǎng)的接口,才能和它進(jìn)行溝通。而微服務(wù)架構(gòu)的興起,正是要把龐大的單體應(yīng)用切割成不要臉的建筑,切割成一個(gè)一個(gè)微小的服務(wù),讓每個(gè)微服務(wù)都能夠和外界交互、讓外部系統(tǒng)可以直接走進(jìn)來調(diào)用。


組成微服務(wù)的業(yè)務(wù)構(gòu)件本身是否還可以繼續(xù)拆分呢?

我們先看一個(gè)例子。

客戶查詢自己剛剛添加進(jìn)購(gòu)物車的物品信息,發(fā)現(xiàn)加入購(gòu)物車按鈕點(diǎn)了兩次,結(jié)果同一個(gè)物品的數(shù)量是2個(gè),而不是自己需要的1個(gè),于是點(diǎn)了一下旁邊的減號(hào),把數(shù)字變成了1,然后保存。


客戶的操作分成兩步,第一步是查詢購(gòu)物車信息,查詢結(jié)果的展現(xiàn)包括了要購(gòu)買的產(chǎn)品的詳細(xì)信息,包括圖片、描述、原價(jià)、優(yōu)惠價(jià)等,也包括了購(gòu)物車相關(guān)的信息,如數(shù)量、金額等。第二步是修改購(gòu)物車信息,需要提交的信息有購(gòu)物車項(xiàng)的編號(hào)(頁(yè)面不可見)、數(shù)量、金額,而不需要包括產(chǎn)品相關(guān)的信息。

從這里我們可以看到,查詢展現(xiàn)的信息和修改提交的信息并不相同,查詢一個(gè)購(gòu)物車項(xiàng),不能僅僅展現(xiàn)產(chǎn)品編號(hào)和數(shù)量、金額??蛻暨€需要看到詳細(xì)的產(chǎn)品的圖片、描述、單價(jià),才知道到底是否選擇了正確的產(chǎn)品進(jìn)行購(gòu)買;而提交修改時(shí)僅僅需要提交客戶能夠修改的、屬于購(gòu)物車項(xiàng)本身的信息即可,那些屬于產(chǎn)品的、用于查詢展示的、并不屬于購(gòu)物車項(xiàng)本身的信息是不需要提交的。

這類場(chǎng)景是普遍存在的,因此需要把查詢數(shù)據(jù)的服務(wù)接口和用于生成、修改數(shù)據(jù)的接口分開,形成單獨(dú)的、可以復(fù)用的服務(wù),以便滿足外部各種類型的應(yīng)用,這種模式叫做CQRS,即命令和查詢職責(zé)分離。


把對(duì)構(gòu)件的請(qǐng)求拆分為查詢和命令兩種后,即使是命令請(qǐng)求,按照客戶實(shí)際的使用場(chǎng)景,對(duì)同一個(gè)業(yè)務(wù)對(duì)象的增刪改的請(qǐng)求也會(huì)有多個(gè)。

比如說要管理一個(gè)商鋪的產(chǎn)品,要配置/修改產(chǎn)品的基本信息,配置/修改產(chǎn)品的詳情,修改價(jià)格,上架,下架等。如果只通過一個(gè)Command提供這些所有功能,就會(huì)出現(xiàn)以下問題:

1、 接口結(jié)構(gòu)復(fù)雜,晦澀難懂;

2、傳遞的參數(shù)龐大,耗費(fèi)資源,降低性能;

3、 接口參數(shù)需要根據(jù)文檔選擇填充,如果沒有詳盡的文檔就很難組織,有時(shí)為省事就傳遞全部參數(shù),浪費(fèi)資源,降低了性能;

4、接口高耦合,相互影響。

這種單一接口的Command又成為了要臉的建筑,如果把它拆分為多個(gè)單一的、職責(zé)明確的Command,每個(gè)Command只完成一個(gè)功能,多個(gè)組合起來就完成了全部功能,這個(gè)接口就改造成一個(gè)不要臉的接口了。


4.不要臉的業(yè)務(wù)構(gòu)件的對(duì)象

接口拆分完畢后,剩下的就是核心業(yè)務(wù)邏輯的處理了。對(duì)像CRM這一類業(yè)務(wù)邏輯的處理,采用面向?qū)ο蟮脑O(shè)計(jì)和實(shí)現(xiàn)方法是比較合適的,因?yàn)镃RM類業(yè)務(wù)的對(duì)象和關(guān)系和自然界中的關(guān)系非常類似,也容易進(jìn)行對(duì)象的識(shí)別和抽象。但很多業(yè)務(wù)實(shí)現(xiàn)的對(duì)象往往成了擺設(shè),真正的業(yè)務(wù)邏輯依然以成百上千行代碼的形式堆積在一個(gè)類的一個(gè)方法上,使得以后的維護(hù)成為噩夢(mèng)。

而如果真正采用了面向?qū)ο蟮脑O(shè)計(jì)和實(shí)現(xiàn)方法,通過繼承、抽象、關(guān)聯(lián)的設(shè)計(jì),把一個(gè)構(gòu)件對(duì)象拆分為多個(gè)高內(nèi)聚、低耦合的對(duì)象,復(fù)雜的邏輯拆分到各自應(yīng)該承擔(dān)責(zé)任的對(duì)象上去,大家協(xié)同一起去完成一個(gè)Command的業(yè)務(wù)處理,那么這個(gè)構(gòu)件的核心處理邏輯的也就從要臉的構(gòu)件改造成一個(gè)成功的不要臉的構(gòu)件了。

比如一個(gè)下單的處理過程,在訂單對(duì)象上完成創(chuàng)建訂單、客戶確認(rèn)、付款、完成訂單等邏輯。而訂單行相關(guān)的動(dòng)作則由不同類型的子訂單行去分別進(jìn)行。


比如訂單行的交付方式,對(duì)不同的產(chǎn)品,交付的方式是不同的,對(duì)于網(wǎng)絡(luò)類產(chǎn)品,需要在網(wǎng)元上進(jìn)行開通,對(duì)于實(shí)物類產(chǎn)品,需要通過快遞進(jìn)行投遞交付,而對(duì)于內(nèi)容類產(chǎn)品,需要通過推送或客戶主動(dòng)下載的方式進(jìn)行交付,這些不同的交付方式由對(duì)應(yīng)的不同類型的訂單行分別完成自己的職責(zé)是最合適的。

相反,如果這些邏輯全部集中在訂單對(duì)象的一個(gè)方法上去完成,可想而知這個(gè)方面會(huì)包括多少的if else。

5.結(jié)語(yǔ)

去年的一個(gè)項(xiàng)目,一個(gè)段位頗高的架構(gòu)師同學(xué),在看了不要臉的構(gòu)件設(shè)計(jì)后,質(zhì)疑說:“一個(gè)功能需要22個(gè)類去實(shí)現(xiàn),開發(fā)、維護(hù)不太容易”。用類的數(shù)量就能檢驗(yàn)開發(fā)和維護(hù)的難易程度,我也是醉了。如果一定要用數(shù)量來衡量,可能也應(yīng)該用代碼行吧?把22個(gè)類的代碼合并到一個(gè)類的一個(gè)方法中,難道就容易開發(fā)和維護(hù)了嗎?

相反,把一個(gè)類中的一個(gè)方法按照業(yè)務(wù)的本質(zhì),采用抽象、繼承的策略拆分到本來應(yīng)該承擔(dān)自己的職責(zé)的類和方法上去,更符合自然,當(dāng)然也更容易修改、擴(kuò)展和重構(gòu),這和把一個(gè)單體應(yīng)用拆分為多個(gè)可以單獨(dú)部署的微服務(wù)是一個(gè)道理啊。

要臉的構(gòu)件改造成不要臉的構(gòu)件后,如同下圖所示:


不要臉的建筑達(dá)到了建筑與人、建筑與自然的和諧,不要臉的構(gòu)件達(dá)到了業(yè)務(wù)構(gòu)件內(nèi)部對(duì)象之間的和諧關(guān)系、業(yè)務(wù)構(gòu)件與外部調(diào)用者之間自然的和諧關(guān)系,這兩種不要臉是多么的相像啊。

當(dāng)然,除了接口和內(nèi)部業(yè)務(wù)對(duì)象外,還有可能由于設(shè)計(jì)不合理,把不應(yīng)該屬于該構(gòu)件的對(duì)象放進(jìn)了該構(gòu)件中,該構(gòu)件也許應(yīng)該拆分為多個(gè)構(gòu)件,當(dāng)然,這是屬于業(yè)務(wù)建模的范疇。我打算有空的時(shí)候,《不要臉》系列的下一篇文章寫一寫《不要臉的數(shù)據(jù)模型》。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,834評(píng)論 18 399
  • 每天進(jìn)步一點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)點(diǎn)~~從開始只能寫幾句話、模仿別人的觀點(diǎn),到現(xiàn)...
    一個(gè)帥氣的名字呀閱讀 19,455評(píng)論 4 31
  • Looking for a fail-proof way to feed a big family to ever...
    安琪的簡(jiǎn)書閱讀 379評(píng)論 0 0
  • 最近項(xiàng)目沒那么忙,想著開發(fā)app的話,有很多都是重復(fù),既然是重復(fù)的,那就沒有必要每次都去寫,所以就想著寫一個(gè)app...
    想你依然心痛閱讀 937評(píng)論 0 9
  • 這次這種通透的感覺真好,當(dāng)自己清楚認(rèn)識(shí)到自己想要什么?當(dāng)自己清楚自自己目前的狀況,但自己一次次去在困難時(shí)候依然堅(jiān)...
    尹澤Rancho閱讀 298評(píng)論 2 1

友情鏈接更多精彩內(nèi)容