kotlin 中的嵌套 let 块和验证
nested let blocks in kotlin and valiadation
我想用函数式方法处理验证。我有如下用户验证逻辑
- 如果用户对象为空则抛出异常
- 如果用户不活跃则抛出异常
- 如果用户类型是 super 什么也不做。如果用户类型是管理员做一些操作。
在我的代码片段中,如果生成的随机数是偶数,我将抛出异常,否则将完成流程。
* 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
,这是不正确的。它应该默默地完成功能 call.Any 一个帮助我代码有什么问题?
在内部区块
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")
您有一个非空值。
因为您没有链接 ?.
调用。更好的办法是尽早 return/throw.
val existing = user ?: throw IllegalStateException("user not created at all")
所以嵌套块可以被压平。
第二个异常 "User is not active right now" 发生在两个检查之一未满足时。
描述这种业务逻辑的编程概念不是可为空的变量。常规的旧 if
检查要干净得多。
if (existing.status != UserStatus.ACTIVE || existing.userType == UserType.SUPER) {
throw IllegalStateException("User is not active right now")
}
顺便说一句,您的错误消息似乎有误。
"functional approach",我想你的意思是让代码基于表达式。但是可空类型对于您的用例来说还不够强大。
您应该寻找 Either
或 Try
。它们都在 Arrow library 中可用。他们都是单子。它们的链接 (flatMap
),就像 ?.let
调用一样,也需要回调地狱。
在某些语言中,有语法糖来平息 flatMap
s 的回调地狱。你可以看看Monad Comprehensions,看看你是否喜欢。
如果没有,没问题。在 Kotlin 中,早 return/throw.
并不丢脸
务实。
我想用函数式方法处理验证。我有如下用户验证逻辑
- 如果用户对象为空则抛出异常
- 如果用户不活跃则抛出异常
- 如果用户类型是 super 什么也不做。如果用户类型是管理员做一些操作。
在我的代码片段中,如果生成的随机数是偶数,我将抛出异常,否则将完成流程。
* 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
,这是不正确的。它应该默默地完成功能 call.Any 一个帮助我代码有什么问题?
在内部区块
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")
您有一个非空值。
因为您没有链接 ?.
调用。更好的办法是尽早 return/throw.
val existing = user ?: throw IllegalStateException("user not created at all")
所以嵌套块可以被压平。
第二个异常 "User is not active right now" 发生在两个检查之一未满足时。
描述这种业务逻辑的编程概念不是可为空的变量。常规的旧 if
检查要干净得多。
if (existing.status != UserStatus.ACTIVE || existing.userType == UserType.SUPER) {
throw IllegalStateException("User is not active right now")
}
顺便说一句,您的错误消息似乎有误。
"functional approach",我想你的意思是让代码基于表达式。但是可空类型对于您的用例来说还不够强大。
您应该寻找 Either
或 Try
。它们都在 Arrow library 中可用。他们都是单子。它们的链接 (flatMap
),就像 ?.let
调用一样,也需要回调地狱。
在某些语言中,有语法糖来平息 flatMap
s 的回调地狱。你可以看看Monad Comprehensions,看看你是否喜欢。
如果没有,没问题。在 Kotlin 中,早 return/throw.
并不丢脸务实。