Scala: return has its place

前端 未结 4 1788
北荒
北荒 2020-12-14 11:14

References:
Scala return keyword
handling errors in scala controllers

EDIT3
This is the \"final\" solution, again thanks to Dan Burton.<

4条回答
  •  太阳男子
    2020-12-14 11:35

    IMHO, seems the problem here is that you are executing business logic in a controller, and Play signatures don't ahem play nice with return values like this is secondary.

    I'd recommend you incapsulate the generateOrderNum, processPayment, createMember calls behind a facade, and that return value can return the appropriate state of the business transaction, which can then be used to return the proper controller state.

    Will update this answer with an example in a bit.

    Edit: This is pretty sloppy so double-check the syntax, but the gist of my answer is to move your business logic sequence into an external class which will leverage the Either/Left/Right you are already using, but now includes your check for empty Transaction ID in the Left response.

    def save = Action {implicit request =>
      val bound = form.bindFromRequest
      if (!bound.hasErrors) {
        val model = bound.get
        val ip = request.headers.get("X-Forwarded-For")
    
        val result = paymentService.processPayment(model, ip)
    
        result match {
          case Left(_) => Ok(withForm(bound.withGlobalError(...)))
          case Right((foo, bar, baz)) => // all good: generate pdf, email, redirect with success msg
        }
      }
      else Ok(withForm(bound))
    }
    
    class PaymentService {
      def processPayment(model, ip): Either[Blah, Blah] = {
        val orderNum = generateOrderNum()
        val transID = processPayment(model, orderNum)
        if (transID.isEmpty) Left(yadda)
        else Right(dao.createMember(model, ip, orderNum, transID))
      }
    }
    

    The only thing a little hokey here is the if/else for bound.hasErrors, but not sure of a clean way to fold that into the match.

    Make sense?

提交回复
热议问题