在 What Color is Your Function? 一文中
Async function 被比喻成「紅色函式」
紅色函式不能在普通的函式裡(即「藍色函式」)使用
因此紅色具有感染性
定義函式之前必須先決定是否要染成紅色
作者不喜歡這種麻煩的規則
但我認為這種麻煩是有道理的
並不是只有Async function具有這種特性
其他像是:
Java的throw catch語法
rust的unsafe function
PureScript的partial function
Haskell的IO Monad
c++的non-const function
它們都具有感染性
它們的顏色代表了它們所關注的特性
Java強化傳統的例外處理機制
使錯誤變得可預期
rust在意記憶體安全
並使用unsafe在語法上明確地說明這一點
Haskell對於pure(referential transparency)的要求很嚴格
side effect必須以Monad的形式標註於型別上
Haskell因為歷史因素在totality上有很大的問題
而PureScript用Partial class修復了這個的問題
c++的non-const function只能在non-const function裡和non-const variable呼叫
使得const保證物件不會被修改
感染性使問題得以從根源(callee)傳播到你面前(caller)
這些都是在編譯時期完成的
因此開發者得以解放部分的專注力
把精力與時間花在真正的程式邏輯上
感染性使得這個特性使用起來會比較麻煩
這是因為他把原本被忽略被隱藏的特性顯現出來
rust的unsafe揭示了原本在c++習以為常但危險的操作
PureScript的partial也是如此
它們同時也建議使用者盡量把紅色函式抽離出來
而不是全部攪和在一起
rust本身的設計就是希望安全的程式碼應該好寫
不安全的程式碼仍然可能但不容易寫
Haskell的IO雖然是因為純函數式設計的問題才出現的
但同時也提供了「分離輸入輸出與計算邏輯」的思考方式
總結來說感染性使用的好是會給開發者帶來好處的
但像是c++的const就是使用的很差的例子
具有感染性的其實是non-const
但開發者常常在宣告函式時沒有正確的使用const
這使得const用起來很不方便
常常需要手動const_cast
相較之下rust的mut就非常地完美
更糟的例子是當有兩套一樣的函式但有兩種顏色時
我們就必須選邊站
Async function就是這種情況
另外類似的還有OOP的encapsulation
OOP把封裝限定在資料型別上
要使用封裝的函式只能繼承自該類別
這使得「少用繼承多用組合」變得難以實現
物件導向因此變得具有感染性(在壞的意義上)