vlambda博客
学习文章列表

函数式代码是诚实代码

I’ve been reading quite a few attempts to define Functional Programming recently. It’s hard because we’ve taken so many paths in the industry. There’s some nexus around immutability, referential transparency, and typing. Each language makes its choices, and — if we are looking at those three qualities — it’s clear that you don’t need all of them to have what we call “functional programming” but having at least two at a time working together is enough to give us Good Stuff™.

最近,我已经读了很多定义函数式编程的尝试。很难,因为我们在行业中走了很多路。关于不变性,参照透明性和打字性存在一些联系。每种语言都有自己的选择,而且-如果我们要考虑这三种特质-显然,您不需要所有语言都具有我们所说的“函数式编程”,但是一次至少有两个一起工作就足以 给我们Good Stuff™。

There is a different way to approach it, though, and I think I arrived at it through years of slogging though legacy code. The biggest issue in legacy code (all code really) is understandability. It’s hard to change things that you don’t understand — you can try, but you’ll often fail.

但是,有一种不同的方法来处理它,我想我是通过多年编写遗留代码来解决它的。遗留代码(实际上是所有代码)中最大的问题是可理解性。很难改变您不了解的事物-您可以尝试,但经常会失败。

When I encounter a legacy system, the first thing I want to know is where the gotchas are, the things that break my understanding of the system. Invariably, they are the things that you can’t see at the interface. You call a function and you have no idea that it modifies some global variable, or surreptitiously saves to a database through a chain of calls. In other words, the function signature is a bit of a lie. We use the term side effect for these things, but really, they are the things that break the understanding that an interface could give you, if only it told you everything about how the system was affected when you call the function.

当我遇到一个遗留系统时,我想知道的第一件事就是陷阱,这是破坏我对系统理解的东西。这些都是您在界面上看不到的东西。您调用一个函数,却不知道它会修改某些全局变量,或者通过一系列调用秘密地保存到数据库中。换句话说,功能签名有点谎言。我们将副作用一词用于这些事情,但实际上,它们只是打破了接口可以为您提供的理解的东西,只要它告诉您有关调用函数时系统如何受到影响的所有信息。

Programming without side effects is really about making signatures honest in that way. If you want to know whether IO is possible, look at the signature. It should tell you.

没有副作用的编程实际上就是以这种方式使签名诚实。如果您想知道是否可以使用IO,请查看签名。它应该告诉你。

This isn’t typical in OO code. Sometimes I joke that if I were to rewrite Working Effectively with Legacy Code I’d call it Working Effectively with Object-Oriented Code. So many of the techniques around gaining testability involve parameterizing classes and methods so that all of the inputs and outputs are explicit and mockable under test. You don’t have an embedded call to, say, the file system in a class. You pass in a reference to that capability as a constructor or method argument. This makes an OO system, broadly functional. That is, to say, it is honest. You can look at the signatures and see what is possible. Maybe some mutation happens a function body. You increment a local variable rather than using a fold. That's ok. If it doesn't leak through the interface (the call), you have referential transparency at the call. The signature tells you the full story.

这在OO代码中并不常见。有时我开玩笑说,如果我要重写“使用遗留代码有效工作”,我会称之为“使用面向对象代码有效工作”。因此,围绕获得可测试性的许多技术都涉及到参数化类和方法的过程,以使所有输入和输出在测试中都是显式且可模拟的。您没有对类中的文件系统进行嵌入式调用。您将对该功能的引用作为构造函数或方法参数传递。这使OO系统具有广泛的功能。也就是说,这是诚实的。您可以查看签名,看看有什么可能。也许某些突变发生在功能体上。您增加局部变量而不是使用折叠。没关系。如果它没有通过接口(调用)泄漏,则您在调用时具有引用透明性。签名告诉您完整的故事。

I don’t want to denigrate OO. It’s useful and it can be a decent way of structuring systems, but it is a little less explicit at times. It permits a lot and you have to be careful to use it well.

我不想贬低OO。它很有用,并且可能是构建系统的一种不错的方式,但是有时它的含义不太明确。它允许很多,您必须小心使用。

Pure FP, especially in the typed world, can be a tower of mechanism to make sure that interfaces are explicit. That comes at a price. Monads and effect systems make us think more, and even write more, but we have more support to give our code this quality.

纯FP(尤其是在类型化的世界中)可以成为确保接口明确的机制之塔。那是有代价的。Monad和效果系统使我们思考更多,甚至编写更多,但是我们有更多的支持来使我们的代码具有这种品质。

That’s the goal, really. Simplify understanding. No surprises. Honest code.

真的,这就是目标。简化理解。没什么好奇怪的 诚实的代码。