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