optionals_如何避免JavaScript中的空检查污染:使用Optionals

optionals

by Konstantin Blokhin

康斯坦丁·布洛欣(Konstantin Blokhin)

如何避免JavaScript中的空检查污染:使用Optionals (How to avoid null check pollution in JavaScript: use Optionals)

I’ve been using JavaScript for the past few years and have been enjoying it in general. But it lacks some cool features from other languages. For instance, there is no built-in safe navigation and no means to avoid null checks. The code gets polluted with boilerplate conditional branches. It’s error-prone and less readable.

在过去的几年中,我一直在使用JavaScript,并且一直都很喜欢它。 但是它缺少其他语言的一些出色功能。 例如,没有内置的安全导航,也没有避免空检查的方法。 该代码被样板条件分支污染。 它易于出错且可读性较差。

What’s wrong with null checks, you might ask?

您可能会问,空检查有什么问题?

First of all, the inventor of the null reference, Tony Hoare, called it a billion-dollar mistake:

首先,空引用的发明者Tony Hoare 称之为 十亿美元的错误:

But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.

但是我无法抗拒引入空引用的诱惑,只是因为它是如此容易实现。 这导致了无数的错误,漏洞和系统崩溃,在最近四十年中可能造成十亿美元的痛苦和破坏

JavaScript is no different. How many times have you encountered TypeError: Cannot read property 'bar' of null error? To avoid these, developers always have to keep this null possibility in mind. And they would rather concentrate on the real thing like application-specific logic.

JavaScript也不例外。 您遇到过几次TypeError: Cannot read property 'bar' of null错误的TypeError: Cannot read property 'bar' of null ? 为避免这些情况,开发人员始终必须牢记这种无效的可能性。 他们宁愿专注于诸如特定于应用程序的逻辑之类的真实事物。

Next, you actually have to introduce new conditional branches into your code. And generally you don’t wanna have lots of them, since if statements tend to decrease overall readability of the code. Take the arrow anti-pattern as an extreme example. Moreover, these statements are almost meaningless in terms of your domain or business logic.

接下来,您实际上必须在代码中引入新的条件分支。 通常,您不需要很多,因为if 语句会降低代码的整体可读性。箭头反模式为例。 而且,就您的领域或业务逻辑而言,这些陈述几乎毫无意义。

I like one of the ways of solving that problem, explained here by Michael Feathers — the “commands instead of queries” approach. And he also develops this idea and talks about the benefits of unconditional code in general.

我喜欢迈克尔·费瑟斯(Michael Feathers)在此处解释的解决问题的一种方法,即“命令而不是查询”的方法。 他还提出了这个想法,并讨论了无条件代码的总体好处。

Basically, instead of querying a piece of data and checking if it’s there for further processing, we just express our intention and let module internals decide whether or not the action should be taken.

基本上,我们只是表达我们的意图,而不是查询一条数据并检查是否有进一步处理的数据,而是让模块内部成员决定是否应采取该措施。

Let’s say we want to fetch a user and their friends’ favourite books for recommendation. The code could be like:

假设我们要获取用户及其朋友最喜欢的书作为推荐。 代码可能像这样:

So, I’d rather have some module to encapsulate the checking logic. Therefore, we just tell it what to do with an active user:

因此,我宁愿有一些模块来封装检查逻辑。 因此,我们只告诉它如何处理活动用户:

The code is more focused on the business logic now. And we can reuse it to perform other actions with an active user without the burden of null checks.

该代码现在更加集中于业务逻辑。 而且我们可以重用它与活动用户一起执行其他操作,而无需进行空检查。

But the given solution is a bit too specific. Besides, we still have a null check in our controller or some other place where we use the function.

但是给定的解决方案过于具体。 此外,我们在控制器或使用函数的其他地方仍然有空检查。

A more general approach is required. What we need is a special data type, a container for nullable values — such as the Optional class in Java, for example. Point is, any actions, given to the container, will be executed only on a non-empty containing value.

需要一种更通用的方法。 我们需要一种特殊的数据类型,一个可为空的值的容器,例如Java中的Optional类。 重点是,赋予容器的任何操作将仅在非空的包含值上执行。

There are some JS libraries (like Optional.js), implementing almost the same interface as Java Optional. But they don’t take into account the asynchronous nature of JS and don’t work with Promises.

有一些JS库(例如Optional.js ),实现了与Java Optional几乎相同的接口。 但是它们没有考虑到JS的异步特性,也无法与Promises一起使用。

And most of the time when the absence of a value is possible, we actually have to deal with promises and async functions. For instance, take external resource requests like database queries and API calls.

在大多数情况下,可能缺少值时,我们实际上必须处理promise和async函数。 例如,接受外部资源请求,例如数据库查询和API调用。

That’s when AsyncOptional comes to the rescue. So, it’s a container for an optional value of asynchronous nature. Optional means that the value may be present or absent. Both null and undefined are considered absent.

那就是AsyncOptional抢救出来的时候。 因此, 它是异步性质的可选值的容器可选表示该值可以存在或不存在。 nullundefined均不存在。

As soon as we want to tell the program what to do with a non-empty value, the factory method is called “with”:

一旦我们想告诉程序如何处理非空值,工厂方法就称为“ with”:

const withUser = AsyncOptional.with(user);

Then we could do some processing, as it’s shown in the example below. Once we’re done and want to fix the result somewhere, one of terminal methods should be used.

然后,我们可以进行一些处理,如下面的示例所示。 一旦我们完成并想要将结果固定在某个地方,则应使用一种终端方法。

For instance, when we don’t need to react on an empty value:

例如,当我们不需要对空值做出React时:

We can also specify what to do in case of the absence of the value in this natural-language-like way:

我们还可以通过类似自然语言的方式指定在缺少值的情况下该怎么做:

Between factory and terminal method calls, there can be any processing logic, described in the readme. It’s guaranteed that no action will be taken upon an empty value.

在工厂方法和终端方法调用之间,可以有任何处理逻辑,如自述文件所述 。 保证不会对空值采取任何措施。

Some of the actions you can use to process the value:

您可以用来处理值的一些操作:

So let’s take a final look at our example:

因此,让我们最后看一下我们的示例:

So, how is it better compared with the initial one?

那么,与最初的相比有什么更好的呢?

I believe the answer is — it’s way more clean and readable, and readability is the essence of good code.

我相信答案是–它更简洁易读,可读性是好的代码的本质。

First, we got rid of null-checking conditional branches, so we can focus on the important thing — which is the business logic of the system.

首先,我们摆脱了空检查条件分支,因此我们可以专注于重要的事情-这是系统的业务逻辑。

Next, we eliminated the possibility of having null pointer exceptions here. This means we don’t have to keep the nullability of the value in mind, which is one less way to introduce bugs.

接下来,我们消除了此处出现空指针异常的可能性。 这意味着我们不必牢记值的可为空性,这是引入错误的一种较少方法。

Another case the library can come in handy is in a “default value” situation. Let’s say we have some kind of form for a user to fill, and among other fields there is fruit selection. The user can choose an orange, apple or nothing.

库可以派上用场的另一种情况是处于“默认值”情况。 假设我们有某种表单供用户填写,在其他字段中还有水果选择。 用户可以选择橙,苹果或什么都没有。

So the output is:

因此输出为:

conditionalChooseFruit(‘Joe’);// => You chose nothing, Joe.
conditionalChooseFruit(‘Joe’, {notFruit: ‘x’});// => You chose nothing, Joe.
conditionalChooseFruit(‘Joe’, {fruit: 1});// => You chose apple, Joe.
conditionalChooseFruit(‘Joe’, {fruit: 11});// => You chose a wrong gardener to mess with, Joe.

For me, this method looks a bit messy even with the help of async/await and reversed conditions. The business logic gets blurred by conditional branches.

对我来说,即使在异步/等待和逆向条件的帮助下,这种方法也显得有些混乱。 条件分支使业务逻辑变得模糊。

And with AsyncOptional it can be rewritten in a more straightforward way:

使用AsyncOptional可以用更直接的方式重写它:

Isn’t that more readable?

这不是更具可读性吗?

So, the AsyncOptional library could help you to:

因此, AsyncOptional库可以帮助您:

  • write code you may find more readable, maintainable, clean and nice-looking;

    编写代码,您可能会发现它们更具可读性,可维护性,简洁和美观;
  • avoid null-related TypeErrors better, thus increasing the stability of your system;

    更好地避免与null相关的TypeErrors ,从而提高系统的稳定性;

  • work with Promises and asynchronous functions in the same clean manner (and it works with synchronous ones too).

    以相同的干净方式使用Promises和异步功能(也可以使用同步功能)。

If you’ve liked the examples, please feel free to explore the Readme file in the GitHub repo or even check out the complete API Docs. I even dare to suggest you could install the package via npm. :) I would also appreciate any feedback.

如果您喜欢这些示例,请随时在GitHub存储库中浏览自述文件,甚至查看完整的API Docs 我什至不敢建议您可以通过npm安装该软件包 :)我也将不胜感激任何反馈。

async-optionalOptional implementation with async supportwww.npmjs.com

async-optional 带有异步支持的可选实现 www.npmjs.com

翻译自: https://www.freecodecamp.org/news/avoiding-null-check-pollution-in-javascript-4ed8e2702ce3/

optionals

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值