Kotlin 开发规范
基本原则
- 优先使用类型推断,必要时显式声明类型提高可读性
- 避免使用
Any,创建具体的类型定义
- 优先使用
val 而非 var,保持不可变性
- 使用 Kotlin 的空安全特性,避免显式 null 检查
- 避免魔法数字,定义有意义的常量
命名规范
- 类和接口:PascalCase (
UserRepository, PaymentService)
- 函数和变量:camelCase (
getUserById, isValid)
- 常量和枚举值:UPPER_SNAKE_CASE (
MAX_RETRY_COUNT, DEFAULT_TIMEOUT)
- 包名:全小写,使用点分隔 (
com.example.userservice)
- 文件名:PascalCase,与主要类名一致
- 布尔变量:使用
is、has、can、should 前缀 (isLoading, hasPermission, canDelete)
- 使用完整单词而非缩写,确保拼写正确
- 标准缩写除外:API、URL、HTTP、JSON 等
- 常见缩写:id、ctx、req、res
函数设计
- 编写简短且单一目的的函数(建议 ≤20 行)
- 使用表达式函数简化单行返回:
fun square(x: Int) = x * x
- 函数名以动词开头,体现其行为
- 优先使用高阶函数和扩展函数
- 使用命名参数提高可读性:
createUser(name = "John", age = 25)
- 合理使用默认参数值,减少函数重载
- 通过早期返回和提取工具函数避免深层嵌套
- 使用单一抽象级别原则
类和数据结构
- 数据类:用于纯数据承载,自动生成
equals、hashCode、toString
- 密封类:用于有限状态表示,替代枚举的复杂场景
- 密封接口:Kotlin 1.5+ 用于更灵活的类型层次
- 对象类:用于单例模式和工具类
- 内联类:用于类型安全的原始类型包装
- 优先使用组合而非继承
- 遵循 SOLID 原则
- 保持类的职责单一,避免过大的类(建议 ≤200 行,≤10 个公共方法)
- 不要滥用原始类型,将相关数据封装在复合类型中
空安全和错误处理
- 使用
?. 安全调用操作符
- 使用
?: Elvis 操作符提供默认值
- 使用
!! 操作符需要有充分理由并添加注释
- 优先使用
Result 类型处理可能失败的操作
- 对于异常情况使用具体的异常类型而非通用异常
- 避免在函数中进行数据验证,使用具有内部验证的类型
协程和异步编程
- 使用
suspend 函数处理异步操作
- 在合适的作用域中启动协程 (
viewModelScope, lifecycleScope, runBlocking)
- 使用
Flow 处理数据流,StateFlow/SharedFlow 处理状态
- 避免
GlobalScope,始终使用结构化并发
- 合理使用协程上下文和调度器
- 使用
async/await 进行并发操作
- 正确处理协程取消和异常
集合和函数式编程
- 优先使用不可变集合 (
listOf, setOf, mapOf)
- 使用函数式操作:
map、filter、reduce、fold
- 合理使用序列 (
Sequence) 处理大数据集或链式操作
- 使用作用域函数:
let、run、with、apply、also
- 使用
takeIf、takeUnless 进行条件处理
- 对简单 lambda 使用
it 参数,复杂情况使用命名参数
泛型和类型系统
- 合理使用泛型约束和变型(
in、out)
- 使用
reified 参数访问泛型类型信息
- 利用类型别名提高代码可读性:
typealias UserId = String
- 使用内联函数优化高阶函数性能
可见性和封装
- 使用最小必要的可见性修饰符
- 优先使用
internal 而非 public 用于模块内部 API
- 使用
private 限制类内部实现细节
- 合理使用
protected 用于继承场景
测试规范
- 测试方法使用描述性命名:
should_return_user_when_valid_id_provided
- 遵循 Arrange-Act-Assert 模式
- 清楚命名测试变量:
given...、when...、then... 或 input...、expected...、actual...
- 为每个公共函数编写单元测试
- 使用测试替身(Mock、Stub)模拟依赖
- 为每个模块编写集成测试
- 遵循 Given-When-Then 约定编写行为测试
代码组织和架构
- 按功能而非类型组织包结构
- 将相关的类放在同一文件中(如密封类的子类)
- 合理使用扩展函数增强现有类型
- 声明接口定义契约,面向接口编程
- 使用依赖注入提高代码可测试性
- 遵循领域驱动设计原则
性能和资源管理
- 使用
inline 关键字优化高阶函数
- 合理使用
lazy 延迟初始化
- 注意避免内存泄漏,特别是在协程和回调中
- 使用
use 函数自动管理资源