Purity in My Programming: Functions in Go

原文连接

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都没错,看人的水平能否把控。

posted @ 2020-07-02 20:34  zhangyu63  阅读(120)  评论(0编辑  收藏  举报