我有点纠结于如何将命令式样式转换为函数式样式。
在命令式Web请求中,我习惯于说类似以下psudo代码的内容:
public Response controllerAction(Request request) {
val (req, parserErrors) = parser.parseRequest(request);
if (parserErrors.any()) {
return FourHundredError(parserErrors);
}
val businessErrors = model.validate(req);
if (businessErrors.any()){
return FourOhFour(businessErrors);
}
val (response, errorsWithOurStuff) = model.doBusinessLogicStuff(req);
if (errorsWithOurStuff.any()) {
return FiveHundredError(errorsWithOurStuff);
}
return OK(response)
}
我正在尝试使用HTTP4将其转换为函数样式。
def businessRoutes[F[_]: Sync](BL: BusinessLogic[F]): HttpRoutes[F] = {
val dsl = new Http4sDsl[F]{}
import dsl._
HttpRoutes.of[F] {
case req @ POST -> Root / "sms" =>
for {
request <- req.as[BL.BuisnessRequest]
requestErrors <- BL.validateRequest(request)
response <- if (requestErrors.isEmpty) {
BL.processRequest(request) match {
case Failure(e) => InternalServerError(e)
case Success(response) => Ok(response)
}
} else {
BadRequest(requestErrors)
}
} yield response
}
}
上面的代码看起来只是...对我不好,我不知道怎么让它变得更好。我的目标是保留这里包含的所有http样式抽象,因为我不想将HTTP4或Circe向下泄漏到业务层。我觉得我得到了一个for
,然后是一个if
,然后是一个match
,所有的响应都乱七八糟地放在一起,没有顺序。为了理解这里的代码,我写得很努力,我希望一些ScalaMaven能告诉我如何清理这些代码,并使其具有可读性。
1条答案
按热度按时间xsuvu9jc1#
IMHO,问题的根源在于您建模数据的方式;主要是使用
validateRequest
永远记住,parse, don't validate。
此外,我会使用如下所示的主处理程序来处理非类型化错误:
为了简单起见,我在这里使用了混凝土
IO
,如果愿意,您可以使用F[_]
。