kotlin - kotlin 和验证中的嵌套 let 块
问题描述
我想以功能方法处理验证。我有如下的用户验证逻辑
- 如果用户对象为空,则抛出异常
- 如果用户不活跃,则抛出异常
- 如果用户类型是 super 什么都不做。如果用户类型是 admin 做一些操作。
在我的代码片段中,如果生成的随机数是偶数,我将抛出异常,否则完成流程。
* You can edit, run, and share this code.
* play.kotlinlang.org
*/
import java.time.Instant
import java.util.UUID
import java.lang.IllegalStateException
import java.util.Random
fun main() {
val user : User? = User(UUID.randomUUID(),Instant.now(),UserStatus.ACTIVE,UserType.SUPER)
//val user : User? = User(UUID.randomUUID(),Instant.now(),UserStatus.ACTIVE,UserType.NORMAL) // works fine
user?.let{ existing -> existing.takeIf{it.status == UserStatus.ACTIVE}?.let{ activeUser ->
activeUser.takeUnless{ user -> user.userType == UserType.SUPER}?.let{
val number = Random().nextInt(5);
println(number)
if(number %2 == 0) throw IllegalStateException("invalid random number")
}
}?: throw IllegalStateException("User is not active right now")
} ?:throw IllegalStateException("user not created at all")
}
data class User(val uuid:UUID, val created:Instant, val status:UserStatus, val userType:UserType)
enum class UserStatus {
ACTIVE,INACTIVE
}
enum class UserType{
SUPER,NORMAL
}
user is not active right now
当生成的随机数是奇数时,它会抛出不正确的错误消息。它应该默默地完成函数调用。任何人帮助我代码有什么问题?
解决方案
在内部块
existing.takeIf { it.status == UserStatus.ACTIVE }?.let { activeUser ->
activeUser.takeUnless { user -> user.userType == UserType.SUPER }?.let {
val number = Random().nextInt(5);
println(number)
if (number % 2 == 0) throw IllegalStateException("invalid random number")
}
} ?: throw IllegalStateException("User is not active right now")
你有一个非空值。
因为你没有链接?.
电话。更好的主意是尽早返回/投掷。
val existing = user ?: throw IllegalStateException("user not created at all")
所以嵌套块可以展平。
当两项检查之一未得到满足时,会发生第二个异常“用户现在不处于活动状态”。描述这种业务逻辑的编程概念是不可为空的变量。定期的旧if
支票更清洁。
if (existing.status != UserStatus.ACTIVE || existing.userType == UserType.SUPER) {
throw IllegalStateException("User is not active right now")
}
顺便说一句,您的错误消息似乎是错误的。
通过“功能方法”,我认为您的意思是基于代码表达式。但是可空类型对于您的用例来说还不够强大。您应该寻找Either
或Try
。两者都可以在Arrow 库中找到。它们都是单子。它们的链接 ( flatMap
) 和?.let
调用一样,也需要回调地狱。
在某些语言中,有语法糖可以使flatMap
s 的回调地狱变平。你可以看看Monad Comprehensions,看看你是否喜欢。
如果没有,没问题。在 Kotlin 中,提前返回/抛出没有任何羞耻感。
务实。
推荐阅读
- java - Intelij 用新名称创建新包
- amazon-web-services - 从 Google Scripts 到 AWS Lambda 的 POST 请求以 null 的形式通过
- azure-active-directory - 开发和测试 Live Active Directory B2C 租户的更新
- django - Celery beat 卡在“写条目……”。芹菜工人工作正常
- rust - 如何为外部类型实现 serde 的反序列化和序列化?
- html - 为什么我的部分元素没有显示为正文的一部分?
- mongodb - Mongodb:$四舍五入十进制
- typescript - 'IntrinsicAttributes & Props & { children?: ReactNode; 类型上不存在属性 'customerCode' }'
- mongodb - 在查找查询中引用自己的项目字段
- objective-c - 我应该为自己的网络浏览器使用哪个用户代理?