如何重构这段Scala代码?基于Play框架优化代码可读性与质量
重构后的Scala + Play框架代码示例
先看重构前的典型混乱代码(模拟你的场景)
package controllers import play.api.mvc._ import play.api.libs.json._ import scala.concurrent.{ExecutionContext, Future} import models.User class UserController @Inject()(val controllerComponents: ControllerComponents)(implicit ec: ExecutionContext) extends BaseController { def getUser(id: String) = Action.async { implicit request => // 硬编码错误信息+嵌套逻辑,重复代码多 if (id.isEmpty) { Future.successful(BadRequest(Json.obj("error" -> "User ID cannot be empty"))) } else { User.findById(id).map { case Some(user) => Ok(Json.obj( "id" -> user.id, "name" -> user.name, "email" -> user.email, "age" -> user.age )) case None => NotFound(Json.obj("error" -> "User not found with id: " + id)) }.recover { case ex: Exception => InternalServerError(Json.obj("error" -> "Something went wrong: " + ex.getMessage)) } } } def createUser() = Action.async(parse.json) { implicit request => request.body.validate[User].fold( errors => { Future.successful(BadRequest(Json.obj("error" -> JsError.toJson(errors)))) }, user => { if (user.email.isEmpty || user.name.isEmpty) { Future.successful(BadRequest(Json.obj("error" -> "Email and name are required"))) } else { User.create(user).map { createdUser => Created(Json.obj( "id" -> createdUser.id, "name" -> createdUser.name, "email" -> createdUser.email, "age" -> createdUser.age )) }.recover { case ex: Exception => InternalServerError(Json.obj("error" -> "Failed to create user: " + ex.getMessage)) } } } ) } }
重构后的优雅版本
package controllers import play.api.mvc._ import play.api.libs.json._ import scala.concurrent.{ExecutionContext, Future} import models.User class UserController @Inject()(val controllerComponents: ControllerComponents)(implicit ec: ExecutionContext) extends BaseController { // 提取通用JSON格式化器,避免手动拼接JSON implicit private val userFormat: OFormat[User] = Json.format[User] // 统一错误处理逻辑,减少重复代码 private def handleServerError(ex: Exception): Result = InternalServerError(Json.obj("error" -> s"Server error: ${ex.getMessage}")) // 提取ID参数验证逻辑 private def validateUserId(id: String): Option[Result] = if (id.isEmpty) Some(BadRequest(Json.obj("error" -> "User ID cannot be empty"))) else None def getUser(id: String) = Action.async { implicit request => validateUserId(id) .map(Future.successful) .getOrElse { User.findById(id).map { case Some(user) => Ok(Json.toJson(user)) case None => NotFound(Json.obj("error" -> s"User not found with id: $id")) }.recover { case ex => handleServerError(ex) } } } def createUser() = Action.async(parse.json) { implicit request => request.body.validate[User].fold( errors => Future.successful(BadRequest(Json.obj("error" -> JsError.toJson(errors)))), user => { // 用Seq收集所有验证错误,避免嵌套if val validationErrors = Seq( Option.when(user.name.isEmpty)("Name is required"), Option.when(user.email.isEmpty)("Email is required") ).flatten if (validationErrors.nonEmpty) { Future.successful(BadRequest(Json.obj("error" -> validationErrors.mkString(", ")))) } else { User.create(user).map(createdUser => Created(Json.toJson(createdUser))) .recover { case ex => handleServerError(ex) } } } ) } }
核心优化点
- 提取重复逻辑:把重复的错误处理、JSON序列化、参数验证抽成独立方法,避免代码冗余
- 活用Scala特性:用
Option.when简化条件判断,字符串插值s""替代拼接,让代码更简洁 - 统一JSON处理:使用Play自动生成的格式化器
Json.format[User],减少手动构建JSON的出错概率 - 扁平化控制流:用
Option.map替代嵌套if-else,让逻辑更线性,降低阅读成本 - 语义化命名:方法命名比如
handleServerError、validateUserId,一眼就能看懂作用
内容的提问来源于stack exchange,提问作者DonDrapper
相关产品推荐
相关产品推荐

