Ich entwickle einen Web-Service mit Scala und Play Framework 2.5. Meine Anwendung hat eine typische Schichtarchitektur. Ich habe die folgenden Klassen: model.User
, repository.UserRepository
, und controllers.UserController
und ich versuche, eine gute Möglichkeit, Geschäftslogikfehler zu behandeln, ohne Exception
zu verwenden.Buisness Logic Fehlerbehandlung in Scala
Betrachten Sie den folgenden Fall: eine Anfrage für die Registrierung eines neuen Benutzers erhalten wurde. Der Anfragetext enthält zwei Parameter: email
und password
. Diese Parameter werden an UserService#registerUser
übergeben, die prüft, ob die E-Mail gültig ist und ob ein Benutzer mit einer solchen E-Mail bereits existiert. Meine Lösung ist UserService#registerUser
zurückzukehren als Ergebnis ein Either[BuisnessFailure, Int]
Objekt. BuisnessFailure
ist ein Merkmal und wird vererbt von WrongEmailFormatFailure
und UserAlreadyExistFailure
. Wenn die E-Mail nicht gültig ist, gibt UserService#registerUser
Left(WrongEmailFormatFailure)
zurück. Wenn ein Benutzer mit einer solchen E-Mail bereits existiert, gibt UserService#registerUser
Left(UserAlreadyExistFailure)
zurück. Und im Erfolgsfall UserService#registerUser
gibt Right(userRepository.create(User(email, password))
zurück. Danach kann ich in controllers.UserController
diesen Fall mit Mustervergleich umgehen und eine entsprechende Antwort senden.
Also, ist dieser Ansatz gut genug, um ähnliche Fälle zu behandeln? Bitte finden meinen Code unten:
Benutzer:
package model
case class User(email: String, password: String)
UserRepository:
package repository
import model.User
class UserRepository {
def create(user: User): Int = ???
def find(email: String): Option[User] = ???
}
Userservice:
package service
import model.User
import repository.UserRepository
import util.{BuisnessFailure, UserAlreadyExistFailure, WrongEmailFormatFailure}
class UserService {
private val userRepository: UserRepository = ???
def registerUser(email: String, password: String): Either[BuisnessFailure, Int] = {
if (userAlreadyExists(email))
Left(UserAlreadyExistFailure)
else
if (!isEmailValid(email))
Left(WrongEmailFormatFailure)
else
Right(userRepository.create(User(email, password)))
}
private def isEmailValid(email: String): Boolean = ???
private def userAlreadyExists(email: String): Boolean = ???
}
Usercontroller:
package controller
import service.UserService
import util.{UserAlreadyExistFailure, WrongEmailFormatFailure}
class UserController extends play.api.Controller {
private val userService = new UserService
def signUp() = Action(parse.json) { implicit request =>
//obtaining email and password parameters from request body
val email = ???
val password = ???
userService.registerUser(email, password) match {
case Left(WrongEmailFormatFailure) => // send 400 code and appropriate error message
case Left(UserAlreadyExistFailure) => // send 400 code and appropriate error message
case Right(_) => // send response with 200 code
}
}
}
BuisnessFailure:
package util
sealed trait BuisnessFailure
case object UserAlreadyExistFailure extends BuisnessFailure
case object WrongEmailFormatFailure extends BuisnessFailure
Gute Frage, aber es wäre angemessener auf http://softwareengineering.stackexchange.com – Jubobs
@Jubobs Danke für den Link. Ich habe noch nie von Softwareengineering.stackexchange.com gehört. – alex
Ich würde Validierung einen anderen Service, so dass es mehr testbar und wiederverwendbar ist –