首页 存档 技术 查看内容

被NULL虐过的程序员一定要看看

2018-3-30 13:00 |来自: 互联网 496 0

摘要: (点击上方公号,可快速关注) 【2015-10-31 更新】补充插播一个改自 StackOverflow 帖子的段子: 杯具啊!我们公司有个职工姓 Null,当用他的姓氏做查询词时,把所有员工查询应用给弄崩溃了! 我该肿么办? ----- ...

(点击上方公号,可快速关注)


【2015-10-31 更新】补充插播一个改自 StackOverflow 帖子的段子:

杯具啊!我们公司有个职工姓 Null,当用他的姓氏做查询词时,把所有员工查询应用给弄崩溃了! 我该肿么办?


----------【分隔线】----------


在1965 年有人提出了这个计算机科学中最糟糕的错误,该错误比Windows 的反斜线更加丑陋、比 === 更加怪异、比PHP 更加常见、比CORS 更加不幸、比Java 泛型更加令人失望、比XMLHttpRequest 更加反复无常、比C 预处理器更加难以理解、比MongoDB 更加容易出现碎片问题、比UTF-16 更加令人遗憾。


“我把 Null 引用称为自己的十亿美元错误。它的发明是在1965 年,那时我用一个面向对象语言( ALGOL W )设计了第一个全面的引用类型系统。我的目的是确保所有引用的使用都是绝对安全的,编译器会自动进行检查。但是我未能抵御住诱惑,加入了Null引用,仅仅是因为实现起来非常容易。它导致了数不清的错误、漏洞和系统崩溃,可能在之后 40 年中造成了十亿美元的损失。近年来,大家开始使用各种程序分析程序,比如微软的 PREfix 和 PREfast 来检查引用,如果存在为非 Null 的风险时就提出警告。更新的程序设计语言比如 Spec# 已经引入了非 Null 引用的声明。这正是我在1965年拒绝的解决方案。” 《Null References: The Billion Dollar Mistake》托尼霍尔(Tony Hoare),图灵奖得主



为纪念 Hoare 先生的 null 错误五十周年,这篇文章将会解释何为 null、为什么它这么可怕以及如何避免。


NULL 怎么了?


简单来说:NULL 是一个不是值的值。那么问题来了。


这个问题已经在有史以来最流行的语言中恶化,而它现在有很多名字:NULL、nil、null、None、Nothing、Nil 和 nullptr。每种语言都有自己的细微差别。


NULL 导致的问题,有一些只涉及某种特定的语言,而另一些则是普遍存在的;少量只是某个问题的不同方面。


NULL…


  1. 颠覆类型

  2. 是凌乱的

  3. 是一个特例

  4. 使 API 变得糟糕

  5. 使错误的语言决策更加恶化

  6. 难以调试

  7. 是不可组合的


1. NULL 颠覆类型


静态类型语言不需要实际去执行程序,就可以检查程序中类型的使用,并且提供一定的程序行为保证。


例如,在 Java 中,如果我编写 x.toUppercase(),编译器会检查 x 的类型。如果 x 是一个 String,那么类型检查成功;如果 x 是一个 Socket,那么类型检查失败。


在编写庞大的、复杂的软件时,静态类型检查是一个强大的工具。但是对于 Java,这些很棒的编译时检查存在一个致命缺陷:任何引用都可以是 null,而调用一个 null 对象的方法会产生一个 NullPointerException。所以,


  • toUppercase() 可以被任意 String 对象调用。除非 String 是 null。

  • read() 可以被任意 InputStream 对象调用。除非 InputStream 是 null。

  • toString() 可以被任意 Object 对象调用。除非 Object 是 null。


Java 不是唯一引起这个问题的语言;很多其它的类型系统也有同样的缺点,当然包括 AGOL W 语言。


在这些语言中,NULL 超出了类型检查的范围。它悄悄地越过类型检查,等待运行时,最后一下子释放出一大批错误。NULL 什么也不是,同时又什么都是。


2. NULL 是凌乱的


在很多情况下 null 是没有意义的。不幸的是,如果一种语言允许任何东西为 null,好吧,那么任何东西都可以是 null。


Java 程序员冒着患腕管综合症的风险写下


if (str == null || str.equals("")) {

}


而在 C# 中添加 String.IsNullOrEmpty 是一个常见的语法


if (string.IsNullOrEmpty(str)) {

}


真可恶!


每次你写代码,将 null 字符串和空字符串混为一谈时,Guava 团队都要哭了。 Google Guava


说得好。但是当你的类型系统(例如,Java 或者 C#)到处都允许 NULL 时,你就不能可靠地排除 NULL 的可能性,并且不可避免的会在某个地方混淆。


null 无处不在的可能性造成了这样一个问题,Java 8 添加了 @NonNull 标注,尝试着在它的类型系统中以追溯方式解决这个缺陷。


3. NULL 是一个特例


考虑到 NULL 不是一个值却又起到一个值的作用,NULL 自然地成为各种特别处理方法的课题。


指针


例如,请看下面的 C 代码:


char c = 'A';

char *myChar =

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部