当前位置: 首页 > 编程日记 > 正文

模糊推理 控制 易于实现_代码“易于推理”是什么意思?

模糊推理 控制 易于实现

by Preethi Kasireddy

通过Preethi Kasireddy

代码“易于推理”是什么意思? (What does it mean when code is “easy to reason about”?)

You’ve probably heard the expression “easy to reason about” enough times to make your ears bleed.

您可能已经听过“易于推理”的表达,足以让您的耳朵流血。

The first time I heard this expression, I had no idea what the person meant by it.

第一次听到这种表达时,我不知道这个人是什么意思。

Does it mean functions that are easy to understand?

它是否意味着功能易于理解?

Does it mean functions that work properly?

这是否意味着功能正常工作?

Does it mean functions that are easy to analyze?

它是否意味着易于分析的功能?

After a while, I’d heard “easy to reason about” in so many contexts that I figured it was just another semi-meaningless developer buzzword.

一段时间后,我在很多情况下都听到“容易推理”,以至于我认为这只是另一个无意义的开发人员流行语。

…But is it really meaningless?

…但这真的没有意义吗?

The truth is, the expression does have a significant meaning. It captures a fairly complex idea, which makes decoding it a bit tricky. Trickiness aside, having a high-level understanding of what “easy to reason about” code looks like absolutely helps us write better programs.

事实是,该表达确实具有重要意义。 它捕获了一个相当复杂的想法,这使其解码起来有些棘手。 除了棘手的问题外,对“易于推理”的代码看起来有高层的了解绝对可以帮助我们编写更好的程序。

To that end, this post will be dedicated to dissecting the expression “easy to reason about” as it relates to the technical conversations we have as developers.

为此,本文将专门剖析“易于推理”的表达方式,因为它与我们作为开发人员进行的技术对话有关。

了解程序的行为 (Understanding your program’s behavior)

Once you’ve written a piece of code, you typically also want to understand the program’s behavior, how it interacts with other parts of the program, and the properties it exhibits.

一旦编写了一段代码,您通常还希望了解程序的行为,程序与程序其他部分的交互方式以及所显示的属性。

For example, take the piece of code below. This should multiply an array of numbers by 3.

例如,采用下面的代码。 这应该将数字数组乘以3。

How can we test that it works as intended? One logical way is to pass a bunch of arrays as input and ensure that it always returns the array with each item multiplied by 3.

我们如何测试它是否按预期工作? 一种逻辑方法是传递一堆数组作为输入,并确保它总是返回每个项目乘以3的数组。

Looks good so far. We’ve tested that the function does what we want it to do.

到目前为止看起来不错。 我们已经测试过该功能可以完成我们想要的功能。

But how do we know it doesn’t do what we don’t want it to do? For instance, with careful inspection, we can see that the function mutates the original array.

但是,我们如何知道它没有做我们希望做的事情? 例如,通过仔细检查,我们可以看到该函数对原始数组进行了变异。

Is that what we intended? What if we need references to both the original array and the resulting array? Too bad, I guess.

那是我们想要的吗? 如果我们需要同时引用原始数组和结果数组该怎么办? 我想这太糟糕了。

Next, let’s see what happens if we pass the same array a bunch of different times — does it always return the same result for a given input?

接下来,让我们看看如果我们多次传递相同的数组会发生什么—它是否总是为给定的输入返回相同的结果?

Uh oh. It looks like when we passed the array [1, 2, 3] to the function the first time, it returned [3, 6, 9], but later it returned [ 49, 98, 147 ]. Those are very different results.

哦哦 看起来像是当我们第一次将数组[1、2、3]传递给函数时,它返回了[3、6、9] ,但后来又返回了[49、98、147] 。 这些是截然不同的结果。

That’s because the multiplyByThree function relies on an external variable multiplier. So, if the external state of the program causes the variable multiplier to change in between calls to the function multiplyByThree, the behavior of the function changes even if we pass the same array into the function.

那是因为multipleByThree函数依赖于外部变量乘数 。 因此,如果程序的外部状态导致变量乘数在对函数multipleByThree的调用之间改变,那么即使将相同的数组传递给函数,该函数的行为也会改变。

Eeek. Not looking that great anymore. Let’s dig a little deeper.

eek 看起来不再那么好了。 让我们深入一点。

So far, we’ve tested perfect array inputs. Now, what if we were to do this:

到目前为止,我们已经测试了完美的数组输入。 现在,如果我们要这样做:

What in the world?!?

到底是什么?!?

The program looked great on the surface — when we take a few minutes to evaluate it, however, it was a different story.

该程序表面上看起来很棒–当我们花几分钟时间对其进行评估时,却是另一回事了。

We saw that it sometimes returns an error, sometimes returns the same thing you passed to it, and only occasionally returns the expected result. Moreover, it has some unintended side effects (mutating the original array) and doesn’t seem to be consistent in what it returns for a given input (since it relies on external state).

我们看到它有时返回错误,有时返回您传递给它的东西,并且仅偶尔返回预期结果。 而且,它具有一些意外的副作用(使原始数组发生突变),并且对于给定输入返回的结果似乎不一致(因为它依赖于外部状态)。

Now, let’s look a slightly different multiplyByThree function:

现在,让我们看一个稍微不同的multipleByThree函数:

Just like above, we can test for correctness.

就像上面一样,我们可以测试正确性。

Looking good so far.

到目前为止看起来不错。

Let’s also test to see if it does what we don’t want it to do. Does it mutate the original array?

让我们也测试一下是否可以完成我们不希望做的事情。 它会改变原始数组吗?

Nope. The original array is intact!

不。 原始数组完好无损!

Does it return the same output for a given input?

对于给定的输入,它是否返回相同的输出?

Yep! Since the multiplier variable is now within the scope of the function, even if we declare a duplicate multiplier variable in the global scope, it won’t affect the result.

是的 由于乘数变量现在位于函数的范围内,因此即使我们在全局范围内声明重复的乘数变量,也不会影响结果。

Does it return the same thing if we pass a bunch of different types of arguments?

如果我们传递一堆不同类型的参数,它是否会返回相同的东西?

Yep! Now the function behaves more predictably — it either returns an error or a new resulting array.

是的 现在,该函数的行为更具可预测性-它返回错误或新的结果数组。

At this point, how confident are we that this function does exactly what we want it to do? Have we covered all the edge cases? Let’s try a few more:

在这一点上,我们对这个功能确实能够实现我们想要的功能充满信心吗? 我们涵盖了所有极端情况吗? 让我们再尝试一些:

Damn. Looks like our function still needs a little work. When the array itself contains unexpected items, like undefined or strings, we see weird behavior again.

该死的。 看起来我们的功能仍然需要一点工作。 当数组本身包含意外项目( 如未定义或字符串)时,我们会再次看到怪异的行为。

Let’s try to fix it by adding another check in our for-loop checking for invalid array elements:

让我们尝试通过在for循环检查中添加另一个检查无效数组元素来解决此问题:

With this new function, why not try those two edge cases again:

有了这个新功能,为什么不再次尝试这两个边缘情况:

Sweet. Now it also returns an error if any of the items in the array are not numbers instead of some random funky output.

甜。 现在,如果数组中的任何项目不是数字,而是一些随机的时髦输出,它也会返回一个错误。

最后,一个定义 (Finally, a definition)

By going through the the above steps, we’ve slowly built up a function that is easy to reason about because it has these key qualities:

通过上述步骤,我们逐步构建了一个易于推理的函数,因为它具有以下关键特性:

  1. Does not have unintended side effects

    没有意外的副作用
  2. Does not rely on or affect external state

    不依赖或不影响外部状态
  3. Given the same argument, it will always return the same corresponding output (also known as “referential transparency”).

    给定相同的参数,它将始终返回相同的对应输出(也称为“ 参照透明性 ”)。

我们可以保证这些属性的方法 (Ways we can guarantee these properties)

There’s a lot of different ways we can guarantee that our code is easy to reason about. Let’s take a look at a few:

我们可以通过很多不同的方式来保证我们的代码易于推理。 让我们看一些:

单元测试 (Unit tests)

Firstly, we can write unit tests to isolate pieces of code and verify that they function as intended:

首先,我们可以编写单元测试来隔离代码段并验证它们是否按预期运行:

Unit tests like these help us verify that our code behaves correctly and give us living documentation about how small pieces of the overall system work. The caveat with unit tests is that unless you’re very thoughtful and thorough, it’s incredibly easy to miss problematic edge cases.

像这样的单元测试可以帮助我们验证我们的代码是否正确运行,并为我们提供有关整个系统的小部分工作方式的实时文档。 单元测试的警告是,除非您非常周到和透彻,否则遗漏有问题的边缘情况非常容易。

For example, we would never have figured out that the original array is being mutated unless we somehow thought to test for it. So our code is only as robust as our tests.

例如,除非我们以某种方式考虑对其进行测试,否则我们永远不会弄清楚原始数组是否正在被突变。 因此,我们的代码仅与测试一样强大。

种类 (Types)

In addition to tests, we might also use types to make it easier to reason about code. For example, if we were using a static type checker for JavaScript like Flow, we could ensure that the input array is always an array of numbers:

除了测试,我们还可以使用类型来简化代码推理。 例如,如果我们对像Flow这样JavaScript使用静态类型检查器,则可以确保输入数组始终是数字数组:

Types force us to explicitly state that the input array is an array of numbers. They help create restrictions on our code which prevent many kinds of runtime errors like we saw earlier. In our case, we no longer have to think about checking to make sure that each item in the array is a number — this is a guarantee given to us with types.

类型迫使我们明确声明输入数组是数字数组。 它们有助于对我们的代码创建限制,以防止像我们前面看到的多种运行时错误。 在我们的例子中,我们不再需要考虑确保数组中的每个项目都是数字,这是对类型的保证。

不变性 (Immutability)

Lastly, another thing we can do is use immutable data. Immutable data just means that the data cannot be changed once it’s created. This helps avoid unintended side effects.

最后,我们可以做的另一件事是使用不可变数据。 不可变的数据只是意味着一旦创建数据就无法更改。 这有助于避免意外的副作用。

In our earlier example, for instance, if the input array were immutable, it would have prevented the unpredictable behavior where the original array is mutated. And if the multiplier were immutable, it would prevent situations where some other part of the program can mutate our multiplier.

例如,在我们前面的示例中,如果输入数组是不可变的,那么它将防止原始数组发生突变时发生不可预测的行为。 而且,如果乘数是不可变的,它将防止程序的其他部分可以使乘数发生变化的情况。

Some of the ways we can reap the benefits of immutability is by using a functional programming language that inherently ensures immutability or by using an external library, like Immutable.js, that enforces immutability on top of an existing language.

我们可以利用不变性的好处的一些方法是使用一种功能性编程语言来固有地确保不变性,或者使用外部库(例如Immutable.js)在现有语言之上实施不变性。

As a fun exploration, I’ll use Elm, a typed functional programming language, to demonstrate how immutability helps us:

作为一个有趣的探索,我将使用一种类型化的函数式编程语言Elm来演示不变性如何帮助我们:

This little snippet does the same thing as our JavaScript multiplyByThree function from before, except it’s now in Elm. Since Elm is a typed language, you’ll see on line 6 that we define the input and output types for the function multiplyByThree as both being a list of numbers. The function itself uses the basic map operation to generate the resulting array.

这个小片段与JavaScript的遍历功能相同,只是现在在Elm中 。 由于Elm是一种类型化的语言,因此您会在第6行看到我们将函数multipleByThree的输入和输出类型定义为数字列表。 该函数本身使用基本映射操作来生成结果数组。

Now that we’ve defined our function in Elm, let’s do one last round of the same tests we did for our earlier multiplyByThree function:

既然我们已经在Elm中定义了函数,那么让我们做最后一轮的测试,该测试与我们之前的multiByThree函数相同:

As you can see, the result is what we expected and the originalArray has not been mutated.

如您所见,结果是我们所期望的,而且originalArray还没有发生突变。

Now, let’s throw Elm for a trick and try mutating the multiplier:

现在,让我们把Elm当作一个把戏,然后尝试改变乘数:

Aha! Elm restricts you from doing this. It throws a very friendly error.

啊哈! 榆木限制您执行此操作。 它抛出一个非常友好的错误。

What if we were to pass a string as an argument, instead an array of numbers?

如果我们将字符串作为参数而不是数字数组传递呢?

Looks like Elm caught that as well. Because we declared the argument as a List of numbers, we cannot pass anything but a List of numbers even if we tried!

看起来榆树也抓住了这一点。 因为我们将参数声明为数字列表,所以即使尝试,我们也只能传递数字列表!

We cheated a little bit in this example by using a functional programming language which has both types and immutability. The point I wanted to prove is that with these two features, we no longer have to think about manually adding checks for all the edge cases in order to gain the three properties we discussed. Types and immutability guarantee that for us, and in turn, we can reason about our code more easily ?

在本示例中,我们使用了一种既具有类型又具有不变性的功能编程语言,以作弊。 我想证明的一点是,有了这两个功能,我们不再需要考虑为所有边缘情况手动添加检查以获取我们讨论的三个属性。 类型和不变性为我们提供了保证,进而可以使我们更轻松地推理代码?

现在轮到您对代码进行推理了 (Now it’s your turn to reason about your code)

I challenge you to take a moment next time you hear someone say, “XYZ makes it easy to reason about code” or “ABC makes is difficult to reason about code.” Replace that fancy buzzword with the properties mentioned above, and try to understand what the person means. What properties does the piece of code have that makes it easy to reason about?

下次您听到有人说“ XYZ使代码推理变得容易”“ ABC使代码推理变得困难”时 ,我挑战您花点时间 用上面提到的属性替换该时髦的流行语,并尝试理解该人的含义。 代码段具有哪些属性可以使推理变得容易?

Personally, doing this exercise has helped me critically think about code and, in turn, has motivated me think about how to write programs that are easier to reason about. I hope it does the same for you too!

就个人而言,进行此练习可以帮助我批判性地考虑代码,进而促使我考虑如何编写更易于推理的程序。 我希望它也对您有帮助!

I’d love to hear your thoughts on other properties that I might have missed that you think are important. Please leave your feedback in the comments!

我很想听听您对其他物业的想法,我可能会错过您认为重要的事物。 请在评论中留下您的反馈!

翻译自: https://www.freecodecamp.org/news/what-does-it-mean-when-code-is-easy-to-reason-about-4e6f63eb386f/

模糊推理 控制 易于实现

相关文章:

简单介绍一下R中的几种统计分布及常用模型

统计学上分布有很多,在R中基本都有描述。因能力有限,我们就挑选几个常用的、比较重要的简单介绍一下每种分布的定义,公式,以及在R中的展示。 统计分布每一种分布有四个函数:d――density(密度函…

leetcode题解:Construct Binary Tree from Preorder and Inorder Traversal (根据前序和中序遍历构造二叉树)...

题目: Given preorder and inorder traversal of a tree, construct the binary tree. Note:You may assume that duplicates do not exist in the tree. 说明: 1)二叉树可空 2)思路:a、根据前序遍历的特点, 知前序序列…

swift string,Int,Double相互转换

import UIKitvar str "Hello, playground" // 1 字符串转Int Double Float var str1 "818"; // 转Int var val1 Int(str1); // 转Double var val2 Double(str1); // 转float var val3 Float(str1);// 如果是25.0 转 Int,则需要先转为Doubl…

classlist使用方法_如何通过使用HTML5的classList API在没有jQuery的情况下操作类

classlist使用方法by Ayo Isaiah通过Ayo Isaiah 如何通过使用HTML5的classList API在没有jQuery的情况下操作类 (How to manipulate classes without jQuery by using HTML5s classList API) As a front end developer, you often need to change CSS rules based on how a us…

键盘码 ascii码

ASCII码表 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 ASCII值 控制字符 0 NUT 32 (space) 64 96 、 1 SOH 33 ! 65 A 97 a 2 STX 34 ” 66 B 98 b 3 ETX 35 # 67 C 99 c 4 EOT 36 $ 68 D 100 d 5 ENQ 37 % 69 E 101 e 6 ACK 38 & 70 F 102 f 7 BEL …

Swift -布局框架SnapKit使用

SnapKit 1 安装 SnapKit github地址 2 文档地址 在线文档 // // ViewController.swift // SK_SnapKit // // Created by coder on 2019/3/6. // Copyright © 2019 AlexanderYeah. All rights reserved. //import UIKit import SnapKitclass ViewController: UIVie…

Hadoop概念学习系列之为什么hadoop/spark执行作业时,输出路径必须要不存在?(三十九)...

很多人只会,但没深入体会和想为什么要这样? 拿Hadoop来说,当然,spark也一样的道理。 输出路径由Hadoop自己创建,实际的结果文件遵守part-nnnn的约定。 如何指定一个已有目录作为Hadoop作业的输出路径,作业将…

已知环境静态障碍物避障_我女儿如何教我无障碍环境

已知环境静态障碍物避障by Drew通过德鲁 我女儿如何教我无障碍环境 (How my daughter taught me about accessibility) 在过去的几个月里,花了很多时间学习编程知识,这真是令人大开眼界。 面对似乎无穷无尽的技术和概念(即使是最简单的事物)&#xff0c…

IIS 部署 node.js ---- 基础安装部署

一些可能有用的相关文章: https://blogs.msdn.microsoft.com/scott_hanselman/2011/11/28/window-iisnode-js/ http://blog.csdn.net/puncha/article/details/9047311 20161123,这几天看了一些相关文章,觉得说的不太清楚,记录一下…

Qt中的 Size Hints 和 Size Policies

sizeHint 这个属性所保存的 QSize 类型的值是一个被推荐给窗口或其它组件(为了方便下面统称为widget)的尺寸,也就是说一个 widget 该有多大,它的一个参考来源就是这个 sizeHint 属性的值,而这个值由 sizeHint() 函数来…

atom 中首次使用git_使用Atom获得更好的Git提交消息

atom 中首次使用gitby Hasit Mistry通过Hasit Mistry 使用Atom获得更好的Git提交消息 (Get Better Git Commit Messages with Atom) Recently, I came across two enlightening posts about writing better Git commit messages. These posts give suggestions about how a we…

正确理解ThreadLocal

详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt107 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程…

PHP-密码学算法及其应用-对称密码算法

转自:http://www.smatrix.org/bbs/simple/index.php?t5662.html //目录1. PHP的散列函数及其应用2. PHP中的对称密码算法及其应用3. PHP的公钥密码算法及其应用///2 PHP中的对称密码算法及其应用前一段时间一直想写完PHP中的密码学算法及其应用的三大部分…

Swift4 String截取字符串

var str1 "AlexanderYeah";// 1 截取字符串的第一种方式 // prefix 截取前3个字符串 var str2 str1.prefix(3); print(str2);// suffix 截取后3个字符串 var str3 str1.suffix(3); print(str3);// 2 截取一个范围的字符串 // 从0开始 到倒数第二位结束 let idx1 …

angular react_Angular 2 vs React:将会有鲜血

angular reactAngular 2 has reached Beta and appears poised to become the hot new framework of 2016. It’s time for a showdown. Let’s see how it stacks up against 2015’s darling: React.Angular 2已达到Beta版本,并有望成为2016年炙手可热的新框架。该…

Welcome to Swift (苹果官方Swift文档初译与注解三十四)---241~247页(第五章-- 函数)

In-Out Parameters (全局参数) 像前面描述的参数变量,只能在函数体内进行修改,如果你需要函数修改的它的参数值,并且希望这些改变在函数调用结束后仍然有效,可以定义使用全局参数. 定义全局参数使用关键字inout,全局参数的值在函数调用的时候进行传递,在函数体内进行修改,最后函…

递归 尾递归_代码简报:递归,递归,递归

递归 尾递归Here are three stories we published this week that are worth your time:这是我们本周发布的三个值得您关注的故事: A beginner’s guide to recursion: 6 minute read 递归初学者指南: 6分钟阅读 Things you probably didn’t know you …

Hadoop 生态系统

当下 Hadoop 已经成长为一个庞大的生态体系,只要和海量数据相关的领域,都有 Hadoop 的身影。下图是一个 Hadoop 生态系统的图谱,详细列举了在 Hadoop 这个生态系统中出现的各种数据工具。这一切,都起源自 Web 数据爆炸时代的来临。…

socket通信——通过Udp传输方式,将一段文字数据发送出去

需求:通过Udp传输方式,将一段文字数据发送出去定义一个Udp发送端思路:1、建立updsocket服务2、提供数据,并将数据封装到数据包中。3、通过socket服务的发送功能,将数据包发出去4、关闭资源。import java.net.*; class …

编码中统一更该变量的快捷键_流媒体的7种方式使您成为更好的编码器

编码中统一更该变量的快捷键by freeCodeCamp通过freeCodeCamp 流媒体的7种方式使您成为更好的编码器 (7 Ways Streaming Makes you a Better Coder) After coding live on twitch.tv for dozens of hours, I’m convinced that streaming makes you a better coder. Here’s w…

AutoConfig工具使用

下载安装Auto工具包: http://code.taobao.org/mvn/repository/com/alibaba/citrus/tool/antx-autoconfig/1.0.9/antx-autoconfig-1.0.9.tgzhttp://code.taobao.org/mvn/repository/com/alibaba/citrus/tool/antx-autoexpand/1.0.9/antx-autoexpand-1.0.9.tgztar zxv…

Spark2 ML 学习札记

摘要:  1.pipeline 模式 1.1相关概念 1.2代码示例  2.特征提取,转换以及特征选择 2.1特征提取 2.2特征转换 2.3特征选择 3.模型选择与参数选择 3.1 交叉验证 3.2 训练集-测试集 切分 4.spark新增SparkSession与DataSet 内容: 1.pipeline …

xCode 开发快捷键

Ctrl CMD 右箭头返回上一个编辑的界面Ctrl CMD 左箭头返回后一个编辑的界面CMD Option 左箭头区域代码折叠CMD Option 右箭头区域代码展开Shift CMD Option 左箭头折叠界面内所有的代码Shift CMD Option 右箭头展开界面内所有的代码CMD Ctrl 上下箭头.h 和 .m …

javascript模块_JavaScript模块第2部分:模块捆绑

javascript模块by Preethi Kasireddy通过Preethi Kasireddy JavaScript模块第2部分:模块捆绑 (JavaScript Modules Part 2: Module Bundling) In Part I of this post, I talked about what modules are, why developers use them, and the various ways to incorp…

idea上实现github代码同步

1.先将github远程仓库clone到本地 2.将本地仓库中的项目导入到idea中 3.如果你的项目代码不是放在仓库的根目录下,idea会识别到你的项目是在git仓库目录下,必须点击add root才能匹配路径。 4.add root后会发现右击项目时会多了一个git选项 5.在git选项中…

iOS12 UITabbar Item 向上漂移错位的bug

[[UITabBar appearance] setTranslucent:NO]; 加此行代码 完美解决此bug

jQuery学习笔记(一)

补充一些自己容易忘的知识点: event.stopPropagation() 阻止事件冒泡 event.preventDefault() 阻止事件的默认行为 return false 相当于event.stopPropagation() event.preventDefault() 。除了阻止默认行为之外,还会阻止事件冒泡。 转载于:https://www.cnblogs.…

随机网络构建_构建随机报价机

随机网络构建by Ayo Isaiah通过Ayo Isaiah 构建随机报价机 (Building a Random Quote Machine) I really wasn’t entirely satisfied with my first attempt at building a Random Quote Generator on Free Code Camp. It was ugly, and the quotes were too long, so I didn…

20145231 《信息安全系统设计基础》第11周学习总结

20145231《信息安全系统设计基础》第11周学习总结 教材学习内容总结 异常 异常是异常控制流的一种形式,由硬件和操作系统实现。简单来说,就是控制流中的突变。 出现异常的处理方式: 1.处理器检测到有异常发生 2.通过异常表,进行间…

JAR命令使用

jar 命令详解 jar 是随 JDK 安装的,在 JDK 安装目录下的 bin 目录中,Windows 下文件名为 jar.exe,Linux 下文件名为 jar。它的运行需要用到 JDK 安装目录下 lib 目录中的 tools.jar 文件。不过我们除了安装 JDK 什么也不需要做,因…