:notebook: 本文已歸檔到:「blog」html
第一次讀《重構:改善既有代碼的設計》時,我曾整理過一個簡單的筆記。最近,由於參與一個重構項目,再一次溫習了《重構:改善既有代碼的設計》。過程當中,萌發了認真總結、整理重構方法的衝動,因而有了這系列文字。git
代碼的壞味道還有幾篇沒有完稿,後面我會陸續補充。。。github
「有病要早治,不要放棄治療」。多麼樸素的道理 ,人人都懂。數據庫
病,就是不健康。編程
人有病,能夠經過打針、吃藥、作手術來進行治療。設計模式
若是把代碼的壞味道(代碼質量問題)比做病症,那麼重構就是治療代碼的壞味道的藥。安全
我的認爲,在重構這件事上,也能夠應用治病的道理:架構
防病於未然。 —— 春秋戰國時期的一代名醫扁鵲,曾經有個很著名的醫學主張:防病於未然。 我以爲這個道理應用於軟件代碼的重構亦然。編程前要有合理的設計、編程時要有良好的編程風格,儘可能減小問題。從這個層面上說,瞭解代碼的壞味道,不只僅是爲了發現問題、解決問題。更重要的做用是:指導咱們在編程過程當中有意識的去規避這些問題。併發
小病不醫,易得大病。 —— 劉備說過:「勿以善小而不爲,勿以惡小而爲之」。發現問題就及時修改,代碼質量天然容易進入良性循環;反之,亦然。要重視積累的力量,別總覺得代碼出現點小問題,那都不是事兒。框架
對症下藥。 —— 程序出現了問題,要分析出問題的根本,有針對性的制定合理的重構方案。你們都知道吃錯藥的後果,一樣的,瞎改還不如不改。
忌猛藥 —— 醫病用猛藥容易產生反作用。換一句俗語:步子大了容易扯着蛋。重構若是大刀闊斧的幹,那你就要有隨時可能撲街的心理準備。推倒重來不是重構,而是重寫。重構應該是按部就班,步步爲營的過程。當你發現重寫代碼比重構代碼更簡單,每每說明你早就該重構了。
前面把代碼質量問題比做病症,而把重構比做藥。這裏,咱們再進一步討論一下重構的原則。
重構(Refactoring)
的常見定義是:不改變軟件系統外部行爲的前提下,改善它的內部結構。
我的以爲這個定義有點生澀。不妨理解爲:重構是給代碼治病的行爲。而代碼有病是指代碼的質量(可靠性、安全性、可複用性、可維護性)和性能有問題。
重構的目的是爲了提升代碼的質量和性能。
注:功能不全或者不正確,那是殘疾代碼。就像治病治不了殘疾,重構也解決不了功能問題。
翻翻書,上網搜一下,談到重構的理由大致相同:
總之就是,重構能夠提升代碼質量。
關於什麼時候重構,我先引用一下 重構並不是難在如何作,而是難在什麼時候開始作 一文的觀點。
對於一個高速發展的公司來講,中止業務開發,專門來作重構項目,歷來就不是一個可接受的選項,「邊開飛機邊換引擎」纔是這種公司想要的。
咱們不妨來衡量一下重構的成本和收益。
重構的成本
重構是有成本的,費時費力(時間、人力)不說,還有可能會使原本正常運行的程序出錯。因此,不少人都抱着「不求有功,但求無過」的心理得過且過。
還有一種成本:重構使用較新且較爲複雜的技術,學習曲線不平滑,團隊成員技術切換困難,短時間內開發效率可能不升反降。
可是,若是一直聽任代碼腐朽下去,技術債務會愈來愈沉重。當代碼最終快要跑不動時,架構師們每每仍是不得不使用激進的手段來治療代碼的頑疾。可是,這個過程一般都是很是痛苦的,並且有着很高的失敗風險。
重構的收益
重構的收益是提升代碼的質量和性能,並提升將來的開發效率。可是,應當看到,重構每每並不能在短時間內帶來實際的效益,或者很難直觀看出效益。而對於一個企業來講,沒有什麼比效益更重要。換句話說,沒有實際效益的事,一般也沒有價值。不少領導,尤爲是非技術方向的領導,並不關心你應用了什麼新技術,讓代碼變得多麼優雅等等。
重構的合適時機
從以上來看,重構實在是個吃力不討好的事情。
因而,不少人屈服於萬惡的 KPI 和要命的 deadline,一邊吐槽着之前的代碼是垃圾,一邊本身也在造垃圾。
可是,**重構本應該是個漸進式的過程,不是隻有傷筋動骨的改造才叫重構。**若是非要等到代碼已經爛到病入膏肓,再使用激進方式來重構,那必然是困難重重,風險極高。
《重構》書中提到的重構時機應該在添加功能、修復功能、審查代碼時,不建議專門抽出時間專門作重構項目。
我認爲,其思想就是指:重構應該是在開發過程當中實時的、漸進的演化過程。
重構的不恰當時機
可是,這裏我也要強調一下:不是全部軟件開發過程都必定要重構。
較能凸顯重構價值的場景是:代碼規模較大、生命週期還較長、承擔了較多責任、有一個較大(且較不穩定,人員流動頻繁)團隊在其上工做的單一代碼庫。
與之相反,有一些場景的重構價值就很小:
重構行爲在我看來,也是能夠分層級的。由高到低,越高層級難度越大:
服務、數據庫 現代軟件每每業務複雜、龐大。使用微服務、數據遷移來拆分業務,下降業務複雜度成爲了主流。可是,這些技術的測試、部署複雜,技術難度很高。
組件、模塊、框架 組件、模塊、框架的重構,主要是針對代碼的設計問題。解決的是代碼的總體結構問題。須要對框架、設計模式、分佈式、併發等等有足夠的瞭解。
類、接口、函數、字段 《重構》一書提到了**「代碼的壞味道」**以及相關的重構方法。這些都是對類、接口、函數、字段級別代碼的重構手段。因爲這一級別的重構方法較爲簡單,因此可操做性較強。具體細節能夠閱讀《代碼的壞味道》篇章。
前兩種層級的重構已經涉及到架構層面,影響較大,難度較高,若是功力不夠不要輕易變更。因爲這兩個層級涉及領域較廣,這裏不作論述。
此處爲分割線。下面是代碼的壞味道系列。。。
《重構:改善既有代碼的設計》中介紹了 22 種代碼的壞味道以及重構手法。這些壞味道能夠進一步歸類。我總以爲將事物分類有助於理解和記憶。因此本系列將壞味道按照特性分類,而後逐一講解。
代碼臃腫(Bloated)這組壞味道意味着:代碼中的類、函數、字段沒有通過合理的組織,只是簡單的堆砌起來。這一類型的問題一般在代碼的初期並不明顯,可是隨着代碼規模的增加而逐漸積累(特別是當沒有人努力去根除它們時)。
濫用面向對象(Object-Orientation Abusers)這組壞味道意味着:代碼部分或徹底地違背了面向對象編程原則。
變革的障礙(Change Preventers)這組壞味道意味着:當你須要改變一處代碼時,卻發現不得不改變其餘的地方。這使得程序開發變得複雜、代價高昂。
非必要的(Dispensables)這組壞味道意味着:這樣的代碼無關緊要,它的存在反而影響總體代碼的整潔和可讀性。
耦合(Couplers)這組壞味道意味着:不一樣類之間過分耦合。