---
# System prepended metadata

title: 用 Functional Programing 的方式思考

---

# 用 Functional Programing 的方式思考

> 網頁世界裡的大禹治水

---

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

---

### Funcitonal Programing 的價值是什麼？

> 區隔外部和內部，當你確定程式內部沒有副作用，就可以確定程式碼運行結果符合預期，而且很容易做改動。

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

---

## 生活中的 Funcitonal Programing

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

---

### 生活中的 Funcitonal Programing

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

---

### 生活中的 Funcitonal Programing
![](https://i.imgur.com/oicfTDr.png)

---

### 生活中的 Funcitonal Programing
![](https://i.imgur.com/eoqeZNk.png)

---

### 生活中的 Funcitonal Programing

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

---

### 生活中的 Funcitonal Programing

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

---

### WTF FP？

> 區隔副作用和非副作用產生的地方

將程式的運行，拆解成各個「沒有副作用」的獨立環節（水管）與環節（水管）的串連，每個獨立環節都可以獨立做優化。

---

### 水管 VS Pure Function

- 一個良好設計的水管不會漏水（副作用）
- 相同輸入，相同輸出。

---

### 前端應用程式

React 單向資料流，自上而下的流動

我們從雲上拿到水（資料），水在一個個湖泊短暫停留（畫面狀態），再流向下一個湖泊，最後送回雲（Server）。

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

---

### FP 的應用

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

---

### FP 的應用

- 前端
    - React
        - Comopnents
        - Hooks
    - Computation (ex: ramda, lodash-fp)
    - Functional CSS (ex: tailwind)

- 後端
    - Lambda(Serverless)

---

### 實際上在前端如何使用 FP ?
- 內建 Function
  - map
  - filter
  - includes
  - reduce

---

### 實際上如何使用 FP ?
- FP Library(lodash-fp/ramda)
  - curry
  - pipe / compose
  - project / pluck / pick
  - keys / values
  - isNil / isEmpty
  - update
  - toPairs
  - innerJoin
  - last
  - reject

---

### 綜合應用 Higher Order Component（參數化的 Container） + FP

```js
import { compose } from 'ramda'
import withMerchant from "./hoc/merchant"
import withPageView from "./hoc/view"

const withPage = compose(withMerchant, withPageView)

const PageComponent = withPage(({ merchant, view }) => <div></div>)

function App() {
  return <PageComponent />
}
```

---

### 綜合應用 FP （Function Composition）
> 任何 Function 都是一種抽象，每一種抽象都要給他一個好的命名

```js
import { pipe, curry, pick, reject, isNil, keys, last } from 'ramda'

const filter = {
    orderNumber: 12341234,
    email: null,
    brandKey: null,
    brandGroupKey: null,
}

const getActiveFilterType = pipe(
  curry(pick)([
    "orderNumber",
    "email",
    "brandKey",
    "brandGroupKey"
  ]),
  curry(reject)(isNil),
  keys,
  last
)

const filterType = getActiveFilterType(filter) // = orderNumber

```

---

### 用 FP 的方式思考
> 網頁世界裡的大禹治水

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

---

### 大禹治水 VS FP

- 我們希望產出結果（水流、資料流）可以預期。
- 只要河道（function）不改變，結果就不會發生改變。
- 每個河道（function) 都可以單獨加強。
- 可以根據河道（function）的串連，預期結果，不用實際等到河流氾濫（程式崩潰產生 Bug）才去尋找原因，更好的除錯。
- 當時空環境發生（需求結果）改變，我們可以更改河道（修改 function 的之間的組合），響應需求的變動。
