---
# System prepended metadata

title: Topic 38 - 40
tags: [The Pragmatic Programmer]

---

# Topic 38 - 40
###### tags: `The Pragmatic Programmer`

## Topic 38 靠巧合寫程式
作為一名程式開發人員，我們的工作之一就是掃雷（踩地雷）→ 時時警惕得到的結論是錯誤的
![](https://i.imgur.com/gyRWw5g.png)


- 避免依靠巧合寫程式
- 蓄意設計程式

### 如何靠巧合寫程式

- 當你不知道為什麼程式碼會 failed
    - 因為你從一開始就不知道它為什麼可以 work
- 有限的測試
    - 依賴未事先設計的程式或邊界條件 → 沒有預期到該情況的發生
    - Instead, developers should try to anticipate and plan for all possible scenarios in their software design and testing to minimize the risk of encountering these types of issues.
    - jest match snapshot
- 可以 work 卻不去細討原因（一方面覺得 jr 心態當然會更傾向能動為主，但要更進步的話，就是保持追究的心態，努力練習）
    - 依賴的邊界條件剛好是個例外，例如 cypress 在 local working fine，但在 github CICD 就常常 error → 原本 test 的寫法就不好
        
        ```jsx
        cy.visit('/products');
        cy.get('img[class^="ProductCard_card-image"]').eq(0).parent().click();
        cy.url({ timeout: 10000 }).should('contains', `${baseUrl}/products/`);
        ```
        
    - third-party libs upgrade version
    - 不必要的 call or invoke，使程式變慢
    - 新增 call = 有新 bug 的風險
        - 但怎麼可能不開發，重點是把測試做好
    - 抱持「只差一點點」的心態：書中時間例子，夏令政策與時區差異，請愛護 UTC !
    - Phantom Patterns(幻覺模式): 人們相信真實存在，但事實上並不存在，或者只是巧合模式
      
      ![](https://i.imgur.com/ItRnngN.png)

        
        - race condition ( race hazard ) - 多線程 process 共享同個資源，同時進行操作，導致落差並且不如預期
    
    ⭐ 盡量做到
    
    - 良好的模組化
    - 完善的說明文件
    - 合約式設計
    - 引用第三方，只使用官方文件提到的，ex antd
    - 不要假設，要證明 → 在不同環境測試及驗證 code


### 如何謹慎的設計程式

- 你的程式碼是否能被初階程序員理解
- 不要使用不理解的技術
- 先 design 再 coding
- 不要依賴假設 - 如果你不確定是否可靠，那就是不可靠
- 記錄假設（合約式設計）
- 測試假設 assertion
    
    ```jsx
    expect(mockDispatch).toBeCalledTimes(1);
    expect(mockDispatch).toHaveBeenNthCalledWith(1, {
       type: 'name',
       payload: {
           'zh-tw': null,
           'en-us': 'abc',
       },
    });
    ```
    
- 優先考慮力氣花在哪 → 先 design 再 coding
- 不要成為 legacy code 的奴隸 → 重構的重要性
---
## Topic 39 演算法速度
同樣的需求可以用不同演算法解決，那麼哪個好？

評估的三個指標

- time
- memory
- processor


| 線性演算法 | 非線性演算法(大多數) |
| --- | --- |
| 時間與 n 成正比增加 | 根據 n 倍數成長 |

#### Big-O notation

寫法 O( )

處理近似值的數學方法

這張圖會看到當 n 到達一定數量，Big O(n²) 所花時間比 Big O(n) 多千倍甚至萬倍。
![](https://i.imgur.com/jIWhWk8.png)
image source(https://ithelp.ithome.com.tw/m/articles/10213615)

#### 演算法實際執行速度

💡 這些值是否有界限？

如果數值是有界限的，就能計算出執行時間

#### Code profilers 程式碼側寫工具

- chrome dev tool
- React browser extension
- React Profiler
![](https://i.imgur.com/huc8F3f.png)
image source(https://www.netlify.com/blog/2018/08/29/using-the-react-devtools-profiler-to-diagnose-react-app-performance-issues/)
---
## Topic 40 重構

#### 比起建築，更像園藝
建築步驟：藍圖 → 挖地基、建造、鋪設管線、修飾 → 住戶入住，有問題時再修補

園藝步驟：種植 → 施肥 → 某些茁壯、某些枯死(成為堆肥)

#### 程式碼應該，甚至必須是個動態的東西
修剪、除草、持續監看花圃狀況作出調整

### 重構的定義

> 重組現有程式碼主體 - 改變其內部結構但不改變外部行為的嚴格技術
> 
- 非自由的
- 不會添增任何新功能
- 低風險的小步驟

宛若花園工項 - 翻耕

### 重構的目標

保持程式碼易於修改

### 重構的時機

- 當你有新的知識
- 隨時隨地
- 你覺得有「錯」
    - DRY
    - 非正交 （具有耦合）
    - 過時 - JQuery、瀏覽器 deprecated …
    - 效能
    - 通過測試時
    

### 重構的難點

- pain management 痛苦管理
    - 痛苦 - 重構或更新程式碼時，出現的困難及挑戰的過程
    - 管理 - 版本控制、事先規劃、測試
- 時間壓力 - 現在不重構，以後會花更多時間修補，且還是要重構 ^.^

### 重構的實施

重構的核心 - 重新設計

- 避免同時重構跟添加新功能
- 重構前，確保有良好的測試
- 更細的拆分


**⭐⭐⭐ Don’t live with broken windows.**