發表文章

目前顯示的是有「重構」標籤的文章

重構的定義與目的

重構定義: 在不改變軟體外部行為的前提下,改變其內部結構,使其更容易理解且易於修改。 目的: 重構的主要目的就是為了提升程式碼品質、 提升程式碼的可讀性 ,以及為了日後有新需求的變化時,程式碼可以 更容易修改或是擴充 (提高可維護性)。 優點: 1. 改進程式碼的設計: 消除重覆的程式碼,每個小功能被歸責到適當的物件中,讓程式碼的職責更清楚就會更容易維護。 將雜亂無序的程式碼,重構成一連串的 精心設計 的流程,讓程式碼更容易擴充。 2. 程式碼更容易被理解: 重構簡單的講,就是整理程式碼,可以透過 Clean Code 的規範 來整理程式碼,提升可讀性。 想想程式碼過一段時間後的第二個讀者,而且這個人常常是你自己。 3. Debug 更容易: 重構的過程中,會透過單一職責原則,依照程式碼的工作責任將程式碼整理至責任相同的類別中。有責任清楚的物件,就能更快釐清問題點,除錯速度自然能夠提升。 什麼時候可以開始重構? 事實上,重構並不是一項需要額外撥出時間來進行的工作, 重構應該是在你的開發過程中持續在發生的事情 。 重構的活動,最理想的情況,就是透過持續不斷的整理,掃除那些有礙程式可讀性及可維護性的程式碼,讓程式碼持續盡可能地保持在一定健康的狀態。 既然重構是一個持續進行的活動,但又不是特意安排、特別撥出時間來做的工作,那麼,在什麼樣明確的時間點,應該觸發重構的進行呢?基本上, 重構的活動應該伴隨著我們一般開發過程中的主要活動來進行。這些主要活動包括了:增加新功能、修正錯誤、以及程式碼審查的時候,還有三次法則 。 三次法則: 同樣的事做三次,犯了 Don’t Repeat Yourself 原則,表示重複的邏輯該被重構成唯一且適當的物件或函式了。 新增功能時重構: 當我們試著增加新功能時,便有可能發現舊有的程式碼可以進行一些調整,而達成了必須重構所想要達成的目的。 但如果你在增加功能的時候,發現原設計就足以優雅地讓你將新功能擴充上去,那麼,這意謂著,還不太需要做什麼重構。 除錯時重構: 除錯的時候,你不僅會接觸到舊有的程式碼,而且,你通常得搞懂它真正的運作邏輯,當你真的懂了之後,就會知道如何用更清晰、簡潔的方式來改寫這段程式碼。 總結: 很多架構良好的程式,

讀書心得#重構JavaScript 3.1.2. 高階與低階(Hight-level and low-level)

圖片
3.1.2. 高階與低階(Hight-level and low-level) 高階與低階一詞在程式的世界中很常見,越高階的程式碼越抽象,越低階的程式碼越多實作。 第一次看到這句話的人可能已經開始神遊,不過現在讓哥帶你釐清如何辨別高階與低階。 註: 「高階」也常以 「Client」 一詞做取代 。 低階程式 首先來看低階程式碼,越低階的程式碼越接近底層。一般來說我們都懂, 越底層的程式碼越複雜 ,這是因為物件導向開發傾 封裝複雜的過程 ,以便重複利用。 這個概念其實在開發過程中也常碰到,以 jQuery 的 ajax (非同步連線)作舉例,你知道 jQuery 在封裝 ajax 之前有多複雜嗎?? 在 ajax 沒有被封裝之前,程式碼長這樣 : // If url is an object, simulate pre-1.5 signature if ( typeof url === "object" ) { options = url; url = undefined ; } // Force options to be an object options = options || {}; var // Create the final options object s = jQuery.ajaxSetup({}, options), // Callbacks context callbackContext = s.context || s, var // Create the final options object s = jQuery.ajaxSetup({}, options), // Callbacks context callbackContext = s.context || s, // Context for global events // It's the callbackContext if one was provided in the options // and if it's a DOM node or a jQuery collection globalEventContext = callbackContext

讀書心得#重構JavaScript 3.1.1 測試覆蓋率 Coverage

圖片
測試的術語 3.1.1 測試覆蓋率 Coverage 測試覆蓋率以百分比表示,用來測量有多少行程式碼已經被 測試程式 執行過。 如果你的程式碼有 4 行,但只有其中 3 行被測試程式執行過,那麼測試覆蓋率就會是 75%。剩下的 25% 可能是應該要廢棄的程式碼,或者是不屬於這個類別的工作責任,應該被移動至屬於他的地方。 以下列出多種測試覆蓋率的用途: 中文名稱 英文名稱 用途 函式覆蓋率 Function Coverage 確保每一個方法至少執行一次,且沒有發生錯誤。 行數覆蓋率 Line Coverage 確保程式每一行至少執行一次,且沒有發生錯誤。 決策覆蓋率 Decision Coverage 確保每個以真偽 (true/false) 控制程式走向的分支,至少被執行一次且沒有發生錯誤。 條件覆蓋率 Condition Coverage 確保每個分支是至少執行一次,並且沒有發生錯誤。 注意:為了滿足決策覆蓋率與條件覆蓋率有多個分支,必須針對每個分支的情境撰寫一個測試案例。 對測試覆蓋率的觀點: 覆蓋率數據只能代表你測試過哪些代碼,不能代表你是否測試好這些代碼。 不要過於相信覆蓋率數據。 測試人員不能盲目追求測試覆蓋率,而應該想辦法設計更多更好的案例,哪怕多設計出來的案例,對覆蓋率一點影響也沒有。 結論: 測試人員不應該為了滿足測試覆蓋率而撰寫測試案例,應該要以「使用情境」撰寫測試案例。 ​

讀書心得#重構JavaScript 1. 什麼是重構?

圖片
什麼是重構? 重構是一系列的等量變換 系統重構,就是在的 不改變軟體外部行為基礎上,改變軟體內部的結構 ,使其更易於閱讀、易於維護、易於擴充與易於變更。 持續不斷地對系統的內部品質進行改善與改進,就是重構的價值。 1.1 如何確保行為不被改變? Ans: 單元測試、版本控制 單元測試 進行重構之前,務必先替程式碼撰寫單元測試。確保每個方法的「 輸出結果符合預期結果 」之後,才可進行重構。 接下來 每重構一小步,就立刻執行一次單元測試 ,確認被重構的方法「行為沒有因為重構而被改變」。 只有測試通過了,這次重構才算成功! 版本控制 一般會採用 小步快跑 的方式進行重構,一次只重構一小部分,重構完馬上執行測試,測試通過後立刻上傳至 版本控制 (Git 或 SVN)。 這麼做的原因是,一但某個修改測試不通過,則還原回來。小步快跑可以讓重構的過程中,以最快速度發現修改的問題,將因重構錯誤帶來的損失減到最小! 畢竟人不可能避免犯錯:-P 1.2 為什麼我們不在意實作細節? Ans: 重構時只在乎受測程式的「輸出結果」與「預期結果」是否保持一致 。 因此,對一個物件進行測試時,只需要測試其公開方法(Public Methods),並不需要測試受保護方法(Protected Methods)與私有方法(Private Methods)。正確的設計下,測試完所有公開方法後,所有的受保護方法與私有方法都會被執行完畢。若出現沒有被執行的方法,表示該方法該被遺棄,或移動至屬於這個方法的類別。 1.3 為什麼不在意不明確且未測試的行為? Ans: 還沒確定一段程式碼的行為是否符合預期之前,不可以對其進行重構! 遇到一段行為不明確的程式碼,可以對其撰寫單元測試,利用輸入的資料與輸出結果,來理解這段程式碼的用意與行為。 當這段程式碼有單元測試保護的情況下,才可對其進行重構。 1.4 為什麼不關注效能? Ans:一般來說, 不會在剛開始重構的階段就去在意效能,只在意程式碼是否有保持正確的輸出 。 但是如果一個實作在太慢,我們就有必要先修改實作了! 如何對效能進行測試?透過 Benchmarking 套件,可以將執行函式的時間點當作「輸入」,並將運作完成的時間當作「輸出」。取時時間差回