kotlin

名称

kotlin

分类

rules

路径

rules/kotlin.mdc

描述

Kotlin 开发约定和最佳实践

Kotlin 开发规范

基本原则

  • 优先使用类型推断,必要时显式声明类型提高可读性
  • 避免使用 Any,创建具体的类型定义
  • 优先使用 val 而非 var,保持不可变性
  • 使用 Kotlin 的空安全特性,避免显式 null 检查
  • 避免魔法数字,定义有意义的常量

命名规范

  • 类和接口:PascalCase (UserRepository, PaymentService)
  • 函数和变量:camelCase (getUserById, isValid)
  • 常量和枚举值:UPPER_SNAKE_CASE (MAX_RETRY_COUNT, DEFAULT_TIMEOUT)
  • 包名:全小写,使用点分隔 (com.example.userservice)
  • 文件名:PascalCase,与主要类名一致
  • 布尔变量:使用 ishascanshould 前缀 (isLoading, hasPermission, canDelete)
  • 使用完整单词而非缩写,确保拼写正确
    • 标准缩写除外:API、URL、HTTP、JSON 等
    • 常见缩写:id、ctx、req、res

函数设计

  • 编写简短且单一目的的函数(建议 ≤20 行)
  • 使用表达式函数简化单行返回:fun square(x: Int) = x * x
  • 函数名以动词开头,体现其行为
  • 优先使用高阶函数和扩展函数
  • 使用命名参数提高可读性:createUser(name = "John", age = 25)
  • 合理使用默认参数值,减少函数重载
  • 通过早期返回和提取工具函数避免深层嵌套
  • 使用单一抽象级别原则

类和数据结构

  • 数据类:用于纯数据承载,自动生成 equalshashCodetoString
  • 密封类:用于有限状态表示,替代枚举的复杂场景
  • 密封接口:Kotlin 1.5+ 用于更灵活的类型层次
  • 对象类:用于单例模式和工具类
  • 内联类:用于类型安全的原始类型包装
  • 优先使用组合而非继承
  • 遵循 SOLID 原则
  • 保持类的职责单一,避免过大的类(建议 ≤200 行,≤10 个公共方法)
  • 不要滥用原始类型,将相关数据封装在复合类型中

空安全和错误处理

  • 使用 ?. 安全调用操作符
  • 使用 ?: Elvis 操作符提供默认值
  • 使用 !! 操作符需要有充分理由并添加注释
  • 优先使用 Result 类型处理可能失败的操作
  • 对于异常情况使用具体的异常类型而非通用异常
  • 避免在函数中进行数据验证,使用具有内部验证的类型

协程和异步编程

  • 使用 suspend 函数处理异步操作
  • 在合适的作用域中启动协程 (viewModelScope, lifecycleScope, runBlocking)
  • 使用 Flow 处理数据流,StateFlow/SharedFlow 处理状态
  • 避免 GlobalScope,始终使用结构化并发
  • 合理使用协程上下文和调度器
  • 使用 async/await 进行并发操作
  • 正确处理协程取消和异常

集合和函数式编程

  • 优先使用不可变集合 (listOf, setOf, mapOf)
  • 使用函数式操作:mapfilterreducefold
  • 合理使用序列 (Sequence) 处理大数据集或链式操作
  • 使用作用域函数:letrunwithapplyalso
  • 使用 takeIftakeUnless 进行条件处理
  • 对简单 lambda 使用 it 参数,复杂情况使用命名参数

泛型和类型系统

  • 合理使用泛型约束和变型(inout
  • 使用 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 函数自动管理资源