第一章已經(jīng)看了好幾遍贷币,書里記錄了一些臨散的筆記掠廓,就是不知道從何落筆記錄,就想著從第二章開始發(fā)了苔严。書里的作者本人風(fēng)格感覺是不太愛描述這種概念性的東西定枷,我不太一樣,如果連一些基本的東西都不去理解届氢,或者說不清楚欠窒,怎么能理解透徹呢?
一退子、何謂重構(gòu)
書中描述了兩種定義岖妄,從名詞到動詞的形式。我大概默寫一些寂祥,你們?nèi)绻肷钊氲睦斫饧雠埃€是看原書。
名詞:
對軟件內(nèi)部結(jié)構(gòu)的一種調(diào)整丸凭,目的是在不改變軟件可觀察行為的前提下福扬,提高其可理解性,降低修改的成本贮乳。(改命名忧换、位置等)
動詞:
使用一系列重構(gòu)的手法,在不改變軟件可觀察行為的前提下向拆,調(diào)整其結(jié)構(gòu)亚茬。(改實(shí)現(xiàn))
- 1.1 重構(gòu)與性能 性能優(yōu)化往往會使代碼更難理解,重構(gòu)是為了更好理解與修改浓恳,出發(fā)點(diǎn)不同刹缝。
- 1.2 使用重構(gòu)時碗暗,會遇到兩個問題,1梢夯、 重構(gòu)言疗。 2、 添加新技能
兩種場景應(yīng)該說是互不干擾的颂砸,但是在重構(gòu)中噪奄,會經(jīng)常替換雁歌,一會兒會添加新功能肄鸽,一會會修改結(jié)構(gòu)為了更好的添加。
目的
- 可以改進(jìn)代碼的設(shè)計(jì): 1.消費(fèi)重復(fù)代碼内地。 2.易于理解 3.提高編碼速度色罚。4碰缔,更好定位bug并修復(fù)。
重構(gòu)的時機(jī)
我個人覺得無論何時都是可以去慢慢鉆研代碼戳护,然后進(jìn)行重構(gòu)的啦金抡。
比較多的是作者的舉例比如:
在添加功能時重構(gòu),當(dāng)我們需要添加功能或者現(xiàn)有的設(shè)計(jì)無法幫助我們添加新功能更輕松時腌且,就可以進(jìn)行重構(gòu)了梗肝。
修補(bǔ)錯誤時也可以進(jìn)行重構(gòu),這時候主要是為了代碼更容易理解吧切蟋。
復(fù)審代碼時统捶,一般這時候,是重構(gòu)的最好時機(jī)
間接層
書中引入了一個間接層的專業(yè)詞柄粹,我覺得暫時就叫這個名字吧喘鸟。
大多數(shù)重構(gòu)都會為程序引入很多的間接層,會把大型對象驻右,處理類拆成很多的小型對象什黑,大型函數(shù)拆成很多個小函數(shù)。
但是這是一把雙刃劍堪夭,一個東西拆成多份就要多維護(hù)一份愕把,不好管理。一個對象如果委托另一個對象處理森爽,委托多了恨豁,程序也變得很難閱讀跟理解。
書中也總結(jié)了一些間接層的價(jià)值:
1.允許邏輯共享爬迟,這句話其實(shí)是指可以抽象實(shí)現(xiàn)后橘蜜,子類共用。
- 分開解釋和實(shí)現(xiàn),我覺得理解為多態(tài)吧计福。
另外兩種說法跌捆,我覺得都差不多,就不列舉了象颖。
重構(gòu)基本會引入更多的間接層佩厚,但是反過來想,也可以在重構(gòu)時说订,把不必要的間接層刪除掉抄瓦。
重構(gòu)時會遇到的難題
數(shù)據(jù)庫
絕大多數(shù)商用程序都與背后的數(shù)據(jù)庫結(jié)構(gòu)緊密耦合在一起,這也是數(shù)據(jù)庫結(jié)構(gòu)如此難以修改的原因之一陶冷。另一個原因是數(shù)據(jù)遷移闺鲸,就算很小心的進(jìn)行系統(tǒng)分層,將數(shù)據(jù)庫與對象模型的依賴降至最低埃叭,但數(shù)據(jù)庫結(jié)構(gòu)的改變(例如數(shù)據(jù)拆分業(yè)務(wù)拆分)還是讓你不得不遷移所有的數(shù)據(jù)。
對于非對象數(shù)據(jù)庫悉罕,解決遷移所有數(shù)據(jù)的方法就是:在對象模型和數(shù)據(jù)庫模型之間插入一個分隔層赤屋,這就可以隔離兩個模型各自的變化,升級某一模型不用升級另一個模型壁袄,只要升級分隔層就行类早,這樣的分隔層會增加系統(tǒng)復(fù)雜度,但是可以帶來很大的靈活度嗜逻。最好在發(fā)現(xiàn)對象不穩(wěn)定時在去設(shè)計(jì)生產(chǎn)他涩僻。
關(guān)于數(shù)據(jù)庫與對象模型之間的中間層,我們在開發(fā)中可能遇到的會比較少栈顷,我文章開頭說了逆日,今天主要是記錄一些概念性的東西,大家多理解理解萄凤,如果遇到我會分享一些實(shí)現(xiàn)的室抽。
修改接口
這里說的修改接口的情況,就是靡努,當(dāng)你的接口是已經(jīng)發(fā)布或者對外提供的坪圾,或者說你的修改又不能保證能覆蓋到所有的調(diào)用者,這時候惑朦,任何修改都可能會影響使用兽泄。
這個時候,你要怎么辦呢漾月? 一般來說病梢,都盡量推薦,使用舊接口調(diào)用新接口的方式栅屏。當(dāng)你需要修改某個函數(shù)名稱時飘千,請留下舊函數(shù)堂鲜,讓她調(diào)用新函數(shù)。千萬不要復(fù)制函數(shù)的實(shí)現(xiàn)护奈,不然你會陷入重復(fù)代碼缔莲,很難自拔的。
保留舊接口的方式也是可行的霉旗,但是會構(gòu)造并微信一些額外的函數(shù)痴奏。也可以選擇另一種處理,不要發(fā)布接口厌秒。
在書中读拆,對于java還推薦了一種特殊的接口處理方式。在throw子句中增加一個異常鸵闪。你可以為這個函數(shù)改一個新名字檐晕,讓舊函數(shù)調(diào)用他,并將這個新增的受控異常轉(zhuǎn)換成一個非受控異常蚌讼,也可以拋出一個非受控異常辟灰,不過這樣你機(jī)會失去檢驗(yàn)?zāi)芰Α?/p>
處于這個原因,很多開發(fā)者都會設(shè)置一個異常抽象父類篡石,讓所有1自定義異常都繼承他芥喇,對調(diào)用者來說,就都不受影響凰萨。因?yàn)樗麄冎恍枰J(rèn)識一個基類继控。
難以通過重構(gòu)手法完成的設(shè)計(jì)改動
書中舉了一個例子,比如很難將原本就不考慮安全性需求時構(gòu)造起來的系統(tǒng)胖眷,重構(gòu)成具備良好安全性系統(tǒng)武通。
針對這種場景,作者分享了自己的一些小經(jīng)驗(yàn):先想象重構(gòu)的情況瘦材,考慮候選設(shè)計(jì)方案時厅须,想想將某個設(shè)計(jì)重構(gòu)為另一個設(shè)計(jì)的難度有多大?如果看上去看簡單食棕,就直接選最簡單的朗和,如果預(yù)先都看不到,那就多在設(shè)計(jì)上投入精力簿晓。
不該重構(gòu)的情況???
前面作者講了很多重構(gòu)的知識眶拉,當(dāng)然也會有不該重構(gòu)的時候。
比如需要重新編寫所有的代碼邏輯的時候憔儿,這時候還不如直接重新寫一個簡單忆植。
重構(gòu)與設(shè)計(jì)
重構(gòu)肩負(fù)一項(xiàng)特殊使命,跟設(shè)計(jì)互補(bǔ)。在編程具備一定經(jīng)驗(yàn)的時候朝刊,會發(fā)現(xiàn)耀里,事先做好設(shè)計(jì)可以節(jié)省返工的高昂成本,許多人把設(shè)計(jì)看成軟件開發(fā)的關(guān)鍵環(huán)節(jié)拾氓。
書中舉例了一種觀點(diǎn):重構(gòu)可以取代預(yù)先設(shè)計(jì)冯挎,就是不需要做設(shè)計(jì),然后按照最初的想法編碼咙鞍,讓代碼有效運(yùn)作房官,再重構(gòu)成型。這種方式是真的可行的续滋。
如果你選擇這種方式翰守,問題的重點(diǎn)就變了,你任然做預(yù)先設(shè)計(jì)疲酌,但是不一定要找出最正確的解決方案蜡峰,此時只需要得到一個足夠合理的方案就行了。如果是軟件設(shè)計(jì)為主朗恳,則你可能在軟件設(shè)計(jì)的時候事示,會力求設(shè)計(jì)最靈活的解決方案,要建造一個靈活的解決方案僻肖,成本難以計(jì)算,最終得到的也可能更難以維護(hù)卢鹦,可能只修改了一個地方的設(shè)計(jì)但是因?yàn)樵O(shè)計(jì)的非常靈活臀脏,導(dǎo)致維護(hù)非常麻煩,同時系統(tǒng)復(fù)雜度也會大大增加冀自。
當(dāng)然如果最后發(fā)現(xiàn)設(shè)計(jì)的這些都沒必要揉稚,就會造成最大的失敗。
總結(jié):重構(gòu)可以帶來更簡單的設(shè)計(jì)熬粗,同時不失靈活性搀玖,這也降低了設(shè)計(jì)過程的難度。