---
# System prepended metadata

title: 重構要素

---

# 重構要素

1. [重構的原則](https://bryanyu.github.io/2018/01/07/RefactorPactice/)
- [ ] 需要有穩定且堅固的測試機制
- [ ] 以微小步伐修改程式，如果引入錯誤便可以很容易發現
- [ ] 如果覺得比較困難增加新的功能，就先重構後再增加
- [ ] 只有寫出人類容易理解的程式碼，才是優秀的程式員

2. 何時重構?
- [ ] 三次法則：事不過三，三則重構
- [ ] 增加功能的時候重構
- [ ] 修改錯誤的時候重構
- [ ] Code Review的時候重構
- [ ] 實踐 TDD 時


3. [重構的定義](http://teddy-chen-tw.blogspot.com/2014/04/refactoring.html)
* 在不改變軟體的外在行為之下，改善既有軟體的內部設計，refactoring是「改善既有軟體的內部設計」，因此開發人員所面對的問題，不是從頭產生一個新的設計，而是在「既有設計」中想辦法去改善它。
 ![](https://i.imgur.com/gZQMW9C.jpg)
* [重構可由下列四個面向來執行](https://5xruby.tw/posts/code-refactoring-in-ruby/)
> 整理共享的邏輯 (To enable sharing of logic)
---
> 將目的與實作細節分開來解釋，特別是在命名方法名稱的時候 (To explain intention and implementation separately)
---
> 隔離容易變動的程式碼，最簡單且基礎的方式就是把易變動的部份關在私有方法中，限制被存取的範圍 (To isolate change)
---
> 將複雜的條件 (conditionals) 轉化為簡明的訊息(messages)傳遞 (To encode conditional logic)
* 什麼時候不該重構？
- [ ] 當遺留的技術債太大時，不適合下重本進行重構
- [ ] 現在的程式碼無法運作 => TDD 也是綠燈時才重構
- [ ] 專案快死線時


4. 方法列表
- [ ]封裝成員變數 - class / private
- [x]提取方法 (reuse)
- [ ]一般化類型 (reuse)
- [x]函式歸父 - 子類別移動到父類別。
- [x]函式歸子 - 父類別移動到子類別。
- [x]方法更名

![](https://i.imgur.com/Cwnblx2.png)



5. [How ?](https://www.altexsoft.com/blog/engineering/code-refactoring-best-practices-when-and-when-not-to-do-it/)

- Red-Green-Refactor
![](https://www.altexsoft.com/media/2018/09/red-green-refactor.png)
-- Stop and consider what needs to be developed (RED)
-- Get the development to pass basic testing (GREEN)
-- Implement improvements (REFACTOR)

- Refactoring by Abstraction
-- The goal of abstraction is to reduce unnecessary duplications in software code

- Composing Method
1. Extraction
-- class, interface, local variables ...
2. Inline
-- reduce the number of unnecessary methods while simplifying the code

---
> **補充**
> TDD 是一種開發的流程。許多專案在開發時，通常會邊寫程式邊寫測試，或是先寫程式後寫測試，或是更常見 — 你知道的，寫了程式不寫測試。
TDD 則是「先寫測試再開發程式」。沒有程式要怎麼寫測試呢？除了有些工具可以讓你寫測試時，一邊幫你產生空的類別與方法外（如 Eclipse 撰寫 Java 時就有類似的功能），一般來說也可以直接假設你已經撰寫好了程式，先揣摩如果已經寫好了這個程式該要如何使用
---
6. [透過 Android Studio 或第三方套件找出程式碼潛在的壞味道 (Bad Taste)](https://www.twblogs.net/a/5b7e98ae2b717767c6aaad27)
- 實例 : Android Studio → Analyze → Run inspection by name -> 輸入下方關鍵字
實例1. Over long method : 圈複雜度 (cyclomatic complexity) > 11 , 就可以認爲函數過長
-- 可以將過長的函數拆分成幾個不同的小函數，拆分原則：一個函數的功能要保持職責單一，查詢和修改職責分開
實例2. Too many parameters : 函數參數過多
-- 在選項介面選擇 Whole Project 運行
實例3. Rebundant local variable : 冗餘的局部變量
-- 在選項介面選擇 Whole Project 運行
實例4. Unused Declaration : 無用函數
-- 需求已經下線的程式碼不應保留在專案中
- Infer : Facebook 開源的靜態程式碼檢查工具，可檢查 Android 和 Java 程式碼中的 NullPointException 和資源洩漏
-- 在 Analyze →　infer Nullity
- 第三方套件
1. FindBugs : 開源的靜態程式碼分析工具，不注重 style 及 format，注重檢測真正的 bug 及潛在的性能問題
2. MetricsReloaded : 由 JetBrain 開源開發，計算程式碼複雜度，即圈複雜度
3. Sonar : 涵蓋 Findbugs, PMD, CheckStyle, Android Lint 主要檢查規則，可檢測複雜度、重複、單元測試覆蓋率、程式碼標準、程式碼註釋、潛在 bug、架構設計



---

7. [MVVM with Clean Architecture](https://www.toptal.com/android/android-apps-mvvm-with-clean-architecture)
-- data flow
![](https://uploads.toptal.io/blog/image/127608/toptal-blog-image-1543413671794-80993a19fea97477524763c908b50a7a.png)
--- Presentation Layer
--- Domain Layer
--- Data Layer

---
Convert to MVVM
* Callable -> Observable
* Move API code to model
* Use Interface

---
8.[重構練習](https://proandroiddev.com/learn-kotlin-refactoring-an-app-38cf0cbefe6c)：
* [Dagger2](https://medium.com/@genchilu/%E4%BD%BF%E7%94%A8-dependency-injection-%E6%A1%86%E6%9E%B6-dagger2-%E5%BF%83%E5%BE%97-e7208d30f995) ( Koin for Kotlin )使用依賴注入，提高可測性，降低耦合性
* 切分 MVP、MVVM 的邏輯，達到單一職責的特性
* Clean Architecture
![](https://i.imgur.com/ngO6Sih.png)
* UI 測試框架 [Android Expresso](https://developer.android.com/studio/test/index.html) 
    * ViewMatchers：View層級去匹配指定的 View
    * ViewActions：執行 Views 的某些行為，如點擊事件
    * ViewAssertions：檢查 View 的某些狀態，如是否顯示
    * 使用實例：
    onView(ViewMatcher) //1.匹配 View
      .perform(ViewAction) //2.執行 View 行為
           .check(ViewAssertion); //3.驗證 View

---
Refactoring Myths
[使用重構工具的迷思](http://teddy-chen-tw.blogspot.com/2016/08/blog-post_2.html)

1. 意圖（Intent）
認為重構工具之所以有用是因為它可以幫助開發人員自動化完成單調乏味的設計改變(X)
重構工具可以協助自動化完成單調乏味的程式碼改變，這些改變對於設計有不同層度的影響。(O)

2. 原則（Principle）
如果在改善設計的過程中改變了程式行為，這種改善活動就不能稱為重構。

3. 強建度（Robustness）
"自動化重構工具應該很可靠"其實不然
工具只是提供簡單的字句替換，提供替換前與替換後的程式碼範例給開發人員參考，並不負責檢查重構前後行為是否一致。

4. 支援（Support）
最後一個迷思就是將自動化重構工具整合到IDE（整合開發工具例如Eclipse或Visual Studio.Net）是最佳吸引開發人員使用的途徑。作者認為重構工具必須要是開發人員已經熟悉環境的一部分，但這個環境不一定是IDE，可以是Vim、Notepad++或Sublime Text。
---


extra:
1. 變數、方法命名優化
2. 一個方法只做一件事情
3. 重複使用的常數提取出來 Constants
4. Hard code 的東西應設定為常數
5. 內存優化，提升效能
6. 加上註解，與刪除不必要的註解
7. 避免使用雙重否定的
8. 減少耦合
9. coding style
10. class 中 code 的行數與字數
11. refactor 之前，務必 commit 一個可以用的版本，commit commit commit
12. Dependency Injection

Tools:
1. JUnit
1. Mockito
1. Espresso
