原文连接
https://hackernoon.com/purity-in-my-programming-pure-functions-in-go-c21m3u2z
什么是纯函数
在程序设计中,若一个函数符合以下要求,则它可能被认为是纯函数: 此函數在相同的输入值時,需產生相同的輸出。 函數的輸出和輸入值以外的其他隐藏信息或狀態無關,也和由I/O設備產生的外部輸出無關。 该函数不能有语义上可观察的函数副作用,诸如“触发事件”,使輸出設備輸出,或更改輸出值以外物件的內容等。(wiki)
如何理解
纯函数的好处和坏处都有,坏处就是容易产生大量的参数列表,好处就是快,稳定,准确。当然,还是要使用起来的。
例子
这里示例一步步改进
step1
totalCounted := map[string]int{}
func countNamesInText(text string) {
total := 0
const name = getNameFromDatabase()
for _, word := range strings.Split(text, " ") {
if word == mention {
total++
}
}
totalCounted[name] = total
}
这句显然违法了纯函数的基本定义,对一个全局的变量state changed
totalCounted[name] = total
step2
func countNamesInText(text string) int {
totalCounted := 0
const name = getNameFromDatabase()
for _, word := range strings.Split(text, " ") {
if word == mention {
totalCounted++
}
}
return totalCounted
}
似乎看起来ok,但是还有一个痛点,数据库的读取
const name = getNameFromDatabase()
这就取决于数据库是否配置开启,是否中途数据篡改等,举一个这种情况下的“糟糕”的测试
func TestCountNamesInText(t *testing.T) {
assert.Equal(t, 2, countNamesInText("this word here"))
}
其实这个并不是测试的锅,但是这的确会导致test failed
step3
func countNamesInText(text, name string) int {
totalCounted := 0
for _, word := range strings.Split(text, " ") {
if word == mention {
totalCounted++
}
}
return totalCounted
}
func TestCountNamesInText(t *testing.T) {
assert.Equal(t, 1, countNamesInText("this word here", "this"))
}
似乎没什么问题了,ok,的确没问题了
end
这种函数怎么顺序使用呢
totalCounted := map[string]int{}
name := getNameFromDatabase()
totalCounted[name] = countNamesInText("some name in here", name)
可以看到我们需要提前对参数在func外部获取,如果参数过多,则会陷入“参数列表”的窘境,pure or impure都没错,看人的水平能否把控。