自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面對(duì)復(fù)雜業(yè)務(wù),if-else coder 如何升級(jí)?

開發(fā) 開發(fā)工具
針對(duì)業(yè)務(wù)在不同場(chǎng)景下的差異,我們常常會(huì)習(xí)慣性地使用if-else來實(shí)現(xiàn)不同的業(yè)務(wù)邏輯,久而久之代碼越來越難以維護(hù)。那么如何消除這些if-else?面對(duì)復(fù)雜業(yè)務(wù)應(yīng)如何思考和分析?

針對(duì)業(yè)務(wù)在不同場(chǎng)景下的差異,我們常常會(huì)習(xí)慣性地使用if-else來實(shí)現(xiàn)不同的業(yè)務(wù)邏輯,久而久之代碼越來越難以維護(hù)。那么如何消除這些if-else?面對(duì)復(fù)雜業(yè)務(wù)應(yīng)如何思考和分析?本文分享阿里高級(jí)技術(shù)專家張建飛(Frank)關(guān)于復(fù)雜業(yè)務(wù)治理的方法論,介紹一種多維度分析問題的方法:矩陣分析法。

這篇文章,是對(duì)之前我在《阿里高級(jí)技術(shù)專家方法論:如何寫復(fù)雜業(yè)務(wù)代碼?》說的“自上而下的結(jié)構(gòu)化分解 + 自下而上的抽象建?!狈椒ㄕ摰纳?jí)。因?yàn)樵谥暗姆椒ㄕ撝?,我們?nèi)鄙僖粋€(gè)多維度看問題的視角,這種維度思維的缺失,可能會(huì)導(dǎo)致miss掉一些重要的業(yè)務(wù)信息,從而使我們制定軟件設(shè)計(jì)策略的時(shí)候,陷入困難。

有了維度思維,我們便可以更加方面的去看清業(yè)務(wù)的全貌,更加全面的掌握業(yè)務(wù)信息,從而幫助我們更加體系化的去治理復(fù)雜性。

從if-else說起

我經(jīng)常說,我們不要做一個(gè)if-else coder。這里的if-else,不是說我們?cè)赾oding的時(shí)候不能使用if-else,而是說我們不應(yīng)該簡陋地用if-else去實(shí)現(xiàn)業(yè)務(wù)的分支流程,因?yàn)檫@樣隨意的代碼堆砌很容易堆出一座座“屎山”。

業(yè)務(wù)的差異性是if-else的根源。以零售通的商品業(yè)務(wù)為例。不同的處理場(chǎng)景,其業(yè)務(wù)邏輯實(shí)現(xiàn)是有差異性的。如下圖所示,商品業(yè)務(wù)的差異性,主要體現(xiàn)在商品類型、銷售方式和倉儲(chǔ)方式的不同。

??

??

 

這三個(gè)維度上的差異組合起來,有 2 * 3 * 2 = 12 之多。這就是為什么在老代碼中,到處可以看到if(組合品) blabla,if(贈(zèng)品) blabla,if(實(shí)倉) blabla 之類的代碼。

那么,要如何消除這些討厭的if-else呢?我們可以考慮以下兩種方式:

  • 多態(tài)擴(kuò)展:利用面向?qū)ο蟮亩鄳B(tài)特性,實(shí)現(xiàn)代碼的復(fù)用和擴(kuò)展。
  • 代碼分離:對(duì)不同的場(chǎng)景,使用不同的流程代碼實(shí)現(xiàn)。這樣很清晰,但是可維護(hù)性不好。

多態(tài)擴(kuò)展

多態(tài)擴(kuò)展可以有繼承和組合兩種方式。繼承勿用多言,組合有點(diǎn)像策略模式,也就是把需要擴(kuò)展的部分封裝、抽象成需要被組合的對(duì)象,然后對(duì)其進(jìn)行擴(kuò)展,比如星環(huán)的能力擴(kuò)展點(diǎn)就是這種方式。

這里,我們舉一個(gè)繼承的例子,商品在上架的時(shí)候要檢查商品的狀態(tài)是否可售,普通商品(Item)檢查自己就好了,而組合商品(CombineItem)需要檢查每一個(gè)子商品。

用過程式編碼的方式,很容易就能寫出如下的代碼:

public void checkSellable(Item item){ 
if (item.isNormal()){
item.isSellable();
//省略異常處理
}
else{
List<Item> childItems = getChildItems();
childItems.forEach(childItem -> childItem.isSellable());
//省略異常處理
}
}

然而,這個(gè)實(shí)現(xiàn)不優(yōu)雅,不滿足OCP,也缺少業(yè)務(wù)語義顯性化的表達(dá)。更好的做法是,我們可以把CombineItem和Item的關(guān)系通過模型顯性化的表達(dá)出來。

??

??

 

這樣一來,一方面模型正確的反應(yīng)了實(shí)體關(guān)系,更清晰了。另一方面,我們可以利用多態(tài)來處理CombineItem和Item的差異,擴(kuò)展性更好。重構(gòu)后,代碼會(huì)變成:

public void checkSellable(Item item){ if (!item.isSellable()){ throw new BizException("商品的狀態(tài)不可售,不能上架"); }}

代碼分離

所謂的代碼分離是指,對(duì)于不同的業(yè)務(wù)場(chǎng)景,我們用不同的編排代碼將他們分開。以商品上架為例,我們可以這樣寫:

/*** 1. 普通商品上架*/public void itemOnSale(){ checkItemStock();//檢查庫存 checkItemSellable();//檢查可售狀態(tài) checkItemPurchaseLimit();//檢查限購 checkItemFreight();//檢查運(yùn)費(fèi) checkItemCommission();//檢查傭金 checkItemActivityConflict();//檢查活動(dòng)沖突 generateCspuGroupNo();//生成單品組號(hào) publishItem();//發(fā)布商品}/*** 2. 組合商品上架*/public void combineItemOnSale(){ checkCombineItemStock();//檢查庫存 checkCombineItemSellable();//檢查可售狀態(tài) checkCombineItemPurchaseLimit();//檢查限購 checkCombineItemFreight();//檢查運(yùn)費(fèi) checkCombineItemCommission();//檢查傭金 checkCombineItemActivityConflict();//檢查活動(dòng)沖突 generateCspuGroupNo();//生成單品組號(hào) publishCombineItem();//發(fā)布商品}/*** 3. 贈(zèng)品上架*/public void giftItemOnSale(){ checkGiftItemSellable();//檢查可售狀態(tài) publishGiftItem();//發(fā)布商品}

這種方式,當(dāng)然也可以消除if-else,彼此獨(dú)立,也還清晰。但復(fù)用性是個(gè)問題。

多維分析

細(xì)心的你可能已經(jīng)發(fā)現(xiàn)了,在上面的案例中,普通商品和組合商品的業(yè)務(wù)流程基本是一樣的。如果采用兩套編排代碼,有點(diǎn)冗余,這種重復(fù)將不利于后期代碼的維護(hù),會(huì)出現(xiàn)散彈式修改(一個(gè)業(yè)務(wù)邏輯要修改多處)的問題。

一個(gè)極端情況是,假如普通商品和組合商品,只有 checkSellable() 不一樣,其它都一樣。那毫無疑問,我們使用有多態(tài)(繼承關(guān)系)的CombineItem和Item來處理差異,會(huì)更加合適。

而贈(zèng)品上架的情況恰恰相反,它和其他商品的上架流程差異很大。反而不適合和他們合用一套流程代碼,因?yàn)檫@樣反而會(huì)增加他人的理解成本。還不如單獨(dú)起一個(gè)流程來的清晰。

那么,問題來了,我們什么時(shí)候要用多態(tài)來處理差異,什么時(shí)候要用代碼分離來處理差異呢?

接下來,是我今天要給你著重介紹的多維度分析問題的方法論之一:矩陣分析法。

我們可以弄一個(gè)矩陣,縱列代表業(yè)務(wù)場(chǎng)景,橫列代表業(yè)務(wù)動(dòng)作,里面的內(nèi)容代表在這個(gè)業(yè)務(wù)場(chǎng)景下的業(yè)務(wù)動(dòng)作的詳細(xì)業(yè)務(wù)流程。對(duì)于我們的商品業(yè)務(wù),我們可以得到如下的矩陣:

??

??

 

通過上面的矩陣分析,我們不難看出普通品和組合品可以復(fù)用同一套流程編排代碼,而贈(zèng)品和出清品的業(yè)務(wù)相對(duì)簡單,更適合有一套獨(dú)立的編排代碼,這樣的代碼結(jié)構(gòu)會(huì)更容易理解。

維度思維

多維度的重要性

上面的案例不是我編造出來的,而是我在和張文(我同事)討論應(yīng)該用哪種方式去處理業(yè)務(wù)差異的真實(shí)故事。

我記得在和大學(xué)討論完,開車回去的路上,我一直在想這個(gè)問題,然后在第二個(gè)路口等紅燈的時(shí)候,突然有一個(gè)靈感冒出來。我抑制不住興奮,一邊開車,一邊發(fā)消息給張文說:“我想到了一個(gè)很NB的方法論,能解決在‘多態(tài)擴(kuò)展’和‘代碼分離’之間如何做選擇的問題”。

其實(shí),我知道我興奮的不僅僅是解決了這個(gè)問題。我興奮的是,我第一次真正領(lǐng)悟到了多維度思考的重要性。從而有機(jī)會(huì)從一個(gè)“單維度”生物,升級(jí)成一個(gè)“多維度”思考者。媽媽再也不用擔(dān)心我被“降維打擊”了 :)

結(jié)構(gòu)化思維有用、很有用、非常有用,只是它更多關(guān)注的是單向維度的事情。比如我要拆解業(yè)務(wù)流程,我要分解老板給我的工作安排,我要梳理測(cè)試用例,都是單向維度的。

而復(fù)雜性,通常不僅僅是一個(gè)維度上的復(fù)雜,而是在多個(gè)維度上的交叉復(fù)雜性。當(dāng)問題涉及的要素比較多,彼此關(guān)聯(lián)關(guān)系很復(fù)雜的時(shí)候,兩個(gè)維度肯定會(huì)比一個(gè)維度要來的清晰,這也是為什么說矩陣思維是比結(jié)構(gòu)化思維更高層次的思維方式。

實(shí)際上,我們從漢語的詞匯上,也不難看出一個(gè)人的思維層級(jí),是和他的思考維度正相關(guān)的。當(dāng)我們說這個(gè)人很“軸”、“一根筋”的時(shí)候,實(shí)際上是在說他只有一維的線性思維。所以,觀察事物的視角越多,維度越豐富,其思維層級(jí)也會(huì)越高。

??

??

 

無處不在的多維思考

有了這些感悟,我開始系統(tǒng)的整理關(guān)于多維度思考分析的資料,發(fā)現(xiàn)這種思考方式真是無處不在。發(fā)現(xiàn)的越多,我越是感慨,為什么如此重要的思維方式,我到現(xiàn)在才領(lǐng)悟到。

波士頓矩陣

比如,在做產(chǎn)品分析的時(shí)候,有對(duì)產(chǎn)品發(fā)展前景進(jìn)行分析的波士頓矩陣。

??

??

 

訂單要素分析

當(dāng)年,我在1688做交易下單業(yè)務(wù)的時(shí)候,有非常多的下單場(chǎng)景,每種場(chǎng)景下,買家享受的權(quán)益是不一樣的(如下表所示)。我們當(dāng)時(shí)也是使用了矩陣去表達(dá)這個(gè)復(fù)雜的關(guān)系,只是當(dāng)時(shí)還沒有想到要將其提升到方法論的高度。

??

??

 

數(shù)據(jù)交叉分析

在數(shù)據(jù)分析中,維度分析是非常重要的,特別是維度很多的時(shí)候,我們可以通過皮爾遜積矩相關(guān)系數(shù),做交叉分析,從而彌補(bǔ)獨(dú)立維度分析沒法發(fā)現(xiàn)的一些問題。

??

??

簡單相關(guān)系數(shù)矩陣

 

分析矩陣

最近我碰巧看到Alan Shalloway寫的《設(shè)計(jì)模式解析:Design Patterns Explained》,這是一本非常經(jīng)典的關(guān)于OOP的書,里面的第十六章就是專門講“分析矩陣”的,作者創(chuàng)造這個(gè)方法論的初衷也是因?yàn)闃I(yè)務(wù)涉及的要素太多,信息量太大,他需要一種組織海量數(shù)據(jù)的新方式。

??

??

 

我和Alan的路徑不一樣,但是都得出了同樣的結(jié)論。由此可見,這種矩陣分析的方式的確是對(duì)復(fù)雜業(yè)務(wù)進(jìn)行分析的一把利器,業(yè)務(wù)場(chǎng)景越多,交叉關(guān)系越是復(fù)雜,越需要這樣的分析。

組織陣型

生產(chǎn)關(guān)系決定生產(chǎn)力,對(duì)于一個(gè)管理者來說,如何有效的設(shè)置組織結(jié)構(gòu)是決定團(tuán)隊(duì)是否能高效協(xié)作的關(guān)鍵。所以我們可以看到公司里面,每年都有比較大的關(guān)于組織結(jié)構(gòu)和人員安排的調(diào)整。

對(duì)于技術(shù)團(tuán)隊(duì)來說,我們習(xí)慣于按領(lǐng)域劃分工作范圍,這樣做的好處是責(zé)任到人、職責(zé)清晰。然而,領(lǐng)域只是一個(gè)維度,我們工作通常都是以項(xiàng)目的形式的開展,而項(xiàng)目通常是貫穿多個(gè)領(lǐng)域的。所以,在做團(tuán)隊(duì)組織規(guī)劃的時(shí)候,我們可以通過業(yè)務(wù)領(lǐng)域和業(yè)務(wù)項(xiàng)目兩個(gè)維度去看。

比如,在我負(fù)責(zé)的商品團(tuán)隊(duì),我會(huì)按照如下的形式去做職責(zé)劃分。

??

??

 

時(shí)間維度

除了工作,生活中也到處可見多維思考的重要性。

比如,我們說浪費(fèi)可恥,應(yīng)該把盤子舔的很干凈,豈不知加上時(shí)間維度之后,你當(dāng)前的舔盤,后面可能要耗費(fèi)更多的資源和精力去減肥,反而會(huì)造成更大的浪費(fèi)。

我們說代碼寫的丑陋,是因?yàn)橐翱焖佟敝螛I(yè)務(wù),加上時(shí)間維度之后,這種臨時(shí)的妥協(xié),換來的是意想不到的bug,線上故障,以及無止盡的996。

RFM模型

簡單的思考是“點(diǎn)”狀的,比如舔盤、代碼堆砌就是當(dāng)下的“點(diǎn)”;好一點(diǎn)的思考是“線”狀,加上時(shí)間線之后,不難看出“點(diǎn)”是有問題的;再全面一些的思考是“面”(二維);更體系化的思考是“體”(三維);比如,RFM模型就是一個(gè)很不錯(cuò)的三維模型。可惜的是,在表達(dá)上,我們?nèi)祟愔荒茉诙S的空間里去模擬三維,否則四維可能會(huì)更加有用。

??

??

 

復(fù)雜業(yè)務(wù)治理總結(jié)

在前言部分,我已經(jīng)說過了,多維分析是對(duì)之前方法論的升級(jí)。加上以前的方法論,完整的方法論應(yīng)該是“業(yè)務(wù)理解-->領(lǐng)域建模-->流程分解-->多維分析”。

為了方便大家理解,下面我把這些方法論做一個(gè)簡單的串聯(lián)和解釋。

業(yè)務(wù)理解

理解業(yè)務(wù)是所有工作的起點(diǎn)。首先,我們要找到業(yè)務(wù)的核心要素,理解核心概念,梳理業(yè)務(wù)流程。

比如,在零售通的商品域,我們要知道什么是商品(Item),什么是單品(CSPU),什么是組合品(CombineItem)。在下單域,我們要知道訂單(order)的構(gòu)成要素是商品、優(yōu)惠、支付。在CRM領(lǐng)域,我們要理解客戶、機(jī)會(huì)、聯(lián)系人、Leads等等。

這里,我想再次強(qiáng)調(diào)下語言的重要性,語言是我們思考的載體,就像維特根斯坦說的:“凡是能夠說的事情,都能夠說清楚”。

你不應(yīng)該放過任何一個(gè)模糊的業(yè)務(wù)概念,一定要透徹的理解它,并給與合理的命名(Ubiquitous Language)。唯有如此,我們才能更加清晰的理解業(yè)務(wù),才能更好的開展后續(xù)的工作。

領(lǐng)域建模

在軟件設(shè)計(jì)中,模型是指實(shí)體,以及實(shí)體之間的聯(lián)系,這里需要我們具備良好的抽象能力。能夠透過龐雜的表象,找到事務(wù)的本質(zhì)核心。

再復(fù)雜的業(yè)務(wù)領(lǐng)域,其核心概念都不應(yīng)該太復(fù)雜,抓住了核心,我們就抓住了主線,業(yè)務(wù)往往都是圍繞著這些核心實(shí)體展開的。

比如,商品域雖然很復(fù)雜,但其核心的領(lǐng)域模型,無外乎就如下圖所示:

??

??

 

流程分解

關(guān)于流程分解,在《阿里高級(jí)技術(shù)專家方法論:如何寫復(fù)雜業(yè)務(wù)代碼?》里面已經(jīng)有非常詳細(xì)的闡述,這里就不贅述了。

簡單來說,流程分解就是對(duì)業(yè)務(wù)過程進(jìn)行詳細(xì)的分解,使用結(jié)構(gòu)化的方法論(先演繹、后歸納),最后形成一個(gè)金字塔結(jié)構(gòu)。

比如,在商品領(lǐng)域,有創(chuàng)建商品、商品上架、上架審核、商品下架、下架審核、修改商品、刪除商品等一些列動(dòng)作(流程),每個(gè)動(dòng)作的背后都有非常復(fù)雜的業(yè)務(wù)邏輯。我們需要對(duì)這些流程進(jìn)行詳細(xì)的梳理,然后按步驟進(jìn)行分解。最后形成一個(gè)如下的金字塔結(jié)構(gòu):

??

??

 

多維分析

關(guān)于多維分析,我以二維的矩陣分析為例,我想我前面應(yīng)該已經(jīng)說清楚了。

業(yè)務(wù)的復(fù)雜性主要體現(xiàn)在流程的復(fù)雜性和多維度要素相互關(guān)聯(lián)、依賴關(guān)系上,結(jié)構(gòu)化思維可以幫我們梳理流程,而矩陣思維可以幫忙我們梳理、呈現(xiàn)多維度關(guān)聯(lián)、依賴關(guān)系。二者結(jié)合,可以更加全面的展現(xiàn)復(fù)雜業(yè)務(wù)的全貌。從而讓我們的治理可以有的放矢、有章可循。

既然是方法論,在這里,我會(huì)嘗試給出一個(gè)矩陣分析的框架。試想下,如果我們的業(yè)務(wù)很簡單,只有一個(gè)業(yè)務(wù)場(chǎng)景,沒有分支流程。我們的系統(tǒng)不會(huì)太復(fù)雜。之所以復(fù)雜,是因?yàn)楦鞣N業(yè)務(wù)場(chǎng)景互相疊加、依賴、影響。

因此,我們?cè)谧鼍仃嚪治龅臅r(shí)候,縱軸可以選擇使用業(yè)務(wù)場(chǎng)景,橫軸是備選維度,可以是受場(chǎng)景影響的業(yè)務(wù)流程(如文章中的商品流程矩陣圖),也可以是受場(chǎng)景影響的業(yè)務(wù)屬性(如文章中的訂單組成要素矩陣圖),或者任何其它不同性質(zhì)的“東西”。

??

??

 

通過矩陣圖,可以清晰的展現(xiàn)不同場(chǎng)景下,業(yè)務(wù)的差異性?;诖耍覀兛梢远ㄖ茲M足差異性的最佳實(shí)現(xiàn)策略,可能是多態(tài)擴(kuò)展,可能是分離的代碼,也可能是其它。

這就是矩陣分析的要義,其本質(zhì)是一種多維度思考的方法論。

篇后寄語

最后,我想說世界是熵增的(即萬物都在緩慢的分崩離析),控制復(fù)雜度是我們這些從業(yè)者無法推卸的責(zé)任和使命。

軟件行業(yè)的發(fā)展才幾十年,還是一門年輕的學(xué)科,軟件工程就像一個(gè)剛學(xué)會(huì)走路的小孩,還很不成熟,有時(shí)還很幼稚。

但畢竟還是有幾十年的沉淀,還是有一些好的方法和實(shí)踐可以參考,我的這些總結(jié)沉淀只是在前人的基礎(chǔ)上,多走了一點(diǎn)點(diǎn)而已。但就是這一點(diǎn)點(diǎn),也實(shí)屬來自不易,其中冷暖,只有自己能體會(huì)??梢哉f,這一路走來,是一場(chǎng)對(duì)心力、腦力和體力的持續(xù)考驗(yàn)。

??

??

 

心力是指不將就的匠心,不妥協(xié)的決心,不滿足的好奇心、以及不放棄的恒心。

腦力是指那些必要的思維能力、學(xué)習(xí)能力、思考能力、思辨能力。

之所以說“業(yè)務(wù)理解-->領(lǐng)域建模-->流程分解-->多維分析”是體力,是因?yàn)閷?shí)現(xiàn)它們就像是在做填空題,只要你愿意花時(shí)間,再復(fù)雜的業(yè)務(wù)都可以按部就班的清晰起來。

梳理清晰了,再配合COLA(https://start.aliyun.com/)的指導(dǎo),我們就有可能寫出清晰、易讀的代碼,就有可能從一個(gè)if-else coder升級(jí)為一個(gè)complexity conquer。

而這不正是我們工程師孜孜不倦的追求嗎?

 

責(zé)任編輯:武曉燕 來源: 51CTO專欄
相關(guān)推薦

2022-07-04 19:02:06

系統(tǒng)業(yè)務(wù)思考

2023-06-02 07:30:24

If-else結(jié)構(gòu)流程控制

2014-09-11 15:05:40

驅(qū)動(dòng)設(shè)計(jì)驅(qū)動(dòng)開發(fā)

2022-07-11 08:16:55

策略模式if-else

2023-07-17 18:39:27

業(yè)務(wù)系統(tǒng)架構(gòu)

2023-05-30 07:56:23

代碼軟件開發(fā)

2017-04-21 07:41:37

iOS自動(dòng)化測(cè)試容器

2022-04-07 17:30:31

Flutter攜程火車票渲染

2019-08-14 08:52:40

業(yè)務(wù)代碼運(yùn)營

2013-03-06 10:28:57

ifJava

2024-12-20 19:38:01

ToB業(yè)務(wù)狀態(tài)轉(zhuǎn)換

2020-10-22 09:20:22

SQLNoSQL 數(shù)據(jù)庫

2021-04-13 06:39:13

代碼重構(gòu)code

2021-03-10 07:20:43

if-else靜態(tài)代碼

2022-04-12 07:32:40

引擎模式Spring策略模式

2023-02-24 18:47:37

供應(yīng)鏈實(shí)時(shí)數(shù)倉

2025-02-07 08:16:26

Java開發(fā)者代碼

2020-12-15 09:31:58

CTOif-else代碼

2020-05-13 14:15:25

if-else代碼前端

2021-11-04 08:53:00

if-else代碼Java
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)