Kotlin 代码审查:检查要点与反馈技巧
代码审查是维护代码质量、促进团队知识共享和预防 Bug 最有效的工具之一。然而,仅仅"扫一眼"拉取请求是不够的。对于 Kotlin 语言而言,其拥有丰富的类型系统、协程和函数式编程能力,因此在审查时需要特别关注一些特定要点。本文将详细解析审查 Kotlin 代码时应重点关注的内容,以及如何提出有益而不冒犯的评审意见。
1. 建设性反馈的基本原则
在深入技术细节之前,先回顾几条能让代码审查对所有参与者都更有价值的规则。
关注代码本身,而非作者
不要说"你写了烂代码",而是说"这个方法可以用 let 来简化"。具体且中立的措辞能降低紧张情绪。
分类标注
将评审意见标注为:
- 阻塞性 — 必须修复(逻辑错误、资源泄漏)。
- 细节性 — 小问题(风格、格式)。
- 疑问性 — 需要澄清(意图不明确)。
解释"为什么"
仅说"使用 filterNotNull()"是不够的。请补充:"这样可以消除不必要的循环,让代码自文档化。"这样作者不仅会修改,还能学到知识。
2. 空安全与类型:Kotlin 的主要盟友
Kotlin 旨在编译时就避免空指针异常。检查是否破坏了这一保护机制。
避免不必要的 !!(非空断言)
!! 操作符是一个"求救信号"。它的使用应该是例外,而非常态。
// 糟糕:存在 NPE 风险fun process(user: User?) { val name = user!!.name}
// 良好:安全调用fun process(user: User?) { val name = user?.name ?: "Guest"}检查要点:如果看到 !!,请询问作者是否可以用 ?.let、?:(Elvis 操作符)或 requireNotNull() 来替代。
正确使用可空类型
并非所有参数都需要声明为可空。如果函数始终期望一个值,请声明不带问号的类型。
// 有争议:null 表示无意义fun log(message: String?) { println(message ?: "null")}
// 更好:明确要求fun log(message: String) { println(message)}3. 协程与线程:无痛的异步编程
Kotlin 协程是一个强大的工具,但也容易被误用。审查时请注意以下几点。
为任务选择正确的调度器
不要将长时间运行的操作(网络、磁盘)放在 Dispatchers.Main 上执行。
// 糟糕:阻塞 UIGlobalScope.launch(Dispatchers.Main) { val data = fetchFromNetwork() // 会挂起}
// 良好:切换上下文viewModelScope.launch { val data = withContext(Dispatchers.IO) { fetchFromNetwork() } updateUI(data)}协程泄漏与结构化并发
使用 viewModelScope、lifecycleScope 或 coroutineScope 代替 GlobalScope。后者与应用同生命周期,极易导致泄漏。
// 危险:会导致泄漏GlobalScope.launch { /* ... */ }
// 安全:与生命周期绑定lifecycleScope.launch { /* ... */ }4. 集合与函数式风格:简洁与可读性
Kotlin 提供了丰富的集合操作库。请使用它们,而不是显式的循环。
链式调用代替可变操作
避免手动向列表添加元素,应使用操作链来收集结果。