“不健康”的代码到处都是Null检查!
作者 |James Hickey
译者 | 弯月,责编 | 郭芮
出品 | CSDN(ID:CSDNnews)
以下为译文:
你是否知道提出“null”这个概念的人声称这是他的“十亿美元错误!”
这个问题看似很简单,然而一旦你深入大型项目和代码库,就必然会发现有些代码中null的使用简直匪夷所思。
有时,我们希望使对象的属性为可选:
在TypeScript中,string类型的属性值可以为null。
但是,number属性居然也可以!
呃……
再举个例子
乍一看去,似乎并没有什么不妥。
但是,这可能会引发如下情况:
这段代码有什么问题?它会让你的代码(上述代码中的Product类)陷入不一致的状态。
系统中的Product没有id,这合理吗?应该不合理吧。
理想情况下,一旦创建Product,它就应该有id。
那么,在需要与Product打交道的其他地方会怎么样呢?
实际情况惨不忍睹:
真的有人写这样的代码?
有!
在介绍如何修改上述代码之前,首先让我们来看一看为什么这段代码不健康,然后再考虑“代码的味道”。
这段代码很糟糕吗?
这段代码非常难以阅读和理解。因此,在修改这段代码时很容易出bug。
应用中塞满这样的代码可不是什么好事,你也同意吧。尤其是当在应用程序的重要以及关键部分出现这样的代码!
关于TypeScript中的不可为null类型
有人可能会想到,TypeScript支持不可为null的类型。
你可以在编译选项中添加一个特殊的标志,该标志默认情况下会禁止给任何变量赋值null。
关于这个观点我还有几点想说:
我们大多数人都需要处理现有的代码库,如果想修复这些编译错误就需要付出大量的时间和精力。
如果不进行严格的测试且小心地避免作出任何假设,那么这些修改仍可能造成运行时错误。
本文中谈到的解决方案也同样适用于其他语言,即便这些语言可能没有这样的选项。
无论怎样,安全的做法还是更有针对性地改进代码。同样,这可以确保系统的行为不变,而且还可以避免在修改的时候引入大量风险。
一种解决方案:Null对象模式
空集合
想象一下,你在一家为处理法律案件编写软件的公司工作。
有一天,在开发某项功能时,你看到了如下代码:
记得我们应该谨慎使用null检查吗?如果代码的某个地方忘记了检查null数组,就会造成大问题。
Null对象模式可以帮助你:你可以创建一个代表“空”的对象或null对象。
修改代码
让我们来看看fetchCasesFromAPI()方法。我们可以使用这种模式,而且在JavaScript和TypeScript 中处理数组时,这种做法很普遍。
为了避免空数组/集合的值为null,我们将一个空数组赋给它。
这样一来,别处就不需要检查null了!
但是,整个legalCase怎么办呢?如果这个API返回null,该如何是好?
搞定!
现在我们可以确保每个使用该方法的人都无需再担心null检查了!
示例2
在C#、Java等其他语言中,由于强类型的规定,你不能将一个空数组(即[])赋给集合。
这时候,你可以使用Null对象模式:
对象又如何呢?
想象一下,你正在开发一款视频游戏,你在某些级别设定了大boss。
在检查该级别是否有大boss的时候,你可能会遇到如下代码:
我们可能会发现其他地方也有这类的null检查:
我们只需引入一个null对象,就可以省却这些所有的null检查。
首先,我们需要一个表示大boss的接口:
接下来,我们可以创建一个boss类:
然后,我们创建IBoss接口(代表一个“null” boss)的实现:
这个NullBoss会自动让玩家“通关”,所以我们就可以删除所有的null检查了!
在如下代码示例中,如果boss是NullBoss或Boss的实例,也不需要额外的检查。
如何保证代码的健康?可以参考《Refactoring TypeScript 》一书中的部分内容,这本书旨在通过易于入手且实用的工具,帮助开发人员更好地构建高质量的软件。
原文:https://dev.to/jamesmh/unhealthy-code-null-checks-everywhere-2720
本文为 CSDN 翻译,转载请注明来源出处。
【END】
热 文推 荐
华为发布麒麟 990 芯片;苹果召回部分电源插头转换器;KDevelop 5.4.2 发布 | 极客头条
领取专属 10元无门槛券
私享最新 技术干货