首页 > 解决方案 > avoid passing redundant parameters

问题描述

I am using Kotlin with Spring Webflux.

I have two functions which extract the some data from the request, makes the extracted data available to the upcoming function.

The example contains only two functions but I have a dozen.

suspend fun extractQueryParam1(serverRequest: ServerRequest,
                               fn: (p1: String) -> ServerResponse): ServerResponse =
    serverRequest.queryParamOrNull("p1")
        ?.let(fn)
        ?: badRequestResponse("Missing p1")

suspend fun extractQueryParam2(serverRequest: ServerRequest,
                               fn: (p1: Long) -> ServerResponse): ServerResponse =
    serverRequest.queryParamOrNull("p2")
        ?.toLong()
        ?.let(fn)
        ?: badRequestResponse("Missing p2")

Usage

    extractQueryParam1(req) { p1 ->
        extractQueryParam2(req) { p2 ->

        }
    }

The req is somehow like a context for these functions and they share the same context.

What I would like to achieve is somehow to avoid passing the req manually.

Is this achievable in Kotlin? How?

I inspired myself from Akka HTTP in terms of usage. They achieved this using Directives but I haven't go there... yet.

Here is an example: https://doc.akka.io/docs/akka-http/current/routing-dsl/routes.html#route-seal-method-to-modify-httpresponse

标签: kotlin

解决方案


Make them into extension functions, and then you can use with or run scopes to call a series of these without repeatedly passing the parameter.

suspend fun ServerRequest.extractQueryParam1(
                               fn: (p1: String) -> ServerResponse): ServerResponse =
    queryParamOrNull("p1")
        ?.let(fn)
        ?: badRequestResponse("Missing p1")

suspend fun ServerRequest.extractQueryParam2(
                               fn: (p1: Long) -> ServerResponse): ServerResponse =
    queryParamOrNull("p2")
        ?.toLong()
        ?.let(fn)
        ?: badRequestResponse("Missing p2")

Usage:

with(req) {
    extractQueryParam1 { p1 ->
        extractQueryParam2 { p2 ->

        }
    }
}

Since you're building a DSL, instead of with or run, you might want to write your own scope function that builds the request and then runs the code within its lambda, using the build request as the receiver.


推荐阅读