我去,拷貝代碼,居然還有這等好處?
什么是耦合?
耦合,是架構(gòu)中,本來(lái)不相干的代碼、模塊、服務(wù)、系統(tǒng)因?yàn)槟承┰蚵?lián)系在一起,各自獨(dú)立性差,影響則相互影響,變動(dòng)則相互變動(dòng)的一種架構(gòu)狀態(tài)。
感官上,怎么發(fā)現(xiàn)系統(tǒng)中的耦合?
作為技術(shù)人,每每在心中罵上下游,罵兄弟部門(mén),“這個(gè)東西跟我有什么關(guān)系?為什么需要我來(lái)配合做這個(gè)事情?”。明明不應(yīng)該聯(lián)動(dòng),卻要被動(dòng)配合,就可能有潛在的耦合。
因?yàn)楣矌?kù),導(dǎo)致相互受影響,就是一個(gè)耦合的典型案例。
場(chǎng)景還原
一個(gè)看似“公共”的業(yè)務(wù)庫(kù)(*.so *.jar *.dll *.php),很多業(yè)務(wù)系統(tǒng)都依賴(lài)于這個(gè)公共庫(kù),這個(gè)庫(kù)使得這些系統(tǒng)都耦合在了一起。
畫(huà)外音:這里的公共庫(kù)不是指像“字符串操作”這樣的不變化的工具庫(kù),更多是指通用業(yè)務(wù)的公共庫(kù)。
耦合如何導(dǎo)致相互影響?
業(yè)務(wù)1,業(yè)務(wù)2,業(yè)務(wù)3都依賴(lài)于某一個(gè)biz.jar,業(yè)務(wù)1因?yàn)槟硞€(gè)需求需要升級(jí)biz.jar。上線(xiàn)前,業(yè)務(wù)1的QA進(jìn)行了大量的測(cè)試,確保無(wú)誤后,代碼發(fā)布,發(fā)布完線(xiàn)上驗(yàn)證無(wú)誤后,上線(xiàn)完成,閃人。
突然,bug群里有人反饋,業(yè)務(wù)2的系統(tǒng)掛了,業(yè)務(wù)3的系統(tǒng)也掛了,一下炸開(kāi)了鍋:
- 業(yè)務(wù)2的大boss首先發(fā)飆:“技術(shù)都干啥了,怎么系統(tǒng)掛了”
- 業(yè)務(wù)2的rd一臉無(wú)辜:“業(yè)務(wù)1上線(xiàn)了,所以我們掛了”
額,然而,這個(gè)理由,好像在大boss那解釋不通…
- 業(yè)務(wù)2的大boss:“業(yè)務(wù)1上線(xiàn)?業(yè)務(wù)1上線(xiàn)前測(cè)試了么”
- 業(yè)務(wù)1的qa自信滿(mǎn)滿(mǎn):“測(cè)試了呀,上線(xiàn)前上線(xiàn)后都驗(yàn)證了,沒(méi)問(wèn)題呀”
- 業(yè)務(wù)2的大boss對(duì)業(yè)務(wù)2的rd吼道“還想甩鍋,拖出去祭天”
不知道大家工作中會(huì)不會(huì)遇到這樣的場(chǎng)景,因?yàn)楣矌?kù)的耦合,兄弟部門(mén)上線(xiàn),影響的確是你,此時(shí)你心里可能就在罵娘了,這幫不靠譜的**隊(duì)友。
特別的,如果公共庫(kù)的使用方很廣,這個(gè)耦合很?chē)?yán)重,可能影響很大的范圍。
如何解除公共庫(kù)耦合?
方案一:代碼拷貝一份。
別嘲笑這個(gè)方案,誰(shuí)敢說(shuō)自己寫(xiě)代碼的時(shí)候沒(méi)這么干過(guò)?
我們都知道這不是一個(gè)好的方案,但不可否認(rèn),拷貝之后,代碼各自演化,一個(gè)地方升級(jí)出錯(cuò),只影響一方,拷貝方只要不動(dòng)原有代碼,至少是不會(huì)受影響的。
代碼拷貝缺點(diǎn)很多,系統(tǒng)拆分時(shí),萬(wàn)不得已不要使用這個(gè)方案。
方案二:垂直拆分,將公共庫(kù)里業(yè)務(wù)個(gè)性化的代碼拆到調(diào)用方去,不要放在公共庫(kù)里。
需要把業(yè)務(wù)個(gè)性的代碼拆分到各個(gè)業(yè)務(wù)線(xiàn)自己的工程,自己的業(yè)務(wù)庫(kù)里去,例如s1.jar / s2.jar / s3.jar,修改各自的代碼,至少不會(huì)擴(kuò)大影響范圍。
大家為什么都把代碼往一個(gè)公共庫(kù)里塞?
很多時(shí)候,因?yàn)槎栊?,一點(diǎn)一點(diǎn)的惰性,日積月累,終成大坑。
這個(gè)垂直拆分是一個(gè)架構(gòu)重構(gòu)的過(guò)程,需要各業(yè)務(wù)方配合。
方案三:服務(wù)化,將公共庫(kù)里通用業(yè)務(wù)代碼拆到下層去。
完成了第一步,業(yè)務(wù)個(gè)性化的代碼提取到業(yè)務(wù)側(cè)上游。
接下來(lái)是第二步,業(yè)務(wù)通用的代碼,下沉抽取一層服務(wù),服務(wù)對(duì)上游提供RPC接口:
- 每次修改底層接口,需要測(cè)試接口的兼容性,保證不影響舊調(diào)用方;
- 如果是新的業(yè)務(wù),則建議新增接口;
最終,達(dá)到通過(guò)服務(wù)RPC調(diào)用的方式來(lái)解除耦合。
有朋友會(huì)問(wèn):
- 底層服務(wù)接口的測(cè)試;
- 上游業(yè)務(wù)層對(duì)公共庫(kù)的測(cè)試;
都是測(cè)試,為何前者能控制影響范圍呢?
- 底層接口,所有人調(diào)用,接口沒(méi)問(wèn)題則調(diào)用方都沒(méi)問(wèn)題
- 上游業(yè)務(wù)層對(duì)公共庫(kù)測(cè)試,只能保證自己的業(yè)務(wù)沒(méi)有問(wèn)題,并不能保證其他業(yè)務(wù)方?jīng)]有問(wèn)題。
個(gè)性業(yè)務(wù)代碼上浮,共性業(yè)務(wù)代碼服務(wù)化下沉,只是一個(gè)很小的優(yōu)化點(diǎn),但對(duì)于公共庫(kù)解耦卻是非常的有效。
希望大家每天收獲一點(diǎn)點(diǎn),這樣架構(gòu)就能美好一點(diǎn)點(diǎn)。
畫(huà)外音:原來(lái)拷貝代碼,還有解耦的功效?
【本文為51CTO專(zhuān)欄作者“58沈劍”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】