成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

舌尖上的狀態(tài)機(jī)

wuaiqiu / 1517人閱讀

摘要:題記真的猛士,敢于不做設(shè)計(jì),直接開始編碼面對(duì)業(yè)務(wù)系統(tǒng)中最復(fù)雜的部分狀態(tài)模型,有多少程序員就有多少種實(shí)現(xiàn)。聊聊狀態(tài)模型設(shè)計(jì)上常遇到的問題和解決的思路吧。

題記

真的猛士,敢于不做設(shè)計(jì),直接開始編碼——面對(duì)業(yè)務(wù)系統(tǒng)中最復(fù)雜的部分:狀態(tài)模型,有多少程序員就有多少種實(shí)現(xiàn)。聊聊狀態(tài)模型設(shè)計(jì)上常遇到的問題和解決的思路吧。

正文

有時(shí)候我們想做一個(gè)富含業(yè)務(wù)行為,而又足夠通用的技術(shù)架構(gòu)時(shí),剛開始都是信心滿滿,采用各種設(shè)計(jì)方法,充分考慮未來的需求,畫出系統(tǒng)依賴、數(shù)據(jù)模型甚至核心類圖,上線時(shí)各種性能爆表或者擴(kuò)展輕松;上線半年之后畫風(fēng)一轉(zhuǎn),代碼堆得到處都是,哪怕再小心維護(hù)依然無法逃離“一年一重構(gòu)”的魔咒,兩年過后連測(cè)試同學(xué)的TC都寫不出來,發(fā)生了什么?

寫到這里又到晚上了,不湊巧零食都被清理干凈,餓得天昏地暗(⊙o⊙)…就設(shè)想一下這樣一個(gè)場(chǎng)景吧(下面的討論只做場(chǎng)景討論,并非真實(shí)業(yè)務(wù)系統(tǒng)的設(shè)計(jì),請(qǐng)專業(yè)的同行們不要見怪。

接到一個(gè)炒菜機(jī)器人的項(xiàng)目,要求能夠按照吃貨的設(shè)計(jì)做出各種菜式

一分鐘速成方案

大家應(yīng)該比較熟悉需求或者領(lǐng)域驅(qū)動(dòng)的套路吧,抄起自上而下設(shè)計(jì)的錘子開始敲釘子:首先,我們的平臺(tái)中會(huì)有

廚具:各種廚具的基本使用接口和參數(shù)規(guī)范

菜譜:操作指導(dǎo)

先在腦海中預(yù)演一下這樣的設(shè)計(jì)是怎么運(yùn)作的:

首先系統(tǒng)應(yīng)該能夠認(rèn)識(shí)各種不同的廚具,并且知道如何操作它們
案板:切菜程序
炒鍋:翻炒程序、油炸程序
燉鍋:水煮程序、焯水程序
攪拌機(jī):攪拌程序
……
以及它們的清洗程序沒有一一列出

接下來是菜譜,就先來個(gè)番茄炒蛋吧

打蛋流程:使用攪拌機(jī),調(diào)整參數(shù)使其能夠打出均勻的蛋液

番茄流程:使用案板,調(diào)整參數(shù)使其能夠切出合適的番茄塊

炒鍋流程:使用炒鍋,先放油,燒熱,放蛋,翻炒,放番茄,翻炒,加鹽

出鍋流程:使用盤子,出鍋

畢竟我們花了1分鐘設(shè)計(jì)出來的廚具+菜譜架構(gòu),看看再做幾個(gè)需求會(huì)變成什么樣子,需求方要求在能做番茄炒蛋的基礎(chǔ)上,做個(gè)辣椒絲炒蛋:

打蛋流程:使用攪拌機(jī),調(diào)整參數(shù)使其能夠打出均勻的蛋液

辣椒流程:使用案板,調(diào)整參數(shù)使其能夠切出合適的辣椒絲

炒鍋流程:使用炒鍋,先放油,燒熱,放蛋,翻炒,放辣椒,翻炒,加鹽

出鍋流程:使用盤子,出鍋

做到這里,一些同學(xué)指出,多數(shù)雞蛋搭配的菜譜都是擁有四個(gè)標(biāo)準(zhǔn)流程節(jié)點(diǎn):打蛋、切菜、翻炒、裝盤,而在切菜環(huán)節(jié)中,我們只需要調(diào)整參數(shù)類型和數(shù)值,就可以搭配出“*炒雞蛋”的菜色,至于翻炒環(huán)節(jié)相對(duì)麻煩一些,需要加入很多細(xì)粒度的操作才能做出適用于業(yè)務(wù)發(fā)展的擴(kuò)展性來;接下來的工作重點(diǎn),要放在翻炒流程的設(shè)計(jì)上,開放出盡可能多的SPI,讓第三方在我們這個(gè)平臺(tái)上共同實(shí)現(xiàn)翻炒市場(chǎng)。

系統(tǒng)上線半年,出現(xiàn)了各種業(yè)務(wù)分支:不僅原先官方提供的的番茄炒蛋和辣椒炒蛋獲得很好的市場(chǎng)反饋,微調(diào)參數(shù)就輕松支持了苦瓜炒蛋、木耳炒蛋甚至榴蓮炒蛋;業(yè)務(wù)方出現(xiàn)了:我們要開辟湯類市場(chǎng),先從番茄蛋湯開始吧:

打蛋流程:使用攪拌機(jī),調(diào)整參數(shù)使其能夠打出均勻的蛋液

切菜流程:使用案板,調(diào)整參數(shù)切出番茄丁和香蔥段

湯鍋流程:使用湯鍋,加水,燒熱,放蛋,加熱,放番茄,放蔥段,加鹽

出鍋流程:使用湯碗,出鍋

針對(duì)原來設(shè)計(jì)的四套流程,在切菜流程中加入了類似炒鍋流程的多操作支持,接下來又實(shí)現(xiàn)了一套全新的湯鍋流程,出鍋也做了些定制。

腦補(bǔ)一下接下來的紅燒肘子、魚香肉絲、清燉羊肉、回鍋肉該怎么實(shí)現(xiàn)吧(唉,快餓死了,話說好多程序員做飯都是好手,是真的吧?)




回過頭看看之前的實(shí)現(xiàn),核心流程節(jié)點(diǎn)不一定只有4個(gè),每個(gè)流程節(jié)點(diǎn)下面的子節(jié)點(diǎn)可能有多個(gè),如果現(xiàn)在要針對(duì)業(yè)務(wù)方提出的這些葷菜做個(gè)重構(gòu),該怎么做?

將菜譜系統(tǒng)做成一個(gè)多維數(shù)組,就像這個(gè)樣子:
菜譜ID[子流程ID],然后分別實(shí)現(xiàn)這些流程節(jié)點(diǎn)并將它們存儲(chǔ)在這個(gè)菜譜表格中

看起來應(yīng)該比較完善了吧,可程序員的第六感還是隱隱約約覺得有哪里不對(duì)勁,譬如,在番茄炒蛋和辣椒絲炒蛋這兩個(gè)大體相同的流程中,“翻炒”、“加鹽”這兩個(gè)節(jié)點(diǎn)真的是可復(fù)用的嗎?

沒錯(cuò),現(xiàn)實(shí)架構(gòu)中往往沒這么簡(jiǎn)單,因?yàn)?/p>

番茄炒蛋的湯多,鹽可以在最后加,也可以在打蛋的時(shí)候加,而辣椒炒蛋沒什么湯,鹽要在打蛋的時(shí)候加進(jìn)去

好吧,在不影響流程系統(tǒng)的情況下,我們硬著頭皮在打蛋和炒鍋流程節(jié)點(diǎn)上加了個(gè)IF判斷(is 番茄炒蛋),然后就……中招了。

從邏輯來講,這一個(gè)小小的IF,將我們?cè)仍O(shè)計(jì)的三維數(shù)組變了個(gè)味,把流程圖畫出來可能是這樣的:

IF...ELSE分支就像小說里邊的二向箔,看起來像是沒有改變?cè)邢到y(tǒng)的邏輯,但可是可但是它可是混雜在源碼中而不是存在于配置中的邏輯,慢慢的,這種隨意的維護(hù)和簡(jiǎn)單實(shí)現(xiàn),開始模糊系統(tǒng)中的主子流程的邊界,接著模糊菜譜和主流程的邊界,將一個(gè)有層次的設(shè)計(jì)一步一步的煮成一鍋皮蛋瘦肉東北亂燉粥。寫代碼的時(shí)候很爽,做維護(hù)的時(shí)候罵娘

這是一個(gè)小小的開始,我們可以抱著取舍的心態(tài)說:我們可以通過編碼規(guī)范的方式要求開發(fā)人員在涉及主流程節(jié)點(diǎn)的邏輯上不允許使用IF分支來保護(hù)架構(gòu),只有細(xì)枝末節(jié)的流程可以使用不規(guī)范的編碼方式。

可現(xiàn)實(shí)往往沒有那么簡(jiǎn)單,流程節(jié)點(diǎn)之間也不是完全沒有上下文依賴的情況,絕大多數(shù)采用狀態(tài)機(jī)架構(gòu)的系統(tǒng)是不會(huì)用多維數(shù)組劃分狀態(tài)的(不信你可以去review代碼),通過邏輯分支搭建的橋梁,整個(gè)系統(tǒng)變成一個(gè)巨大的狀態(tài)機(jī),那么一個(gè)高維的狀態(tài)機(jī)系統(tǒng)投影到單維的系統(tǒng)中會(huì)發(fā)生什么?(很多視頻網(wǎng)站上有個(gè)很好的教學(xué)系列《Dimensions》,有一部分內(nèi)容關(guān)于如何通過球極投影理解四維空間)狀態(tài)機(jī)爆炸了,囧

這種實(shí)現(xiàn)的問題還不止于此,由于細(xì)粒度的流程是建立在廚具的維度上,而每種廚具對(duì)付不同的食材時(shí),還是需要做很多定制化的工作,譬如:

打蛋器/打蛋碗是否能夠加鹽

鍋里倒油/倒水/倒醬油

菜板切圈/切片/切絲

就拿菜板舉例,胡蘿卜切片的手法,和包心菜切片的手法必然是不同的;習(xí)慣上對(duì)待這種問題的解決手段通常有兩種,一種是把切片的代碼放在菜板上實(shí)現(xiàn),另一種是將復(fù)雜性下沉到各種食材上分別實(shí)現(xiàn)

如果在菜板上實(shí)現(xiàn),我們就將獲得一個(gè)能夠加工天下食材的“超級(jí)菜板”,要么是個(gè)上帝類,要么是個(gè)錯(cuò)綜復(fù)雜的巨型Service;

如果在食材上實(shí)現(xiàn),為了能讓菜板接受各種不同類型食材作為輸入?yún)?shù),我們很可能會(huì)在各種食材的上層抽象一個(gè)BaseEdible的基類好傳遞參數(shù),然后要么在菜板上做switch邏輯,要么在BaseEdible中提供各種加工方法的實(shí)現(xiàn),譬如切片/切絲,但粉條或者大米怎么切片?它和胡蘿卜除了都能吃以外還有什么共性?

也許有細(xì)心的同學(xué)開始考慮在食材上用Command方式來實(shí)現(xiàn)行為,這可能也是一種很糾結(jié)的做法,Debug成本暫且不說,一個(gè)幾乎可以發(fā)送所有命令的菜板加上一堆看起來什么命令都能接受的食材實(shí)現(xiàn),怎么保證系統(tǒng)不會(huì)讓菜板去把面粉切個(gè)絲,也要做不少工作。

一個(gè)看上去很美好的設(shè)計(jì),在實(shí)施的過程中很可能成為下面三者兼?zhèn)涞脑愀鈱?shí)現(xiàn)

狀態(tài)機(jī)爆炸

上帝類

過度繼承/無用代碼

這時(shí)候,比程序員先瘋掉的,大概是聽到程序員說“我做了個(gè)小改動(dòng),你們回歸一下”這句話的測(cè)試同學(xué)吧?

換個(gè)姿勢(shì)

怎樣才能讓這個(gè)系統(tǒng)像親愛的母上大人一樣,什么菜都會(huì)做呢?

回顧前面的設(shè)計(jì),鍋碗瓢盆作為容器,它們本身其實(shí)沒有發(fā)生過任何變化,只是在盛有不同的食材時(shí),樣子看起來有些不同。按照加工的流程設(shè)計(jì)狀態(tài)機(jī)踩了坑,按照容器狀態(tài)設(shè)計(jì)狀態(tài)機(jī)子節(jié)點(diǎn)也踩了坑,那么我們是不是一開始的出發(fā)點(diǎn)就跑偏了?

我們不妨換個(gè)角度來思考,《舌尖上的中國(guó)》教育我們:食材很重要,那么是不是可以從食材入手來設(shè)計(jì)這個(gè)系統(tǒng)?

剛才的設(shè)計(jì)都是以廚師的工作狀態(tài)為出發(fā)點(diǎn)做的:我們手上有各種工具,可以通過各種手段來加工食材。但考慮“做菜”這件事情本身,輸入的是食材,輸出的也是食材,真正發(fā)生狀態(tài)轉(zhuǎn)換的元素是工具嗎?顯然不是,雞蛋到蛋液到炒蛋這個(gè)過程中,鍋碗瓢盆沒有任何變化,從食材的角度入手,也是一個(gè)好玩的嘗試。

雞蛋蛋有很多加工方法,煮蛋,煎蛋,荷包蛋,蛋液
辣椒也有很多加工方法,辣椒絲,辣椒圈,辣椒片

根據(jù)每一種食材進(jìn)行抽象,會(huì)有一個(gè)很好的附帶效果:每個(gè)狀態(tài)之間的變遷不可逆而且轉(zhuǎn)移條件沒有多態(tài)行為

碗 -> 洗干凈 -> 干凈的碗

雞蛋 -> 敲開,放入干凈的碗并用筷子攪動(dòng) -> 蛋液

雞蛋 -> 敲開,放入干凈的碗并用筷子攪動(dòng),加鹽,繼續(xù)攪動(dòng) -> 咸蛋液

鍋 -> 洗干凈 -> 干凈的鍋

干凈的鍋 -> 放油,加熱 -> 熱油鍋

蛋液 -> 放入熱油鍋,翻炒 -> 炒雞蛋

番茄 -> 切碎 -> 碎番茄

辣椒 -> 切絲 -> 辣椒絲

辣椒 -> 切圈 -> 辣椒圈

荷包蛋很難變回生雞蛋的樣子,對(duì)吧?話說還真有人能做到,不過即使能變回來也不影響整體的設(shè)計(jì)

這樣就有了材料的狀態(tài)機(jī)和轉(zhuǎn)移函數(shù),之前的架構(gòu)中,加工工具變成了Services或者Utils,鍋具仍然維持細(xì)粒度狀態(tài)機(jī),但不再是接受各種食材的上帝組件,我們可以在這樣細(xì)粒度的狀態(tài)機(jī)模型上進(jìn)行很細(xì)致的加工

在不同菜色的加工過程中,這些細(xì)粒度的狀態(tài)機(jī)節(jié)點(diǎn)和轉(zhuǎn)移函數(shù)其實(shí)都是可以完整復(fù)用的,列一個(gè)番茄炒蛋的上游流程圖,是不是變得清晰一些?

剩下的部分就不劇透了,設(shè)計(jì)的樂趣不就在這里嗎?真的餓到全身無力扯不動(dòng)蛋啦!有機(jī)會(huì)大家直接討論下,因?yàn)轭愃频膯栴}在交易、物流、工單系統(tǒng)中都有大量的實(shí)例,偶爾換個(gè)思路,收獲沒準(zhǔn)不小滴。

炒蛋·交易核心實(shí)戰(zhàn)

在進(jìn)入這個(gè)章節(jié)之前,我們?cè)倩仡櫼幌?,大家是否已?jīng)通過腦補(bǔ),消滅了炒蛋系統(tǒng)中的那些問題設(shè)計(jì)?

上帝類

過度繼承

非原子的狀態(tài)機(jī)轉(zhuǎn)移函數(shù)

狀態(tài)機(jī)爆炸

如果大體上沒什么問題的話,咱們繼續(xù)向交易核心系統(tǒng)的設(shè)計(jì)上折騰起來!

發(fā)現(xiàn)了嗎,炒蛋和交易核心系統(tǒng)的架構(gòu)也有許多相似之處,復(fù)雜業(yè)務(wù)系統(tǒng)編碼中,最困難的工作是:知道在什么情況下做什么事;我們從炒蛋的思路入手,以兩個(gè)交易場(chǎng)景看看能不能跑通

按照前文的套路,交易系統(tǒng)的設(shè)計(jì)同樣也可以例舉出兩種典型的設(shè)計(jì)路徑:
1、按照資金流、信息流、物流等人們直接感知到的交易元素,自上而下的設(shè)計(jì)
2、按照商品、資金、優(yōu)惠券、紅包等交易物料,自下而上的設(shè)計(jì)

很多同學(xué)對(duì)于前者的思路應(yīng)該比較熟悉了,我們?cè)谶@里重點(diǎn)看一看怎樣以后者的路徑進(jìn)行交易核心的設(shè)計(jì),是否能夠找到一種可以適用于更多業(yè)務(wù)場(chǎng)景、健壯的交易架構(gòu)

首先需要明確,交易的本質(zhì)是什么:多個(gè)參與者按照約定,進(jìn)行財(cái)物的轉(zhuǎn)移或在參與者之間發(fā)生服務(wù)行為

接下來就是如何在系統(tǒng)中體現(xiàn)這些轉(zhuǎn)移或者服務(wù)行為了,會(huì)計(jì)記賬法,在資產(chǎn)核算、資金審計(jì)等領(lǐng)域都有廣泛的應(yīng)用,在我們的交易系統(tǒng)設(shè)計(jì)中,參照會(huì)計(jì)手段,對(duì)每個(gè)交易元素的狀態(tài)進(jìn)行建模(主要體現(xiàn)在數(shù)據(jù)庫(kù)Schema上,本文篇幅所限就不展開介紹會(huì)計(jì)記賬在訂單存儲(chǔ)上的應(yīng)用了,以后有機(jī)會(huì)再敘)

多帶帶抽出狀態(tài)機(jī)來看,用會(huì)計(jì)術(shù)語描述,可以把財(cái)物轉(zhuǎn)移或服務(wù)行為抽象成一個(gè)簡(jiǎn)單的流程

[A]簽訂

[D]借方已履行

[C]貸方已確認(rèn)

對(duì)于任何一種交易元素,無論是否采用了擔(dān)保交易或第三方介入服務(wù)的情況(如對(duì)于商品而言,從賣家發(fā)貨,經(jīng)過快遞,到達(dá)買家的過程中:發(fā)貨及物流進(jìn)行中的狀態(tài)為D,買家確認(rèn)收貨為C)當(dāng)然,完全可以引入更多復(fù)雜的細(xì)粒度狀態(tài)機(jī)。為了敘事簡(jiǎn)便,在后面的表格中,我們都用A、D、C三種狀態(tài)來描述交易元素的轉(zhuǎn)移狀態(tài)。

在一個(gè)典型的一口價(jià)交易流程中,交易流程如下(默認(rèn)全部都是擔(dān)保交易)

下單

買家已付款

賣家已發(fā)貨

買家確認(rèn)收貨

交易成功

在最樸素的一口價(jià)交易流程中,就是買家賣家一手交錢一手交貨的過程,交易元素只有兩個(gè)

資金

商品

那么,在交易過程中,這兩種交易元素的狀態(tài)是如何變更的?

類型 下單 付款 發(fā)貨 收貨 成功
資金 A D D D C
商品 A A D C C

表格中,不難看出交易的各個(gè)環(huán)節(jié)中需要進(jìn)行的操作

下單(錢A->D,引導(dǎo)買家付款)

買家已付款(貨A->D,引導(dǎo)賣家發(fā)貨)

賣家已發(fā)貨(貨D->C,引導(dǎo)買家確認(rèn)收貨)

買家確認(rèn)收貨(錢D->C,系統(tǒng)打款給賣家)

交易成功

就這樣,從最細(xì)粒度的狀態(tài)機(jī)入手,我們獲得了一個(gè)能夠直接明確表示每個(gè)State和Transition的設(shè)計(jì)原型

下面我們?cè)僬乙粋€(gè)更復(fù)雜一點(diǎn)的場(chǎng)景入手

某烘焙供應(yīng)商接入在線交易,由其分銷商以代理的方式引導(dǎo)用戶選購(gòu),用戶在分銷商頁面在線選購(gòu)商品后,付定金,均分給分銷商及供應(yīng)商,等店鋪備貨完成之后,通知買家付尾款給供應(yīng)商,然后供應(yīng)商發(fā)貨,買家收貨,完成交易

首先列出交易流程列表

下單

買家付定金,供應(yīng)商與分銷商均分

供應(yīng)商完成備貨

買家付尾款給供應(yīng)商

供應(yīng)商發(fā)貨

買家確認(rèn)收貨

交易成功

再列出交易元素

分銷商傭金

供應(yīng)商定金

供應(yīng)商尾款

供應(yīng)商備貨

供應(yīng)商商品

列出交易流程狀態(tài)表格

類型 下單 定金 備貨 尾款 發(fā)貨 收貨 成功
傭金 A D D D D D C
定金 A D D D D D C
備貨 A A C C C C C
尾款 A A A D D D C
商品 A A A A A D C

當(dāng)然也可以簡(jiǎn)化一下

類型 下單 定金 備貨 尾款 發(fā)貨 收貨 成功
傭金 A D - - - - C
定金 A D - - - - C
備貨 A - DC - - - -
尾款 A - - D - - C
商品 A - - - - D C

如果需要支持使用優(yōu)惠券的交易呢?再加一行就行

類型 下單 定金 備貨 尾款 發(fā)貨 收貨 成功
券(付款減) A D - - - - C
券(下單減) D - - - - - C

用這樣的細(xì)粒度表格,很輕松就可以獲得每個(gè)State(下單、付定金),以及State之間的Transitions,表格中,不同的列表示交易環(huán)節(jié),而不同的行,則表示不同的交易元素

至于逆向流程的支持,其實(shí)也很簡(jiǎn)單,因?yàn)楸砀裰幸呀?jīng)清晰的描述了每種交易元素的狀態(tài),將交易元素的發(fā)起人和接收人互換,進(jìn)一步區(qū)分交易元素

需要區(qū)分的交易元素主要有

平臺(tái)中轉(zhuǎn)或擔(dān)保類元素(如現(xiàn)金、紅包、優(yōu)惠券)

不可退換元素(優(yōu)惠券、充值卡)

實(shí)物(通常所說)

服務(wù)

按照交易元素的逆向特征來設(shè)計(jì)對(duì)應(yīng)的逆向元素生成策略,就可以不用考慮太多細(xì)節(jié),簡(jiǎn)便的支持逆向流程

至此,我們獲得了一個(gè)通過細(xì)粒度狀態(tài)機(jī)表示的交易核心模塊,大家也可以再用其他的交易場(chǎng)景試著套用一下,看看有沒有比較好或者不適合的場(chǎng)景

在線上應(yīng)用的設(shè)計(jì)上,還要進(jìn)一步考慮一些其他的工程因素

如何進(jìn)行狀態(tài)機(jī)編碼

如何借助TCC實(shí)現(xiàn)最終事務(wù)一致性

合約化的交易數(shù)據(jù)庫(kù)Schema設(shè)計(jì)

這些內(nèi)容我們?cè)谝院蟮钠新接懓?:)

小結(jié)

在很多復(fù)雜業(yè)務(wù)系統(tǒng)的設(shè)計(jì)中,往往因?yàn)榻=嵌鹊倪x取造成后續(xù)維護(hù)中的困難

在狀態(tài)機(jī)/流程引擎的設(shè)計(jì)上,建議考慮

節(jié)點(diǎn)之間的轉(zhuǎn)移函數(shù)是否多態(tài)?

節(jié)點(diǎn)本身是否多態(tài)?

節(jié)點(diǎn)是否清晰的映射了需求場(chǎng)景中那些真正發(fā)生改變的對(duì)象?

新增流程是否需要修改原有代碼?

在類層次設(shè)計(jì)上,建議考慮

是否存在無用代碼?

是否存在上帝類?

如果存在這些情況,就像蛋糕上的霉斑,看起來只有一星半點(diǎn),但你敢吃長(zhǎng)霉的食物嗎?

附錄 開閉原則

還記得“開閉原則”嗎,就一句話:系統(tǒng)(或者理解為系統(tǒng)中的類、模塊、函數(shù))對(duì)于“擴(kuò)展”應(yīng)該開放,而對(duì)于“修改”應(yīng)該是封閉的。

這里首先需要界定“擴(kuò)展”的含義:在不改動(dòng)原有系統(tǒng)代碼的情況下,新增一個(gè)類算不算?新增一個(gè)方法呢?如果將它們套用“修改”的語義,對(duì)于模塊而言新增一個(gè)類是修改,對(duì)于類而言新增方法也是修改。開閉原則的邊界似乎沒有那么清晰。

我們可以用一個(gè)更簡(jiǎn)單的思路來界定開閉原則:是否違背了原有的設(shè)計(jì)初衷

繼承的問題

《重構(gòu)》書中花了很大的篇幅向讀者介紹“代碼的壞味道”,有一個(gè)“Unnecessary Code”的說法,大致的意思是繼承體系的基類中存在下游子類不需要的行為,或者必須被糾正的情況,工作個(gè)三五年的朋友們都或多或少的遇到過某個(gè)類的所有子類都在復(fù)寫基類方法的情況吧。

在不少實(shí)用主義的架構(gòu)文章中,都提過“使用組合來代替繼承”的觀點(diǎn),其中流傳最廣的一個(gè)段子(抱歉我也不知道是不是真事)是:James Gosling 的某次演講會(huì)后Q&A環(huán)節(jié)中,有人問他,如果重新設(shè)計(jì)Java語言,你會(huì)做什么?JG回答說,我會(huì)干掉“類”,倒不是因?yàn)椤邦悺北旧碛袉栴},而是會(huì)用實(shí)現(xiàn)(implements)來取代繼承(extends)

就平時(shí)項(xiàng)目的經(jīng)歷而言,基類,尤其是業(yè)務(wù)系統(tǒng)中的各種基類,是非常難設(shè)計(jì)的。因?yàn)楹茈y在業(yè)務(wù)剛開始的時(shí)候就預(yù)想到它最終(結(jié)束維護(hù)下線時(shí))的樣子,也常常因?yàn)檫@樣,我們看到的大多數(shù)Base*命名的類時(shí),除了限定參數(shù)類型,它的代碼行為和Object基本無異(譬如BaseCommand,BaseItem,BaseAction我去太多了),讓后續(xù)維護(hù)的同事邊罵邊寫代碼。

上帝類

又是來自《重構(gòu)》的點(diǎn)子:“One Class to rule them all, and in the darkness bind them.”,聽起來有點(diǎn)像《魔戒》的臺(tái)詞哈,這個(gè)理解起來就不像為什么避免繼承那么糾結(jié)了,畢竟誰都不愿意維護(hù)一段三五千行而且看起來什么事情都能做的代碼吧?哦,有人用一個(gè)匯編文件寫了個(gè)操作系統(tǒng),咱們的平臺(tái)看起來最多需要兩三個(gè)類就夠了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/64817.html

相關(guān)文章

  • 2017-06-19 前端日?qǐng)?bào)

    摘要:前端日?qǐng)?bào)精選京東如何配合業(yè)務(wù)打造三端融合開發(fā)平臺(tái)第期聊聊組件開發(fā)的邊界把握和狀態(tài)驅(qū)動(dòng)插件拾趣網(wǎng)站開發(fā)微信小程序?qū)崙?zhàn)二全家桶開發(fā)的一個(gè)跨三端的應(yīng)用掘金原生實(shí)現(xiàn)五子棋游戲前端學(xué)習(xí)中文譯年你應(yīng)該了解的函數(shù)式編程個(gè)人文章的設(shè) 2017-06-19 前端日?qǐng)?bào) 精選 京東618:如何配合業(yè)務(wù)打造JDReact三端融合開發(fā)平臺(tái)?【第970期】聊聊vue組件開發(fā)的邊界把握和狀態(tài)驅(qū)動(dòng)webpack 插件...

    alighters 評(píng)論0 收藏0
  • 世界各國(guó)對(duì)于云計(jì)算大力投入,這是為什么?

    摘要:隨著世界各國(guó)對(duì)云計(jì)算的大力投入,以及行業(yè)內(nèi)技術(shù)的快速發(fā)展,現(xiàn)階段整個(gè)產(chǎn)業(yè)公司均在進(jìn)行云計(jì)算的產(chǎn)業(yè)整合。對(duì)于云計(jì)算的發(fā)展前景,各大互聯(lián)網(wǎng)巨頭都相當(dāng)看好,紛紛為此調(diào)整公司的發(fā)展戰(zhàn)略,競(jìng)相推出自己的云計(jì)算產(chǎn)品和服務(wù)。隨著世界各國(guó)對(duì)云計(jì)算的大力投入,以及IT行業(yè)內(nèi)技術(shù)的快速發(fā)展,現(xiàn)階段整個(gè)IT產(chǎn)業(yè)公司均在進(jìn)行云計(jì)算的產(chǎn)業(yè)整合。對(duì)于云計(jì)算的發(fā)展前景,各大互聯(lián)網(wǎng)巨頭都相當(dāng)看好,紛紛為此調(diào)整公司的發(fā)展戰(zhàn)略...

    raledong 評(píng)論0 收藏0
  • 重新科學(xué)學(xué)音標(biāo)-區(qū)別式學(xué)舌位(靠感覺和想象)

    摘要:和區(qū)別,前者發(fā)音時(shí),舌頭位置不但不下拉,還要向上顎貼近,那么發(fā)出來音正確后者舌尖向下拉,發(fā)音正確,否則不對(duì)。 i:和I區(qū)別,前者發(fā)音時(shí),舌頭位置不但不下拉,還要向上顎貼近,那么發(fā)出來音正確;后者舌尖向下拉,發(fā)音正確,否則不對(duì)。

    zengdongbao 評(píng)論0 收藏0
  • 狀態(tài)決定視圖——基于狀態(tài)的前端開發(fā)思考

    摘要:前端與狀態(tài)現(xiàn)在的前端開發(fā)中,對(duì)于狀態(tài)的管理是重中之重。有限狀態(tài)機(jī)那么如何更好的管理前端軟件的復(fù)雜度的狀態(tài)機(jī)思想給出了自己的答案。有限狀態(tài)機(jī)并不是一個(gè)復(fù)雜的概念簡(jiǎn)單說,它有三個(gè)特征狀態(tài)總數(shù)是有限的。 前提 在現(xiàn)在的前端社區(qū),關(guān)于MVVM、Model driven view 之類的概念,已經(jīng)算是非常普及了。React/Vue 這類框架可以算是代表。而自己雖然有 React/Vue 的使用經(jīng)...

    miya 評(píng)論0 收藏0
  • 從根本出發(fā),探索區(qū)塊鏈共識(shí)的四個(gè)階段

    摘要:狀態(tài)機(jī)模型區(qū)塊鏈用許多的節(jié)點(diǎn)共同模擬了一臺(tái)多復(fù)本的狀態(tài)機(jī)。區(qū)塊鏈共識(shí)的四個(gè)階段第一階段是加入共識(shí)加入共識(shí)階段決定了什么樣的節(jié)點(diǎn)可以參與共識(shí)協(xié)議。第四階段是退出共識(shí)這是常常被忽略的部分。 在接下來的秘猿科技小課堂里,我們會(huì)從技術(shù)角度、經(jīng)濟(jì)模型設(shè)計(jì)角度、以及共識(shí)角度來拆解 Nervos 加密經(jīng)濟(jì)網(wǎng)絡(luò)中,底層公鏈 CKB 的設(shè)計(jì)理念。而本文將會(huì)作為技術(shù)角度核心設(shè)計(jì) Cell 模型的預(yù)備文章,...

    pekonchan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<