我从 1000 份代码审查中学到了什么

我看到有些建议不断重复出现,所以我决定整理一个清单,与诸位分享。

这是我的 3(额外 +1)个最常见的代码审查建议。

建议1:出错时抛出异常

我见过的一个常见模式是:

这种模式实际上导致了我做的移动应用程序崩溃,我们当时使用的搜索后端开始抛出异常。而应用程序的 API 服务器中也有一些类似的代码。从应用程序的角度来看,它成功获取了 200 个响应,只是每个搜索请求返回的是空列表。

如果当时 API 直接抛出异常,那么我们的监控系统就会立即检测到并修复它。

很多时候,当你捕获一个异常时,你会希望它返回一个空对象。Java 中的空对象包括 Optional.empty()、null 和空列表,而它们在 URL 解析中经常出现。如果 URL 不能从一个字符串中正确解析时,先不要返回 null,而是停下来问问自己:“为什么 URL 格式不正确?这不是我们应该在上游解决的数据问题吗?”

空对象不是解决此类问题的合适工具。如果有异常,你应该(及时)抛出它。

建议2:使用尽可能具体的类型

这个建议基本上与字符串类型编程相反。

我经常看到类似这样的代码:

尽可能具体的类型可以让你避免整个类的错误,这基本上是大家选择强类型语言(如 Java)的原因。

所以现在的问题是:那些想要写强类型语言的程序员,最终是怎么写出糟糕的字符串类型的代码哪?答案是:因为外部世界不是强类型的。字符串通常来自许多不同的地方,比如:

  • url 中的请求和路径参数
  • JSON
  • 不支持枚举的数据库
  • 写得很差的库

这些情况下,你应该使用以下策略来避免这个问题:将字符串解析和序列化保持到程序边缘。这是一个例子:

它带给我们许多好处:1、能够立刻发现格式不正确的数据;如果有任何问题,应用程序会提前显示并终止。2、一旦数据通过验证,你不必在整个应用程序中捕获解析异常。3、强类型使得签名具有更多信息,这样你就无需在每个方法上写 javadoc。

建议3:使用 Optionals 而不是 null

Optional(可选)类是 Java 8 中最好的特性之一,它表示一个可以合理存在或不存在的实体。

问题时间:唯一用缩写来指代的异常是什么?答:NPE (Null Pointer Exception,空指针异常)。这是迄今为止 Java 中最常见的异常,被称为十亿美元的错误

Optional 允许你从程序中完全删除 NPE。但是,你必须正确地使用它。这里有一些关于如何使用 Optional 的建议:

  • 你不应该在任何时候随意调用 .get(),而应仔细考虑 Optional 不存在的情况,并给出合理的默认值。
  • 如果你还没有一个合理的默认值,那么像 .map().flatMap() 这样的方法,可以让你晚点做这个决定。
  • 如果外部库返回 null 来表示空值,则立即使用 Optional.ofNullable() 以封装它。相信我,以后你会感谢自己的。在程序内部,null 有往上“冒泡”的倾向,所以还是最好从源头上阻止它们。
  • 在返回类型的方法中使用 Optional。这样做可以让你不用阅读 javadoc 就可以获知,值是否可能不存在。

额外建议:尽可能使用“Unlift”方法

你应该尽量避免类似的方法:

所有要避免的方法有什么共同点?他们都使用容器对象,比如 Optional,List 或 Task 作为方法的参数。当返回类型是同一类型的容器(即,一个参数的方法采用 Optional 并返回一个 Optional),情况会变得更糟糕。

为什么?

相比 ① Promise<A> method(Promise<B> param),② A method(B param) 更具有灵活性。

如果你有 Promise<B>,那么你可以使用 ①,也可以通过  .map 函数“提升(lifting)” (比如 promise.map(method))来使用 ②.

但是,如果你只有 B,那么你可以很容易地使用 ②,却不能使用 ①,很明显,② 是一个更灵活的选择。

我喜欢称之为“Unlift”,因为它与普通函数的实用方法“Lift”恰好相反。应用这些重写能使方法更灵活,调用更轻松。

1 收藏 评论

关于作者:飞哥的咖啡

I'm OUT, never IN. 个人主页 · 我的文章 · 50 ·  

相关文章

可能感兴趣的话题



直接登录
跳到底部
返回顶部