Java 将多个方法封装为一个方法的函数方式

Java 将多个方法封装为一个方法的函数方式,java,function,optimization,functional-programming,kotlin,Java,Function,Optimization,Functional Programming,Kotlin,我对函数式编程的世界是相当陌生的,我在Kotlin中尝试了一些代码,下面的代码片段就是我所做的,但对我来说似乎非常必要 @EmailTemplate("onCallTemplate") fun retrieveNextOnCallCreateMailRecipientAndSendMail(time: LocalDateTime, trial: Boolean = true) { val emailTemplateID = extractEmailTemplat

我对函数式编程的世界是相当陌生的,我在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")
}

您可以合并一些计算并减少局部变量的数量。另外,两个
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)
}

你可以试试这样的

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

它的可读性可能不会更高,但体积更小。

当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显示提示,因此您可以获得自动变量+一些自由类型信息:

注意:一般来说,我会保留
?。
周围的一切真的可以为空吗?如果因为嵌套而需要指定
it1
以区别于
it
,那么不妨借此机会对变量进行恰当命名

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

接口调用
接口消息模板
接口消息模板ID
接口邮件收件人
接口消息TemplateAccessPoint{
fun findByID(it:MessageTemplateID):MessageTemplate
}
接口数据通讯器{
来自DataHub(时间:LocalDateTime)的nCallToSendNotification有趣列表:列表
}
接口OnCallListToMailRecipient{
有趣的buildMailRecipientFromOnCalls(oncalls:List):邮件收件人
}
接口电子邮件发送者{
fun sendNotificationToOnCallPersons(收件人:MailRecipient,模板:MessageTemplate,试用版:Boolean)
}
fun extractEmailTemplateValue(名称:字符串):MessageTemplateID=TODO()
val dataHubCommunicator:dataHubCommunicator=TODO()
val messageTemplateAccessPoint:messageTemplateAccessPoint=TODO()
val onCallListToMailRecipient:onCallListToMailRecipient=TODO()
val emailSender:emailSender=TODO()

其中一些可能取决于空值,如果您喜欢
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显示提示,因此您可以获得自动变量+一些自由类型信息:

注意:一般来说,我会保留
?。
周围的一切真的可以为空吗?如果因为嵌套而需要指定
it1
以区别于
it
,那么不妨借此机会对变量进行恰当命名

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

接口调用
接口消息模板
接口消息模板ID
接口邮件收件人
接口消息TemplateAccessPoint{
fun findByID(it:MessageTemplateID):MessageTemplate
}
接口数据通讯器{
来自DataHub(时间:LocalDateTime)的nCallToSendNotification有趣列表:列表
}
接口OnCallListToMailRecipient{
有趣的buildMailRecipientFromOnCalls(oncalls:List):邮件收件人
}
接口电子邮件发送者{
fun sendNotificationToOnCallPersons(收件人:MailRecipient,模板:MessageTemplate,试用版:Boolean)
}
fun extractEmailTemplateValue(名称:字符串):MessageTemplateID=TODO()
val dataHubCommunicator:dataHubCommunicator=TODO()
val messageTemplateAccessPoint:messageTemplateAccessPoint=TODO()
val onCallListToMailRecipient:onCallListToMailRecipient=TODO()
val emailSender:emailSender=TODO()

messageTemplate
之后删除let会导致在
messageTemplate
为null时调用
sendNotificationToOnCallPersons
,因此这是不一样的。@HankD可为null的情况被忽略,根本不被处理,我认为这不是理想的行为,如果
messageTemplate
为null,则在
messageTemplate
之后删除let会导致调用
sendNotificationToOnCallPersons
,因此这是不一样的。@HankD可为null的情况被忽略,根本不被处理,我认为这不是期望的行为,是一种真正的函数方法。一种真正的函数方法。