oam 纯度
在Javascript世界中,纯函数经常被大肆宣传,这可能是由于前端应用程序中的状态丰富。 尽管纯函数有其缺点(即带来不便,可能存在大量参数列表),但我认为应尽可能合理地使用它们,并且我想关注Go中的纯函数。
什么是纯函数?
根据Wikipedia所述 ,Pure函数具有以下属性:
- 对于相同的参数,其返回值是相同的(局部静态变量 , 非局部变量 ,可变引用参数或来自I / O设备的输入流无变化)。
- 它的评估没有副作用 (本地静态变量,非本地变量,可变引用参数或I / O流不会发生突变)。
这意味着作为开发人员,我知道两件重要的事情:
- 当我调用一个纯函数时,每次都会得到相同的精确结果
- 调用纯函数后,我的程序将处于与调用前相同的状态(时间会流逝,并且我将已分配函数的结果)
由于这些特性,纯函数使应用程序简单。 众所周知,简单的应用程序通常会更快,更易于测试和调试,并且更不易出错。
Go(golang)中的示例
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
}
此功能不纯,原因有两个。 让我们检查每个。
1.通过调用countNamesInText()改变程序状态
我们应该通过return语句返回数据,而不是将全局变量变异为“返回”数据给调用者的方法。 我们可以假设这样做是因为在程序的其他地方存储计数映射是个好主意,但是最好在计数功能之外处理状态管理:
func countNamesInText (text string ) int {
totalCounted := 0
const name = getNameFromDatabase()
for _, word := range strings.Split(text, " " ) {
if word == mention {
totalCounted++
}
}
return totalCounted
}
更好的是,此功能更“纯净”,因为它不会更改应用程序的状态。
2.数据库参数
我们的函数仍然不纯正,因为从数据库中检索了影响函数调用结果的“名称”值。 为了使我们的函数具有确定性,该值应改为作为参数传递。
目前,如果我们编写了测试:
func TestCountNamesInText (t *testing.T) {
assert.Equal(t, 2 , countNamesInText( "this word here" ))
}
它不能始终如一地工作。 如果未设置数据库,或者数据库被篡改,我们的测试将失败。 这使它成为一个不好的测试,并且由于功能不纯而我们写了不好的测试。
让我们进一步净化一下:
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" ))
}
如果我们包括状态管理和数据库调用在内,现在我们的应用程序看起来将是什么样子:
totalCounted :=map [ string ] int {}
name := getNameFromDatabase()
totalCounted[name] = countNamesInText( "some name in here" , name)
谢谢阅读!
莱恩·瓦格纳@wagslane
在Qvault学习: https ://classroom.qvault.io
先前发表于 https://qvault.io/2019/10/30/purity-in-my-programming-please/
翻译自: https://hackernoon.com/purity-in-my-programming-pure-functions-in-go-c21m3u2z
oam 纯度