跳转至

Kotlin编码规范约定

根据产品中心实践过程中经验累积,结合官方公开规范整理出一套Kotlin编码规范,为后端开发人员提供规范与指引。

修订记录

版本号 制定团队 更新日期 备注
0.0.1.beta 产品中心 2020.1.18 修改
0.0.1 产品中心 2020.2.8 定稿

源代码组织

  • 【强制】kotlin源文件命名必须使用首字母大写的驼峰风格
  • 【强制】在实现一个接口时,实现成员的顺序应该与该接口的成员顺序相同
  • 【强制】在类中总是将重载放在一起
  • 【建议】避免在文件名中使用诸如“Util”之类的无意义词语
  • 【建议】在源文件保持合理大小条件下鼓励多个声明语义上彼此紧密关联(类、顶级函数或者属性)放在同一个 Kotlin 源文件中

命名规则

  • 【强制】包的名称总是小写且不使用下划线
  • 【强制】类与对象的名称以大写字母开头并使用驼峰风格
  • 【强制】函数、属性与局部变量的名称以小写字母开头、使用驼峰风格而不使用下划线,创建类实例的工厂函数除外,工厂函数可以与要创建的类具有相同的名称
  • 【强制】常量名称(标有const 的属性,或者保存不可变数据的没有自定义 get 函数的顶层/对象 val属性)应该使用大写、下划线分隔的名称
  • 【建议】不鼓励使用多个词的名称,但是如果确实需要使用多个词,可以将它们连接在一起或使用驼峰风格
  • 【建议】如果一个类有两个概念上相同的属性,一个是公共 API 的一部分,另一个是实现细节,那么使用下划线作为私有属性名称的前缀
  • 【建议】类的名称通常是用来解释类是什么的名词或者名词短语
  • 【建议】方法的名称通常是动词或动词短语,说明该方法做什么
  • 【建议】名称应该表明实体的目的是什么,所以最好避免在名称中使用无意义的单词
  • 【建议】当使用首字母缩写作为名称的一部分时,如果缩写由两个字母组成,就将其大写(IOStream);而如果缩写更长一些,就只大写其首字母(XmlFormatterHttpInputStream

格式化

  • 【强制】使用 4 个空格缩进。不要使用 tab
  • 【强制】绝不在 ([ 之后或者 ]) 之前留空格。
  • 【强制】绝不在. 或者 ?. 左右留空格:foo.bar().filter { it > 2 }.joinToString(), foo?.bar()
  • 【强制】不要在用于指定类型参数的尖括号前后留空格:class Map<K, V> { …… }
  • 【强制】不要在 :: 前后留空格:Foo::classString::length
  • 【强制】不要在用于标记可空类型的 ? 前留空格:String?
  • 【强制】当对链式调用换行时,将 . 字符或者 ?. 操作符放在下一行,并带有单倍缩进:
    val anchor = owner
        ?.firstChild!!
        .siblings(forward = true)
        .dropWhile { it is PsiComment || it is PsiWhiteSpace }
    
  • 【建议】对于花括号,将左花括号放在结构起始处的行尾,而将右花括号放在与左括结构横向对齐的单独一行
  • 【建议】在二元操作符左右留空格( a + b )
  • 【建议】不要在一元运算符左右留空格(a++)
  • 【建议】在控制流关键字(ifwhenfor 以及 while)与相应的左括号之间留空格
  • 【建议】在 // 之后留一个空格:// 这是一条注释

注释规范

  • 【强制】接口必须有注释
  • 【建议】对于较长的文档注释,将开头 /**放在一个独立行中,并且后续每行都以星号开头
    /**
     * 这是一条多行
     * 文档注释。
     */
    
  • 【建议】简短注释可以放在一行内:
    /** 这是一条简短文档注释。 */
    

语言特性惯用法

  • 【强制】优先使用不可变类型
  • 【强制】优先使用字符串模板而不是字符串拼接
  • 【强制】返回平台类型表达式的公有函数/方法必须显式声明其 Kotlin 类型
  • 【建议】如果函数返回 Unit,那么应该省略返回类型
  • 【建议】尽可能省略分号
  • 【建议】将简单变量传入到字符串模版中时不要使用花括号。只有用到更长表达式时才使用花括号

  • 【建议】优先声明带有默认参数的函数而不是声明重载函数

  • 【建议】如果有一个在代码库中多次用到的函数类型或者带有类型参数的类型,那么最好为它定义一个类型别名
  • 【建议】在简短、非嵌套的 lambda 表达式中建议使用 it 用法而不是显式声明参数。而在有参数的嵌套 lambda 表达式中,始终应该显式声明参数
  • 【建议】避免在 lambda 表达式中使用多个返回到标签。请考虑重新组织这样的 lambda 表达式使其只有单一退出点;如果这无法做到或者不够清晰,请考虑将 lambda 表达式转换为匿名函数
  • 【建议】二元条件优先使用if而不是when;如果有三个或多个选项时优先使用 when
  • 【建议】优先使用高阶函数(filtermap等)而不是循环
  • 【建议】在某些情况下,不带参数的函数可与只读属性互换,优先使用只读属性

项目代码准则

  • 【强制】kotlin的源码必须放置src/main/kotlin目录下
  • 【强制】所有项目代码顶级包为com.zxy.product
  • 【强制】必须使用dependencyManagement统一管理依赖版本
  • 【强制】协程API不能跟线程API混用
    `runBlocking { Thread.sleep(2000) }` // 反例
    `runBlocking { delay(2000) }` // 正例
    
  • 【强制】代码中sql参数不能使用拼接,应使用占位符
  • 【强制】事物应包裹在协程处理外层或者保证协程中不存在线程切换 协程中事物正常处理,协程存在线程切换,事物应包裹在协程处理外层
  • 【强制】缓存使用应该处理整个生命周期,处理缓存更新、缓存过期,避免脏读、永久缓存
  • 【建议】spring bean定义优先使用BeanDefinitionDsl
  • 【建议】采用扩展简写重复使用代码
    // 反例
    dictService.findPage(
            requestContext.getInteger("pageNum")!!,
            requestContext.getInteger("pageSize")!!,
            requestContext.getOptionalString("name").orElse(null)
    )
    
    // 正例
    inline fun <reified T> RequestContext.value(key: String): T? {
        return this.getOptional(key, T::class.java).orElse(null)
    }
    
    dictService.findPage(
            requestContext.value("pageNum")!!,
            requestContext.value("pageSize")!!,
            requestContext.value("name")
    )
    
  • 【建议】多行字符串处理尽量使用trimMargin去除空格