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