将多种方法合二为一的功能方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将多种方法合二为一的功能方法相关的知识,希望对你有一定的参考价值。

我是功能世界风格编程的新手我在Kotlin尝试了一些代码,下面的代码片段就是我所做的,但看起来对我来说势不可挡

@EmailTemplate("onCallTemplate")
fun retrieveNextOnCallCreateMailRecipientAndSendMail(time: LocalDateTime, trial: Boolean = true) {

    val emailTemplateID =
            extractEmailTemplateValue(
                    "retrieveNextOnCallAndSendMail")

    val messageTemplate = emailTemplateID?.let { messageTemplateAccessPoint.findByID(it) }


    val lisOfOnCalls = dataHubCommunicator
            .listOfOnCallToSendNotificationFromDataHub(time)

    val listOfMailRecipient = lisOfOnCalls
            ?.let { onCallListToMailRecipient.buildMailRecipientFromOnCalls(it) }


    listOfMailRecipient
            ?.let {
                messageTemplate
                        ?.let { it1 ->
                            emailSender
                                    .sendNotificationToOnCallPersons(it, it1, trial)
                        }
            }

    log.info("Message Has been sent Successfully")

}

此函数的作用类似于它检索的聚合器,并从其他函数调用相应的值/状态。我不喜欢这个方法是在任何地方声明变量(val / var)来存储值以传递给其他方法。

为了便于阅读,我不能这样做

onCallListToMailRecipient.buildMailRecipientFromOnCalls(dataHubCommunicator
    .listOfOnCallToSendNotificationFromDataHub(time))

是否有任何声明方式来编写此方法。我可以做些什么更改以使其更具声明性/功能性。

答案

您可以合并一些计算并减少本地变量的数量。此外,两个let的最后一个序列是相当无用的,只需使用您的局部变量调用该函数。我添加了一些null检查。

val messageTemplate = extractEmailTemplateValue("retrieveNextOnCallAndSendMail")?.let {
    messageTemplateAccessPoint.findByID(it) 
} ?: throw IllegalStateException (“Todo”)

val listOfMailRecipient = dataHubCommunicator.listOfOnCallToSendNotificationFromDataHub(time)?.let { 
    onCallListToMailRecipient.buildMailRecipientFromOnCalls(it) 
} ?: throw IllegalStateException (“Todo”)

emailSender
    .sendNotificationToOnCallPersons(listOfMailRecipient, messageTemplate, trial).also{
    println("Message Has been sent Successfully")
}
另一答案

你可以尝试这样的事情

fun retrieveNextOnCallCreateMailRecipientAndSendMail(time: LocalDateTime, trial: Boolean = true) {
    doWithListOfMail(time) { l ->
        doWithTemplate('retrieveNextOnCallAndSendMail') { t ->
            emailSender.sendNotificationToOnCallPersons(l, t, trial)
        }
    }
    log.info("Message Has been sent Successfully")
}
fun doWithTemplate(id: String, action: (Template) -> Void){
    val emailTemplateID = extractEmailTemplateValue(id)
    val messageTemplate = emailTemplateID?.let { 
        messageTemplateAccessPoint.findByID(it) 
    }
    messageTemplate?.let(action)    
}
fun doWithListOfMail(time : LocalDateTime, action: (List) -> Void) {
    val lisOfOnCalls = dataHubCommunicator
        .listOfOnCallToSendNotificationFromDataHub(time)
    val listOfMailRecipient = lisOfOnCalls?.let {
        onCallListToMailRecipient.buildMailRecipientFromOnCalls(it) 
    }
    listOfMailRecipient?.let(action)
}
另一答案

当它们仅在下一个语句中使用时,您可以省略val临时变量,而是在每个连续的行上使用let。应用该经验法则,您的示例可能如下所示:

val messageTemplate = extractEmailTemplateValue("retrieveNextOnCallAndSendMail")
    ?.let(messageTemplateAccessPoint::findByID)

dataHubCommunicator.listOfOnCallToSendNotificationFromDataHub(time)
    ?.let(onCallListToMailRecipient::buildMailRecipientFromOnCalls)
    ?.let {
        messageTemplate?.let {
            emailSender.sendNotificationToOnCallPersons(it, messageTemplate, trial)
        }
    }

它可能不是更具可读性,但它不那么笨重。

另一答案

事情可能取决于其中一些的无效,如果你喜欢let家族,你也可以这样做:

fun retrieveNextOnCallCreateMailRecipientAndSendMail(time: LocalDateTime, trial: Boolean = true) =
    dataHubCommunicator
        .listOfOnCallToSendNotificationFromDataHub(time)
        .let {
            onCallListToMailRecipient.buildMailRecipientFromOnCalls(it)
        }
        .apply {
            val template = messageTemplateAccessPoint.findByID(
                    extractEmailTemplateValue("retrieveNextOnCallAndSendMail"))

            emailSender.sendNotificationToOnCallPersons(this, template, trial)
        }
        .also {
            log.info("Message has been sent successfully to ${it}")
        }
        // if you have nullable recipient and want to detect failure
        // ?: log.info("Message not sent")

注意:块中的新行有助于IDEA显示提示,因此您可以获得自动变量+一些免费类型信息:IDEA hints

注意:总的来说,我会遏制?.,那里的一切真的可以作为空吗?如果我们需要指定it1来区分it,因为嵌套也可以利用这个机会很好地命名变量。

用于类型安全测试的声明存根的附录(我假设非空,但可以在任何地方添加问号):

interface OnCall
interface MessageTemplate
interface MessageTemplateID
interface MailRecipient
interface MessageTemplateAccessPoint {
    fun findByID(it: MessageTemplateID): MessageTemplate
}

interface DataHubCommunicator {
    fun listOfOnCallToSendNotificationFromDataHub(time: LocalDateTime): List<OnCall>
}

interface OnCallListToMailRecipient {
    fun buildMailRecipientFromOnCalls(oncalls: List<OnCall>): MailRecipient
}

interface EmailSender {
    fun sendNotificationToOnCallPersons(recipient: MailRecipient, template: MessageTemplate, trial: Boolean)
}

fun extractEmailTemplateValue(name: String): MessageTemplateID = TODO()

val dataHubCommunicator: DataHubCommunicator = TODO()
val messageTemplateAccessPoint: MessageTemplateAccessPoint = TODO()
val onCallListToMailRecipient: OnCallListToMailRecipient = TODO()
val emailSender: EmailSender = TODO()

以上是关于将多种方法合二为一的功能方法的主要内容,如果未能解决你的问题,请参考以下文章

如何使用行号将多条记录合并为一条?

C# 使用 WebBrowser 实现 HTML 转图片功能

如何将 View 类中的代码片段移动到 OnAppearing() 方法?

有没有更聪明的方法将布局绑定到片段?

javaSE_07_方法

前端15k需要会的手写JS代码题(多种解题方法)