中文字幕日韩一区二区_国产一区二区av_国产毛片av_久久久久国产一区_色婷婷电影_国产一区二区精品

處理遺留系統(tǒng)

  處理遺留系統(tǒng),幾乎是每個(gè)程序員都不可能繞過(guò)的一件麻煩事兒。因?yàn)闀r(shí)間壓力,技能不足以及功能復(fù)雜等諸多原因,常常使得遺留系統(tǒng)的代碼變得糟糕混亂,可讀性與維護(hù)性差,無(wú)法保證功能的可測(cè)試性,糾纏不清的代碼讓類(lèi)、方法之間緊緊耦合在一起。如果遺留系統(tǒng)能夠正常工作,那么我們還可以置之不理,即使代碼接近腐爛的邊緣,我們還可以得過(guò)且過(guò)。倘若我們需要維護(hù)遺留系統(tǒng),或者需要為它添加新的功能,又或者需要將新的系統(tǒng)與遺留系統(tǒng)進(jìn)行集成,就必須正視遺留系統(tǒng)帶來(lái)的問(wèn)題了。

  處理遺留系統(tǒng),首先需要分析和了解遺留系統(tǒng),尤其這個(gè)遺留系統(tǒng)并非你開(kāi)發(fā)時(shí),更需如此。我們可以考慮雙管齊下的辦法。一是從業(yè)務(wù)邏輯方面去了解。相比新系統(tǒng)而言,遺留系統(tǒng)的唯一好處就是它往往是可以運(yùn)行可以使用的。因此,最好的辦法是直接運(yùn)行遺留系統(tǒng),通過(guò)實(shí)際操作了解系統(tǒng)的各個(gè)功能點(diǎn)、業(yè)務(wù)流程。這樣的直觀感受可以最快地幫助你了解該系統(tǒng):它能夠做什么?它能達(dá)成什么目標(biāo)?它的范圍是什么?它存在什么問(wèn)題?其二則需要從系統(tǒng)架構(gòu)出發(fā),了解遺留系統(tǒng)的邏輯結(jié)構(gòu)和物理分布??梢蚤喿x架構(gòu)文檔和源代碼,如果能夠咨詢遺留系統(tǒng)的設(shè)計(jì)者或開(kāi)發(fā)人員,就更好。盡快地描繪出遺留系統(tǒng)的輪廓圖,可以幫助你從技術(shù)的宏觀角度剖析遺留系統(tǒng)的結(jié)構(gòu)與組成。再結(jié)合你對(duì)該系統(tǒng)業(yè)務(wù)的理解,快速地掌握遺留系統(tǒng)。如果需要閱讀源代碼,最好能夠從主程序入口開(kāi)始,找到一些主要的模塊,了解其大體的設(shè)計(jì)方式與編碼習(xí)慣。由于之前對(duì)系統(tǒng)架構(gòu)已有了解,閱讀代碼時(shí),不應(yīng)在一開(kāi)始就去理解代碼實(shí)現(xiàn)的細(xì)節(jié),而應(yīng)結(jié)合架構(gòu)文檔,比對(duì)代碼實(shí)現(xiàn)是否與文檔的描述一致,并充分利用自己的技術(shù)與經(jīng)驗(yàn),找到閱讀代碼的終南捷徑。例如,如果我們知道該系統(tǒng)采用了MVC架構(gòu),就可以很容易地根據(jù)Url找到對(duì)應(yīng)的Controller對(duì)象,并在該對(duì)象中尋找業(yè)務(wù)功能實(shí)現(xiàn)的脈絡(luò)。又例如我們知道系統(tǒng)采用了SSH框架,而我們又非常熟悉SSH框架,就可以基本忽略系統(tǒng)基礎(chǔ)設(shè)施的部分,直接了解系統(tǒng)的業(yè)務(wù)實(shí)現(xiàn)。如果是Swing系統(tǒng),而且在界面中混雜了大量的業(yè)務(wù)邏輯和界面邏輯,則需要找到系統(tǒng)實(shí)現(xiàn)的特點(diǎn),譬如系統(tǒng)的業(yè)務(wù)都是通過(guò)菜單項(xiàng)進(jìn)行操作,就可以在界面中找到相關(guān)的菜單對(duì)象,然后根據(jù)這些對(duì)象的Action操作,一步一步跟蹤。甚至可以利用調(diào)試的方法,設(shè)置斷點(diǎn),來(lái)摸清楚系統(tǒng)的運(yùn)行機(jī)制與執(zhí)行順序。

  分析遺留系統(tǒng)需要有的放矢,根據(jù)目標(biāo)快速鎖定范圍。例如,如果我們是因?yàn)橄到y(tǒng)性能出現(xiàn)問(wèn)題,而要去分析遺留系統(tǒng),就無(wú)需過(guò)于關(guān)心業(yè)務(wù)邏輯,而應(yīng)從性能分析入手??紤]數(shù)據(jù)庫(kù)的訪問(wèn),IO操作,緩存機(jī)制,資源的使用等諸多方面。這就需要借助一些經(jīng)驗(yàn)和技術(shù)了,當(dāng)然也可以考慮使用一些工具,用以診斷性能瓶頸。我們?cè)?jīng)在一個(gè)項(xiàng)目中,發(fā)現(xiàn)遺留系統(tǒng)的性能問(wèn)題非常嚴(yán)重。根據(jù)分析,我們發(fā)現(xiàn)系統(tǒng)對(duì)字符串的處理存在問(wèn)題,大量使用了String類(lèi)型的對(duì)象完成字符的拼接。而在進(jìn)行數(shù)據(jù)庫(kù)查詢時(shí),很多代碼是直接性地一次將相關(guān)表的數(shù)據(jù)“拉”到內(nèi)存的集合對(duì)象中,然后利用過(guò)濾器在集合對(duì)象中進(jìn)行篩選。而在對(duì)數(shù)據(jù)進(jìn)行更改時(shí),又沒(méi)有很好地利用業(yè)務(wù)特性,完成一次提交,導(dǎo)致產(chǎn)生多次數(shù)據(jù)庫(kù)訪問(wèn)。在系統(tǒng)的某些公共模塊中,重復(fù)多次加載了Spring的配置文件。還有某些占用了較大資源的對(duì)象,對(duì)于系統(tǒng)用戶而言應(yīng)該是同一個(gè)對(duì)象,但卻沒(méi)有設(shè)計(jì)為單例。因?yàn)槲覀儽е纳七z留系統(tǒng)性能的目的,所以在分析遺留系統(tǒng)時(shí),就應(yīng)該事先確定可能導(dǎo)致性能損耗的地方,而不是全方位地去了解整個(gè)系統(tǒng)。

  在維護(hù)遺留系統(tǒng)時(shí),需要根據(jù)不同的場(chǎng)景做出不同的決策。簡(jiǎn)言之,我們需要排定優(yōu)先級(jí)。如果時(shí)間緊迫,則解決問(wèn)題是第一要?jiǎng)?wù)。盡快通過(guò)出錯(cuò)情況和記錄日志辨別出錯(cuò)原因,定位出錯(cuò)代碼,并解決之,而不是去考慮設(shè)計(jì)的優(yōu)雅,代碼的重用。我在一次解決報(bào)表顯示的問(wèn)題時(shí),采用的就是這種做法。雖然與錯(cuò)誤相關(guān)的代碼相當(dāng)丑陋,但由于時(shí)間緊迫,解決Bug才是最要緊的,所以我基本上沒(méi)有去修改或改善既有代碼的結(jié)構(gòu),僅僅解決了問(wèn)題就結(jié)束了對(duì)遺留系統(tǒng)的處理。這個(gè)問(wèn)題的處理過(guò)程在我的另一篇博客《精益求精,抑或得過(guò)且過(guò)》中詳細(xì)論述。是的,我在此時(shí)選擇了得過(guò)且過(guò)的做法,主要原因就在于優(yōu)先級(jí)列表中,問(wèn)題的解決才是最高優(yōu)先級(jí)。在這次處理過(guò)程中,我部分地利用了copy & paste的做法,并通過(guò)引入新方法的方式來(lái)解決bug,而不是直接修改出現(xiàn)問(wèn)題的方法。這是因?yàn)樵摲椒ǖ囊命c(diǎn)存在多處,由于遺留系統(tǒng)并沒(méi)有單元測(cè)試的保護(hù),我不能草率地修改,否則可能導(dǎo)致一個(gè)bug的修復(fù),結(jié)果引入更多無(wú)法預(yù)測(cè)的Bug。

  這樣的處理方式其實(shí)是我不甘心的選擇。在時(shí)間允許的情況下,我會(huì)考慮對(duì)相關(guān)代碼進(jìn)行一些小的重構(gòu),例如提取方法或提取類(lèi)等。雖然這些重構(gòu)不能改變遺留系統(tǒng)的本質(zhì),但至少可以提高代碼的可讀性,并能在一定程度下去除代碼重復(fù)。

  這一實(shí)例實(shí)際引出了單元測(cè)試的必要性。如果我們的開(kāi)發(fā)都能夠在單元測(cè)試的呵護(hù)下進(jìn)行,即使當(dāng)它隨著時(shí)間的推移,慢慢變成了丑陋的遺留代碼,因?yàn)橛袉卧獪y(cè)試的保護(hù),在對(duì)它進(jìn)行手術(shù)時(shí),成功的幾率卻會(huì)變得更大。因此,認(rèn)為編寫(xiě)單元測(cè)試是浪費(fèi)時(shí)間的觀點(diǎn),事實(shí)上是一種短視的做法。缺乏單元測(cè)試,就是一種技術(shù)債(technical debt)?,F(xiàn)在欠下的,將來(lái)總是要還的。我們不能忽略軟件的維護(hù)成本。事實(shí)上,在軟件成本中,維護(hù)成本所占的比例遠(yuǎn)遠(yuǎn)大于開(kāi)發(fā)成本。Kent Beck在《實(shí)現(xiàn)模式(Implementation Patterns)》一書(shū)中認(rèn)為:“維護(hù)的代價(jià)很大,這是因?yàn)槔斫猬F(xiàn)有代碼需要花費(fèi)時(shí)間,而且容易出錯(cuò)。知道了需要修改什么以后,做出改動(dòng)就變得輕而易舉了。掌握現(xiàn)在的代碼做了哪些事情是最需要花費(fèi)人力物力的部分,改動(dòng)之后,還要進(jìn)行測(cè)試和部署。”

  當(dāng)然,在處理遺留系統(tǒng)時(shí),仍然可以進(jìn)行單元測(cè)試。但它需要的技能更高,付出的精力更多。若要完成對(duì)遺留系統(tǒng)的單元測(cè)試,首要必須解決的就是依賴(lài)。解除依賴(lài)是面向?qū)ο笙到y(tǒng)開(kāi)發(fā)中似乎亙古不變的話題。無(wú)論你翻閱哪一本面向?qū)ο笾?,都?huì)提到這個(gè)問(wèn)題。依賴(lài)的起源其實(shí)在于對(duì)象的協(xié)作。根據(jù)單一職責(zé)原則,一個(gè)類(lèi)顯然不能承擔(dān)太多的職責(zé)。如果一個(gè)系統(tǒng)的所有功能都是一個(gè)對(duì)象完成的,那么這個(gè)對(duì)象就成了邪惡的“上帝”對(duì)象。它的粒度太大,因此難以重用,不夠靈活,細(xì)節(jié)糾纏,無(wú)法維護(hù)。這樣的設(shè)計(jì)是我們必須避免的。既然一個(gè)類(lèi)不能承擔(dān)太多職責(zé),系統(tǒng)要完成客戶要求的所有功能,就必須讓許多對(duì)象互相協(xié)作,就像人類(lèi)社會(huì)的人際交往一般,于是,就產(chǎn)生了對(duì)象之間的依賴(lài)。凡事有利必有弊,這種細(xì)粒度的對(duì)象協(xié)作,雖然保證了對(duì)象的重用性、靈活性,卻也因?yàn)閰f(xié)作帶來(lái)的依賴(lài),導(dǎo)致對(duì)象之間存在一定的耦合度,變得難以替換。由于一個(gè)對(duì)象依賴(lài)另一個(gè)對(duì)象,就使得我們?cè)趩卧獪y(cè)試時(shí),無(wú)法獨(dú)立地測(cè)試我們的目標(biāo)對(duì)象。

  依賴(lài)雖然不可避免,但如果能夠保證對(duì)象之間的良好協(xié)作,就能夠最大程度保證系統(tǒng)的松耦合。對(duì)象協(xié)作一般可以分為類(lèi)協(xié)作、接口協(xié)作與回調(diào)協(xié)作(回調(diào)協(xié)作通常可以看做是接口協(xié)作的一種特殊方式,關(guān)于這三種協(xié)作的特點(diǎn)與方式,我會(huì)在以后的文章中談到)。依賴(lài)最弱的是接口協(xié)作,這也是我們努力達(dá)到的目標(biāo),它符合“面向接口設(shè)計(jì)”的基本原則。同時(shí),也能夠保證對(duì)象的封裝性,通過(guò)將實(shí)現(xiàn)細(xì)節(jié)隱藏起來(lái),從而降低對(duì)象之間的依賴(lài)程度。

  知易行難,要對(duì)付遺留系統(tǒng)中的依賴(lài)問(wèn)題,通常需要付出百倍的努力。Michael Feathers在其大作《修改代碼的藝術(shù)(Working Effectively with Legacy Code)》中,給出了很多好的解除遺留代碼依賴(lài)的實(shí)踐。例如他提出的接縫類(lèi)型,隱藏依賴(lài),以及影響結(jié)構(gòu)圖。解除依賴(lài)需要合理地利用封裝與抽象,包括對(duì)方法參數(shù)的封裝與抽象。對(duì)于遺留系統(tǒng)而言,F(xiàn)eathers提出的影響結(jié)構(gòu)圖尤其有用。當(dāng)你需要修改某個(gè)方法時(shí),影響結(jié)構(gòu)圖可以幫助你分析該方法的依賴(lài)傳播途徑,避免因?yàn)樾薷膶?duì)其他代碼造成影響。具體做法可以參考該書(shū)。當(dāng)然,現(xiàn)在有很多IDE工具事實(shí)上還支持生成依賴(lài)圖,它可以在一定程度上幫助你尋找依賴(lài)的方向與結(jié)構(gòu)。不過(guò),手工方式的分析尤其是通過(guò)手繪影響結(jié)構(gòu)圖仍然不可缺少,它更能幫助你深入地理解遺留系統(tǒng)。為遺留系統(tǒng)繪制包圖(Package Diagram)同樣非常重要,它既能幫助你理解遺留系統(tǒng)的結(jié)構(gòu),又能為我們找到系統(tǒng)中可能存在的雙向依賴(lài)和循環(huán)依賴(lài),找到分解不合理的包,這就為我們的系統(tǒng)重構(gòu)奠定了良好的基礎(chǔ)。

  如果遺留系統(tǒng)非常復(fù)雜,以至于無(wú)法重構(gòu),同時(shí)我們又需要在遺留系統(tǒng)的基礎(chǔ)上增加新的特性和功能,好的做法就是做好新、舊功能之間的隔離。暫時(shí)可以不去考慮遺留系統(tǒng)的原有結(jié)構(gòu)和代碼(大多數(shù)情況,這些遺留系統(tǒng)其實(shí)是可以正常工作的),而只需要為新增的功能做好單元測(cè)試,并以好的設(shè)計(jì)原則與編碼規(guī)范來(lái)要求新功能的實(shí)現(xiàn)。同時(shí),我們還可以編寫(xiě)一些自動(dòng)化的回歸測(cè)試用例(例如使用Cucumber結(jié)合Watir為Web系統(tǒng)編寫(xiě)回歸測(cè)試),保證新增的功能不會(huì)影響到原有系統(tǒng)。如果新增功能的實(shí)現(xiàn)需要調(diào)用原有系統(tǒng)中的某些類(lèi)或方法,而這些類(lèi)和方法卻又難以分解,則可以考慮參照原有實(shí)現(xiàn)編寫(xiě)新的類(lèi)或方法,新的類(lèi)一定要做到合理的封裝與抽象,保證它的高內(nèi)聚與松耦合;也可以在新的類(lèi)中不去真正實(shí)現(xiàn),而是通過(guò)運(yùn)用Adapter模式來(lái)重用舊有的類(lèi)。

  只要不是更改開(kāi)發(fā)平臺(tái),通常情況下,我們不會(huì)考慮重寫(xiě)遺留系統(tǒng)。如果需要重構(gòu)遺留系統(tǒng),就必須采取“分而治之,小步前進(jìn)”的策略??梢允紫冗x擇實(shí)現(xiàn)較為容易,或者獨(dú)立性較好的模塊進(jìn)行重構(gòu)。將遺留系統(tǒng)逐步提取為一些可重用的模塊與類(lèi),就可以形成“星星之火,可以燎原”的態(tài)勢(shì)。其中,對(duì)于原有類(lèi)或模塊的調(diào)用方,由于在重構(gòu)時(shí)可能會(huì)更改接口,因此可以考慮引入Facade模式或Adapter模式,或者對(duì)接口進(jìn)行另一層的包裝,或者對(duì)接口進(jìn)行適配,使系統(tǒng)慢慢被替換,最后演化為一個(gè)結(jié)構(gòu)合理的良好系統(tǒng)。在重構(gòu)時(shí),甚至可以考慮將一些獨(dú)立性很好的功能,提取為單獨(dú)進(jìn)程下的應(yīng)用或服務(wù),通過(guò)Web Service、Socket或Restful的方式進(jìn)行調(diào)用,既保證了重用,又能夠使遺留系統(tǒng)變得更簡(jiǎn)單,成功瘦身。

  我們還需謹(jǐn)記的一點(diǎn)是,雖然模塊乃至服務(wù)的重構(gòu)對(duì)系統(tǒng)的改造更加重要,但我們卻不能忽視代碼的質(zhì)量。小到方法的提取,以及變量的命名都非常重要。也許它不會(huì)給系統(tǒng)帶來(lái)根本的改變,但它卻能夠改善代碼的可閱讀性,進(jìn)而提高系統(tǒng)的可維護(hù)性。所謂”聚沙成塔“,無(wú)論是系統(tǒng)還是模塊,其實(shí)都是這些類(lèi)和方法以及變量組成的。

  對(duì)遺留系統(tǒng)的處理不可能“一蹴而就”,必須遵循循序漸進(jìn)的做法,逐步改善。處理遺留系統(tǒng)影響深遠(yuǎn),成本也非常高,所以我們也不能因?yàn)槟X袋一發(fā)熱,就開(kāi)始?xì)鈩?shì)洶涌地“提槍上陣”,錯(cuò)將風(fēng)車(chē)當(dāng)做了魔鬼,結(jié)果撞得頭破血流。必須對(duì)整個(gè)遺留系統(tǒng)進(jìn)行審慎的分析,并結(jié)合具體情況考慮這項(xiàng)工程的復(fù)雜度、成本與預(yù)算,了解團(tuán)隊(duì)的重構(gòu)與設(shè)計(jì)能力。處理遺留系統(tǒng)的前路漫漫,我們固然需要上下而求索的決心與勇氣,卻也不能在茫然失措中迷失了前進(jìn)的方向。遺留系統(tǒng)的處理,必須慎之,慎之,再慎之!

it知識(shí)庫(kù)處理遺留系統(tǒng),轉(zhuǎn)載需保留來(lái)源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 国产精品一区二区三区在线 | 国产一区日韩在线 | 久久久久一区二区 | 玖玖免费| 国产精品成人久久久久 | 久久看看| 日韩一区二区不卡 | 亚洲一区二区在线电影 | 欧美天堂一区 | 欧美日韩综合精品 | 91影院在线观看 | 亚洲精品乱码久久久久久久久久 | 久久精品视频免费看 | 99国产精品一区二区三区 | 日日日干干干 | 91精品国产一区二区三区香蕉 | 人和拘一级毛片c | 国产欧美精品在线 | 欧美福利 | 黄色一级片视频 | 中文字幕在线国产 | 免费看黄色视屏 | 日本欧美在线视频 | 天天摸天天干 | 国产精品一区在线观看你懂的 | 国产在线一区二区 | 91偷拍精品一区二区三区 | 男人的天堂一级片 | 亚洲视频在线免费观看 | 欧美精品一区二区三区在线 | 国产免费一区二区三区免费视频 | 一a一片一级一片啪啪 | 91精品国产综合久久婷婷香蕉 | 欧美专区日韩 | 国产精品视频在线播放 | 免费看淫片 | 伊人一区 | 91精品亚洲 | 国产精品a免费一区久久电影 | 亚洲精品一区二区三区中文字幕 | 久久精品国产亚洲夜色av网站 |