再一個交付故事:征服遺留系統(tǒng)
背景
就像曉強(qiáng)在***個故事開篇所介紹的那樣,如今,我們所交付的典型軟件已經(jīng)變成了由若干個Cloud Native Application所組成的分布式的微服務(wù)應(yīng)用,但是在我們所服務(wù)的組織中,仍然存在著類似下面的這種巨大的老舊的單體應(yīng)用,我們稱之為遺留系統(tǒng)。
有些遺留系統(tǒng)仍然在組織中扮演著重要的角色,持續(xù)為客戶提供著價值,而有些則已經(jīng)成為了組織發(fā)展的瓶頸,無法適應(yīng)業(yè)務(wù)的快速變化。這個故事便是關(guān)于我們是如何幫助客戶有效的維護(hù)、提升、最終擺脫這些遺留系統(tǒng)的。
提到遺留系統(tǒng),我們并不陌生也不缺乏案例。過往的大型項(xiàng)目為我們提供了很多值得分享的經(jīng)典案例,能夠從這些經(jīng)驗(yàn)和總結(jié)中感受到在這些項(xiàng)目中所克服的挑戰(zhàn)。這些挑戰(zhàn)分別來自于:
- 如何有效的積累遺留系統(tǒng)的上下文
- 如何對遺留系統(tǒng)進(jìn)行維護(hù)和變更
- 如何能平滑的完成對遺留系統(tǒng)的技術(shù)遷移
積累上下文
萬事開頭難,當(dāng)我們開始任何一項(xiàng)交付工作時,最關(guān)鍵的問題便是如何能夠快速建立業(yè)務(wù)和技術(shù)上下文。而當(dāng)我們開始接手一個遺留系統(tǒng)的時候,這個關(guān)鍵問題變得更加復(fù)雜和困難。
遺留系統(tǒng)的上下文就和一個沒完成的拼圖一樣,碎片散落一地。有些信息只存在某些人深深的腦海里,有些信息在巨大而且過期的文檔里,難辨真?zhèn)?。代碼不會撒謊,但是動輒幾百萬行的代碼很容易讓你迷失方向.
在應(yīng)對這一難題上,我們從以往經(jīng)驗(yàn)中形成了一套行之有效的方法。
首先,通過溝通和詢問客戶團(tuán)隊(duì)的業(yè)務(wù)或技術(shù)人員去了解到盡可能多的信息,然后通過閱讀文檔或在可用環(huán)境中演示來得到更具象的認(rèn)識,最終通過閱讀代碼來解除剩下的疑問,完成巨大拼圖中的一部分。
但是在實(shí)際操作中確仍然不簡單。往往情況是這樣的,在經(jīng)過多次溝通和在文檔中查閱信息后,獲得的信息往往和代碼中的無法對應(yīng)起來,使整個過程需要不斷的反復(fù)。我在去年經(jīng)歷的一次遺留系統(tǒng)改造項(xiàng)目中就有一次類似的經(jīng)歷,團(tuán)隊(duì)被這個令人沮喪的過程打敗,做出了一些基于已有信息的假設(shè),最終給項(xiàng)目的交付造成了不大不小的風(fēng)險,團(tuán)隊(duì)付出了很大的代價才保證了項(xiàng)目的順利交付。
在獲得了上下文后,如何保持信息能得到及時的更新并有效的將信息共享給團(tuán)隊(duì)其他人是緊接著需要思考的問題。Specification by Example為我們提供了很好的方式將所有信息有效的管理起來,構(gòu)建一套和代碼一起管理的可執(zhí)行的Live Document。但是對于一個遺留系統(tǒng),這仍然是一個漫長和繁瑣的過程。在這整個信息收集和記錄的過程中,團(tuán)隊(duì)需要展現(xiàn)強(qiáng)大的耐心才能有效的達(dá)成目標(biāo)為后面的工作打下基礎(chǔ)。
開展變更
對于有些遺留系統(tǒng)我們只需要對其持續(xù)的監(jiān)控,保證其能夠正常的提供服務(wù)。但是在大多數(shù)情況下隨著客戶的業(yè)務(wù)不斷變化,也會產(chǎn)生對遺留系統(tǒng)進(jìn)行變更的需求,來迎合這些業(yè)務(wù)上的變化。那么如何在不破壞遺留系統(tǒng)的前提下修改遺留系統(tǒng)便成了應(yīng)對遺留系統(tǒng)的第二個挑戰(zhàn)。
用我們所推崇和堅(jiān)持的一系列敏捷技術(shù)實(shí)踐可以為遺留系統(tǒng)變更提供一張很好的保護(hù)網(wǎng)。
- 在進(jìn)行對遺留系統(tǒng)的修改工作之前,通過一定的單元測試覆蓋,加上之前我們已經(jīng)建立好的Live Document,能夠?yàn)槲覀兒芎玫奶峁┵|(zhì)量保證。
- 通過建立針對遺留系統(tǒng)的CI/CD Pipeline可以使我們在修改遺留系統(tǒng)時快速的得到反饋,對變更進(jìn)行及時的驗(yàn)證。
- 通過創(chuàng)建Stubs來Mock遺留系統(tǒng)的外部依賴則能幫助我們有效的縮短反饋環(huán),可以大大增強(qiáng)我們對遺留系統(tǒng)進(jìn)行變更的信心。
這些實(shí)踐看起來和我們所交付的其他項(xiàng)目沒有兩樣,但是當(dāng)你需要為某個老舊語言編寫的遺留系統(tǒng)提供單元測試覆蓋的時候,當(dāng)你的CI Pipeline需要支持一個老舊的商業(yè)中間件的自動化部署的時候,看似普通的技術(shù)實(shí)踐則會變得困難重重。
這個時候?qū)?jiān)持這些實(shí)踐作為原則變得尤為重要。這樣才能為遺留系統(tǒng)的變更提供有效的保障。
技術(shù)遷移
當(dāng)然僅憑耐心和原則是無法征服動輒幾百萬行代碼的龐然大物的。應(yīng)對遺留系統(tǒng)對技巧有著更高的要求。在這方面,我的ThoughtWorks同事們已經(jīng)從過去的項(xiàng)目經(jīng)歷中總結(jié)和分享了很多應(yīng)對遺留系統(tǒng)的技巧。特別是在對遺留系統(tǒng)進(jìn)行技術(shù)遷移的過程中。比如:
- 影響結(jié)構(gòu)圖與特征草圖的使用,幫助我們?nèi)ナ崂沓绦蛑懈鱾€模塊之間的關(guān)系和依賴。
- Branch By Abstraction的使用,使我們可以逐漸的替換將系統(tǒng)中遺留的部分更新并剔除出去。
- Strangler Pattern的使用,讓新老系統(tǒng)在一定的時間段內(nèi)共存,使遺留系統(tǒng)能夠平滑的遷移到新的技術(shù)架構(gòu)。
- Feature Toggle的使用使我們能在部署后發(fā)現(xiàn)異常時快速的切換回老系統(tǒng),使遷移風(fēng)險降到了***。
- 針對遺留系統(tǒng)的數(shù)據(jù)特點(diǎn)建立自定義的數(shù)據(jù)管道,完成遺留系統(tǒng)數(shù)據(jù)的遷移。
正是對這些技巧的靈活使用使我們真的做到了“舊的不變,新的創(chuàng)建,一步切換,舊的再見”。
寫在***
遺留系統(tǒng)是個難題,在應(yīng)對一個巨大的遺留系統(tǒng)時沒有捷徑,同時也沒有神奇的秘籍或令人目眩的黑科技。重要的是,團(tuán)隊(duì)需要意識到在面對一個遺留系統(tǒng)的時候我們需要具備:
- 更強(qiáng)大的耐心 – 去有效的收集和鞏固遺留系統(tǒng)漫長發(fā)展過程中遺失的上下文。
- 更堅(jiān)定的原則 – 去堅(jiān)持敏捷技術(shù)實(shí)踐,為遺留系統(tǒng)編織可靠的保護(hù)網(wǎng)給遺留系統(tǒng)的變更提供保障。
- 更豐富的技巧 – 去***程度降低遺留系統(tǒng)技術(shù)遷移過程中對現(xiàn)有業(yè)務(wù)的影響,逐步平滑的完成遺留系統(tǒng)的遷移。
【本文是51CTO專欄作者“ThoughtWorks”的原創(chuàng)稿件,微信公眾號:思特沃克,轉(zhuǎn)載請聯(lián)系原作者】