专栏首页技术小黑屋用好 Require,check,assert,写好 Kotlin 代码

用好 Require,check,assert,写好 Kotlin 代码

在编码的时候,我们需要做很多的检测判断,比如某个变量是否为null,某个成员属性是否为true,执行某个操作结果是否成功。比如像下面的这段代码

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

var isDiskMounted = true fun createNewFile(file: File?): Boolean { return if (isDiskMounted) { if (file != null) { file.createNewFile() if (file.exists()) { true } else { println("Create file($file) failed") false } } else { println("File($file) is null") false } } else { println("Disk is not mounted") false } }

上面的代码实现了

  • 检测磁盘是否挂载
  • 检测file参数是否为null
  • 检测执行操作结果是否成功(file.exists())

但是上面的代码也有一些问题

  • 太多的if else 检测,层级产生,不够平
  • 多个方法出口
  • 更不容易发现异常和错误(有点类似fail safe模式)

使用今天的知识点改造

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

fun createNewFileV2(file: File?): Boolean { check(isDiskMounted) { "Disk is not mounted" } requireNotNull(file) { "file is null" } file.createNewFile() assert(file.exists()) { "createNewFileV2 file($file) does not exist" } return true }

  • 方法体没有多余层级,比较平
  • 单个方法出口
  • 更快更早发现问题(有点类似fail fast)
  • file.createNewFile()执行时可以不需要再使用file?.createNewFile() 这一点是因为使用了Contract

require

  • require(boolean) 用来检测方法的参数,当参数boolean为false时,抛出IllegalArgumentException

示例代码

1 2 3 4 5 6 7 8 9 10 11 12

fun readFileContent(file: File?): String { //判断file不能为null requireNotNull(file) //判断文件必须可读,并提供错误的信息 require(file.canRead()) { "readFileContent file($file) is not readable" } //read file content return "Your file content" }

变种方法

  • fun require(value: Boolean)
  • fun require(value: Boolean, lazyMessage: () -> Any)
  • fun <T : Any> requireNotNull(value: T?)
  • fun <T : Any> requireNotNull(value: T?, lazyMessage: () -> Any)

check

  • check(boolean)用来检测对象的状态(属性),如果boolean为false,抛出异常IllegalStateException

示例代码

1 2 3 4 5 6 7 8 9 10 11 12 13

class Engine { var isStarted = false fun speedUp() { check(isStarted) { "Engine is not started, cannot be speed up now" } //speed up the engine } }

变种方法

  • fun check(value: Boolean, lazyMessage: () -> Any)
  • fun <T : Any> checkNotNull(value: T?)
  • fun <T : Any> checkNotNull(value: T?, lazyMessage: () -> Any)

assert

  • assert(boolean) 用来检测执行结果,当boolean为false时,抛出AssertionError。但是需要在开启对应的JVM选项时才生效。

示例代码

1 2 3 4 5 6 7 8

fun makeFile(path: String) { val file = File(path) file.createNewFile() assert(file.exists()) { "make File($file) failed" } }

使用顺序

  • 先使用check检测对象的状态
  • 再使用require检测方法的参数合法性
  • 执行操作后,使用assert校验结果

关于lazyMessage

崩溃更多了,怎么办

  • 是的,上面无论是require,check,assert都会在发现错误的时候抛出异常
  • 这是为了让问题更早发现,这就是它们的哲学
  • 如果想要考虑稳定的话,可以在业务侧 debug下崩溃,非debug下捕获吞掉异常

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

fun main() { createNewFile(null) safeRun { createNewFileV2(null) } } private val isDebug = true fun safeRun(block: () -> Unit) { try { block() } catch (t: Throwable) { t.printStackTrace() if (isDebug) { throw t } } }

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 31 天,从浅到深轻松学习 Kotlin

    Android 开发者
  • Dart 笔记 3 - 类型

    数字字面量是编译时常量。许多算术表达式也是编译时常量,只要它们的操作数是编译时常量,可以对数字求值。

    七适散人
  • 测试工具mocha用法小结

    这篇是前段时间总结给自己备忘的,要用到的工具实在太多,没法一一记住。 个人感觉,作为一个测试的工具,只要会用就好了。 所以这里稍微做了一些修改,简单介绍一下常用...

    IMWeb前端团队
  • should.js源码分析与学习

    为了研究与学习某些测试框架的工作原理,同时也为了完成培训中实现一个简单的测试框架的原因,我对should.js的代码进行了学习与分析,现在与大家来进行交流下。

    黄Java
  • 测试工具 mocha 用法小结

    这篇是前段时间总结给自己备忘的,要用到的工具实在太多,没法一一记住。个人感觉,作为一个测试的工具,只要会用就好了。所以这里稍微做了一些修改,简单介绍一下常用的写...

    腾讯IVWEB团队
  • 测试工具mocha用法小结

    所以这里稍微做了一些修改,简单介绍一下常用的写法和命令,其次将之前的一些示例改成javascript版本,方便没有coffee基础的同学浏览。

    IMWeb前端团队
  • 为 Kotlin 项目设置编译选项

    经常用终端的人都知道,终端命令有很多选项可以指定,这里我们以相关的kotlinc为例,我们可以在终端这样指定选项

    技术小黑屋
  • Apache Thrift-Node.js教程

    所有Apache Thrift教程都要求您具备: 1.Apache Thrift编译器和库,请参阅下载和从源代码构建以获取更多详细信息。 2.生成了tuto...

    ccf19881030
  • 区块链安全 | 修饰器(modifier)相关漏洞分析

    修饰器(modifier)可以改变函数的行为,例如作为前置的检测条件。同时修饰器具有可继承属性,可以由派生合约中的定义覆盖。本次BUGX.IO区块链安全课堂给大...

    FB客服

扫码关注云+社区

领取腾讯云代金券