编码规范

Kotlin 官方编码规范强调一致性、可读性和工具友好性。团队项目中,编码规范的价值不只是“好看”,更重要的是减少无意义争论,让代码审查集中在行为和设计上。

文件与包

包名使用小写:

package com.example.user

文件名通常与主要声明一致:

UserService.kt
UserRepository.kt

如果文件包含多个紧密相关的顶层声明,可以使用主题名:

UserExtensions.kt

类和接口命名

类、接口、对象使用 PascalCase:

class UserService
interface UserRepository
object AppConfig

函数和属性使用 camelCase:

fun loadUsers()
val userName: String

常量使用大写下划线:

const val MAX_RETRY_COUNT = 3

格式化

使用 4 个空格缩进,不使用 Tab。

函数参数较多时换行:

fun createUser(
    name: String,
    email: String,
    active: Boolean = true
): User {
    return User(name, email, active)
}

链式调用换行:

val activeNames = users
    .filter { it.active }
    .map { it.name }
    .sorted()

类布局建议

类内部通常按以下顺序组织:

  1. 属性。
  2. 初始化块和构造相关逻辑。
  3. 公共函数。
  4. 私有辅助函数。
  5. 伴生对象。

示例:

class UserService(
    private val repository: UserRepository
) {
    val activeUserCount: Int
        get() = repository.countActiveUsers()

    fun findActiveUsers(): List<User> {
        return repository.findAll().filter { it.active }
    }

    private fun normalizeName(name: String): String {
        return name.trim()
    }
}

团队可以有自己的顺序,但要保持一致。

表达式风格

简单函数可以使用表达式函数体:

fun isAdult(age: Int) = age >= 18

逻辑复杂时使用块函数体:

fun register(command: RegisterCommand): User {
    require(command.email.isNotBlank())
    val user = command.toUser()
    return repository.save(user)
}

不要为了追求短而牺牲可读性。

空安全风格

优先使用明确的空值处理:

val email = user.email ?: return
sendEmail(email)

避免无解释地使用 !!

// 不推荐
sendEmail(user.email!!)

如果业务上必须非空,抛出带上下文的异常:

val email = user.email
    ?: error("用户 ${user.id} 缺少邮箱")

Lambda 风格

简单场景可用 it

users.filter { it.active }

复杂场景命名参数:

users.filter { user ->
    user.active && user.email.isNotBlank()
}

嵌套 Lambda 中不要同时依赖多个 it,可读性会迅速下降。

扩展函数风格

扩展函数应该放在与领域相关的位置,而不是堆进全局工具文件。

推荐:

fun User.displayName(): String =
    name.takeIf { it.isNotBlank() } ?: "匿名用户"

不推荐把复杂业务流程伪装成普通属性或扩展:

// 不推荐:看起来像轻量转换,实际可能包含远程请求
fun User.loadPermissionsFromRemote(): List<Permission>

扩展函数应当让调用更自然,而不是隐藏依赖和副作用。

Java 互操作命名

如果 Kotlin API 会被 Java 调用,考虑:

  • 默认参数是否需要 @JvmOverloads
  • 伴生对象方法是否需要 @JvmStatic
  • 顶层函数在 Java 中生成的类名是否需要 @file:JvmName
  • 属性暴露到 Java 后 getter/setter 名称是否符合预期。

Kotlin 内部写法优雅,不代表 Java 调用方也会优雅。公共库需要同时检查两边 API。

实践建议

  • 使用 IDE 官方格式化,不要手动争论缩进和换行。
  • 代码审查重点放在语义、边界和可维护性上。
  • 简洁不是越短越好,尤其不要滥用作用域函数和隐式 it
  • 对外 API 显式写返回类型,避免实现变化影响调用方理解。
  • Java/Kotlin 混合项目要同时关注 Kotlin 风格和 Java 调用体验。

参考

  • 官方编码规范:https://kotlinlang.org/docs/coding-conventions.html