這里是Z哥的個(gè)人公眾號
每周五11:45 按時(shí)送達(dá)
當(dāng)然了,也會(huì)時(shí)不時(shí)加個(gè)餐~
我的第「163」篇原創(chuàng)敬上
應(yīng)該有不少程序員受過這樣的困擾,特別是做后端的。項(xiàng)目一直在持續(xù)不斷的迭代,但是呢老版本的代碼還不能直接刪掉,因?yàn)椴灰欢ㄋ械恼{(diào)用端都能在同一時(shí)間點(diǎn)完成升級。方法上增加參數(shù)?方法實(shí)現(xiàn)里增加if else?論難度的話,這個(gè)問題是不難,肯定每個(gè)人都有辦法解決。但是解決的是否優(yōu)雅?是否會(huì)給后續(xù)帶來更大的成本?有這考慮的人可能就不多了。我看到過一些項(xiàng)目里做兼容的方法是真的粗暴,直接懟if else。比如,原本創(chuàng)建一筆交易的時(shí)候,我們需要的數(shù)據(jù)是用戶的姓名、收貨地址、郵編。現(xiàn)在迭代的一個(gè)新版本需要增加手機(jī)號信息,并且不需要郵編了。????if(postData.mobile != null){
如果以后再新加了一個(gè)參數(shù)呢?if else再多嵌套一層……
這可能是最容易想到的改法,但針對向前兼容不僅僅只有這一種方式。容我一個(gè)個(gè)來說。http://api.xxx.com/1/user/login
如果后續(xù)的改動(dòng)完全是新業(yè)務(wù)的追加,那么可以繼續(xù)沿用這個(gè)1版本的接口。如果有做刪減,那么可以新增一個(gè)版本2的接口,調(diào)整后的業(yè)務(wù)邏輯在這個(gè)版本的接口里實(shí)現(xiàn)。http://api.xxx.com/2/user/login
這樣一來,你的項(xiàng)目中就同時(shí)存在了兩個(gè)版本的接口。新的客戶端調(diào)用2版本的,老的客戶端調(diào)用1版本的。在這個(gè)期間,讓客戶端盡快都升級到2版本,然后后續(xù)就把1版本的接口刪掉。有的人有代碼潔癖,覺得一個(gè)項(xiàng)目里同時(shí)存在兩個(gè)相同業(yè)務(wù)邏輯的接口不太舒服,那么可以試試下面這個(gè)方法。/02? 一個(gè)前端版本對應(yīng)一個(gè)后端版本/與上面的區(qū)別就是,在項(xiàng)目的代碼里,你不用新增加一個(gè)接口出來,直接把原先的接口修改成新的業(yè)務(wù)邏輯即可。但是呢,新版本上線的時(shí)候,老版本不能被全部替換掉,需要保留一段時(shí)間給舊版本的客戶端使用。這件事的邏輯與前面一樣,給客戶端一段時(shí)間來升級。其實(shí)所謂的「服務(wù)發(fā)現(xiàn)」或者說「服務(wù)治理」就是這類思想的體現(xiàn),只是玩的更加體系化。在服務(wù)發(fā)現(xiàn)的服務(wù)端,針對不同的服務(wù)本身就有版本的概念,比如:OrderService/v1 : 192.168.0.1:8000 , 192.168.0.1:8001OrderService/v2 : 192.168.0.1:8100 , 192.168.0.1:8101UserService/v1 : 192.168.0.1:9000 , 192.168.0.1:9001UserService/v2 : 192.168.0.1:9100 , 192.168.0.1:9101
客戶端調(diào)用的時(shí)候,根據(jù)其傳入的版本號,自動(dòng)路由到對應(yīng)版本的服務(wù)目標(biāo)地址。
當(dāng)然這個(gè)方案有一個(gè)問題是,由于產(chǎn)生環(huán)境同時(shí)運(yùn)行著多個(gè)版本的程序,所以數(shù)據(jù)庫的字段只能增加,不能刪除,并且增加的字段需要給上默認(rèn)值。刪除字段只能隨著后續(xù)舊版本的去除進(jìn)行。除了以上兩種方案外,我們還可以做一些其他的工作以保障向前兼容更好地進(jìn)行。/01? 數(shù)據(jù)庫設(shè)計(jì)預(yù)留擴(kuò)展字段/我們在設(shè)計(jì)數(shù)據(jù)表的時(shí)候,如果對后續(xù)業(yè)務(wù)預(yù)判會(huì)擴(kuò)展。那么可以在做數(shù)據(jù)表設(shè)計(jì)的時(shí)候預(yù)留幾個(gè)擴(kuò)展字段(ext1,ext2,ext3,……)。這樣的話配合上面提到的方案2能更好地進(jìn)行,因?yàn)楹罄m(xù)新增的字段可以暫時(shí)存在這些擴(kuò)展字段里,不需要對表結(jié)構(gòu)作出變更。如果是針對APP的向前兼容,那么務(wù)必在APP里留出一個(gè)強(qiáng)制更新的口子。以免有些用戶長期不升級,導(dǎo)致你的舊版本遲遲無法去除。針對你可以承受的多版本情況,可以給予提示性的更新提醒,由用戶自行選擇是否更新。如果針對少數(shù)隔了多個(gè)版本還未升級的用戶,可以給出強(qiáng)制性的更新,讓其無法繼續(xù)在舊版本上操作。強(qiáng)制更新也分局部更新和全量更新。現(xiàn)在針對局部更新的「熱更新」受到了一些應(yīng)用市場的限制,所以在用「熱更新」之前謹(jǐn)慎了解對應(yīng)平臺(tái)的規(guī)則。另外,向前兼容不可能是無止境,不丟掉一些包袱,不斷的新增包袱只會(huì)讓后續(xù)的維護(hù)成本不堪重負(fù)。所以需要做好對各個(gè)版本使用情況的監(jiān)控,一旦某個(gè)版本的使用量低于某個(gè)值,就應(yīng)該給予強(qiáng)制更新的提醒。其實(shí)類似的向前兼容問題,除了api之外,在對外提供的三方庫SDK、公司內(nèi)給其他項(xiàng)目調(diào)用的二方庫SDK中,也有一樣的情況。最后我建議你多看一些知名的開源項(xiàng)目,從中你可以學(xué)到很多優(yōu)雅的編程技巧和代碼設(shè)計(jì)理念。這篇呢Z哥和你分享了軟件向前兼容的一些方法。除了粗暴的if else之外,你可以嘗試一下以下兩種方法:通過接口上增加版本號
一個(gè)前端版本對應(yīng)一個(gè)后端版本
除此之外,以下這兩件事也對做好向前兼容有很大幫助。數(shù)據(jù)庫設(shè)計(jì)預(yù)留擴(kuò)展字段
APP提供強(qiáng)制更新功能
推薦閱讀:
原創(chuàng)不易,如果你覺得這篇文章還不錯(cuò),就「在看」或者「分享」一下吧。鼓勵(lì)我的創(chuàng)作 :)
如果你有關(guān)于軟件架構(gòu)、分布式系統(tǒng)、產(chǎn)品、運(yùn)營的困惑
可以試試點(diǎn)擊「閱讀原文」