极客视点
极客时间编辑部
极客时间编辑部
113243 人已学习
免费领取
课程目录
已完结/共 3766 讲
2020年09月 (90讲)
时长 05:33
2020年08月 (93讲)
2020年07月 (93讲)
时长 05:51
2020年06月 (90讲)
2020年05月 (93讲)
2020年04月 (90讲)
2020年03月 (92讲)
时长 04:14
2020年02月 (87讲)
2020年01月 (91讲)
时长 00:00
2019年12月 (93讲)
2019年11月 (89讲)
2019年10月 (92讲)
2019年09月 (90讲)
时长 00:00
2019年08月 (91讲)
2019年07月 (92讲)
时长 03:45
2019年06月 (90讲)
2019年05月 (99讲)
2019年04月 (114讲)
2019年03月 (122讲)
2019年02月 (102讲)
2019年01月 (104讲)
2018年12月 (98讲)
2018年11月 (105讲)
时长 01:23
2018年10月 (123讲)
时长 02:06
2018年09月 (119讲)
2018年08月 (123讲)
2018年07月 (124讲)
2018年06月 (119讲)
时长 02:11
2018年05月 (124讲)
时长 03:16
2018年04月 (120讲)
2018年03月 (124讲)
2018年02月 (112讲)
2018年01月 (124讲)
时长 02:30
时长 02:34
2017年12月 (124讲)
时长 03:09
2017年11月 (120讲)
2017年10月 (86讲)
时长 03:18
时长 03:31
时长 04:25
极客视点
15
15
1.0x
00:00/04:26
登录|注册

做了1000次Code Review,我学到3点经验

讲述:丁婵大小:6.09M时长:04:26
近日,开发人员史蒂芬·海黛尔(Steven Heidel)发文称,其在 LinkedIn 工作时,工作的很大一部分内容是做 Code Review。于是他将一些人很容易出现的错误总结起来,供开发者参考。以下为原文内容。

经验一:当出现错误时 Throw an exception

我看到的一个常见模式是:
List<String> getSearchResults(...) {
try {
List<String> results = // make REST call to search service
return results;
} catch (RemoteInvocationException e) {
return Collections.emptyList();
}
}
这可能是很多新手工程师的做法,但这种模式会有问题。在我曾经参与的移动应用项目中,这种模式导致了移动应用程序的故障。用户搜索开始后,我们的后端发生错误开始 throwing exceptions,但在应用程序的 API server 中并沒有 throwing exceptions。
因此,从应用角度看,前端会收到 200 个成功的响应,然后显示空白的搜索结果给使用者,而团队却毫不知情。
如果 API thrown an exception,那我们的监控系统会立刻发现它,并能及时修复。
很多时候,当捕捉到异常后,我们倾向于返回 empty object。Java 中 empty object 的样例包括 Optional.empty()、null 和 empty list。这种情况经常发生在 URL 解析中。如果 URL 无法从字符串解析得到的话,不要返回 null,而要问问自己:URL 格式为什么是不合法的?这是一个需要在 upstream 解决的数据问题吗?
对于这种任务来说,empty object 并不是恰当的工具。如果出现异常行为,那么就应该 throw an exception。

经验二:尽可能使用最具体的类型(type)

我经常看到下面所示的代码:
void doOperation(String opType, Data data);
// where opType is "insert", "append", or "delete", this should have clearly been an enum
String fetchWebsite(String url);
// where url is "https://google.com", this should have been an URN
String parseId(Input input);
// the return type is String but ids are actually Longs like "6345789"
用最具体的类型 (type)可避免很多 Bug。现在问题是:好心的程序员为什么会写出糟糕的 stringly typed 代码?
答案在于外部世界不是强类型的。字符串有很多不同的来源,比如:
URL 中的查询和路径参数
JSON
不支持枚举的数据库
编写糟糕的库
在上述场景中,我们应使用如下策略来避免该问题:将字符串解析和序列化放在程序的边缘处。比如下面这段代码:
// Step 1: Take a query param representing a company name / member id pair and parse it
// example: context=Pair(linkedin,456)
Pair<String, Long> companyMember = parseQueryParam("context");
// this should throw an exception if malformed
// Step 2: Do all the stuff in your application
// MOST if not all of your code should live in this area
// Step 3: Convert the parameter back into a String at the very end if necessary
String redirectLink = serializeQueryParam("context");
这种方式有很多优点,能立即发现格式错误的数据,如果出现任何问题,应用程序将提前 fails。数据被验证一次后,不必在整个应用程序中继续捕获解析异常。此外,强类型使方法签名更具描述性,我们不再需要在每个方法上编写那么多的 JavaDocs。

经验三:用 Optionals 而非 nulls

Java 8 最棒的特性之一是 Optional 类,它代表一个可能存在也可能不存在的实体。
Java 中最常见的异常是 NPE,Optional 能让我们完全从程序中移除 NPE。但是,必须以正确的方式使用它。如下是关于使用 Optional 的一些建议:
我们不能在得到 Optional 的任何时候都简单地调用它的.get(),相反,我们要仔细考虑 Optional 不存在的情况并给出一个合理的默认值;
如果还没有合理的默认值,那么像.map() 和.flatmap() 这样的方法允许我们推迟到以后再做决定;
如果外部库返回 null 来表示为空的情况,那么立即使用 Optional.ofNullable()wrap 该值。null 值在程序内部有“bubble up”的倾向,所以最好在源代码中停止它们;
在方法的返回类型中使用 Optional。这种做法非常好,因为我们不需要读取 JavaDoc 来确定值是否可能不存在。
最后,还有一个额外建议:尽可能采用“Unlift”方法。因为它与常见的函数式工具方法“lift”恰好相反。采用这种方式进行重写会让方法更具灵活性,对调用者更加易用。
以上就是今天的内容,希望对你有所帮助。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
该免费文章来自《极客视点》,如需阅读全部文章,
请先领取课程
免费领取
登录 后留言

全部留言(1)

  • 最新
  • 精选
  • caozhao
    好经典的错误
收起评论
大纲
固定大纲
经验一:当出现错误时 Throw an exception
经验二:尽可能使用最具体的类型(type)
经验三:用 Optionals 而非 nulls
显示
设置
留言
1
收藏
75
沉浸
阅读
分享
手机端
快捷键
回顶部