【问题标题】:nested let blocks in kotlin and valiadationkotlin 和验证中的嵌套 let 块
【发布时间】:2023-03-21 08:01:01
【问题描述】:

我想以功能方法处理验证。我有如下的用户验证逻辑

  1. 如果用户对象为空,则抛出异常
  2. 如果用户不活跃,则抛出异常
  3. 如果用户类型是 super 什么都不做。如果用户类型是 admin 做一些操作。

在我的代码 sn-p 中,如果生成的随机数是偶数,则抛出异常,否则完成流程。

 * 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,这是不正确的。它应该默默地完成函数调用。任何人帮助我代码有什么问题?

【问题讨论】:

  • 代码中没有任何内容表明“用户处于非活动状态”。您指的是“订阅”吗?
  • 是的.. 更新了代码以反映正确的代码。
  • 你能把代码放在问题中而不是第 3 方网站吗?
  • 完成..更新代码
  • 请使用适当的缩进,以便我们遵循代码结构。

标签: kotlin scope functional-programming let


【解决方案1】:

在内部块中

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")
}

顺便说一句,您的错误消息似乎是错误的。


通过“功能方法”,我认为您的意思是基于代码表达式。但是可空类型对于您的用例来说还不够强大。 您应该寻找EitherTry。它们都可以在Arrow library 中找到。它们都是单子。它们的链接 (flatMap),就像 ?.let 调用一样,也需要回调地狱。

在某些语言中,有句法糖可以使flatMaps 的回调地狱变平。你可以看看Monad Comprehensions,看看你喜不喜欢。

如果没有,没问题。在 Kotlin 中,提前返回/抛出没有任何羞耻感。

务实。

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 2018-08-11
    • 2016-08-15
    • 2019-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    相关资源
    最近更新 更多