Last active
March 29, 2018 22:58
-
-
Save junior-ales/b08ffd0041235100f828f2b40e9c5fda to your computer and use it in GitHub Desktop.
Exemplo do uso de Either e generics nos erros
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait ServiceError { | |
def errorMessage: String | |
} | |
case class HttpError(error: Error, code: Int) extends ServiceError { | |
override def errorMessage: String = | |
s"Error: ${error.getMessage}. Code: $code" | |
} | |
case class DbError(error: Error, dbName: String) extends ServiceError { | |
override def errorMessage: String = | |
s"Error: ${error.getMessage}. Database name: $dbName" | |
} | |
case class UserData(name: String, age: Int) | |
case class GithubData(username: String) | |
case class User(data: UserData, github: GithubData) { | |
def printIt: String = | |
s"The user ${data.name} is ${data.age} years old and " + | |
s"is in github under the username ${github.username}" | |
} | |
// Chamada pro banco ficticia, soh pra ilustrar | |
def getUserDataById(id: Int): Either[DbError, UserData] = { | |
if (id == 5) | |
Right(UserData("Ronaldo Nazario", 40)) | |
else if (id == 8) | |
Right(UserData("Bebeto", 52)) | |
else | |
Left(DbError(new Error("DB is down"), "footballPlayers")) | |
} | |
// Chamada pra api do github ficticia, soh pra ilustrar | |
def findGithubByName(name: String): Either[HttpError, GithubData] = { | |
if (name.equals("Ronaldo Nazario")) | |
Right(GithubData("ronaldinho9")) | |
else | |
Left(HttpError(new Error("API is down"), 500)) | |
} | |
def getUser(id: Int): Either[ServiceError, User] = for { | |
user <- getUserDataById(id) | |
github <- findGithubByName(user.name) | |
} yield User(user, github) | |
/* | |
* | |
* Resultado do input sendo 5 = "The user Ronaldo Nazario is 40 years old and is in github under the username ronaldinho9" | |
* Resultado do input sendo 8 = "Error: API is down. Code: 500" | |
* Resultado de qualquer outro input = "Error: DB is down. Database name: footballPlayers" | |
* | |
*/ | |
val res1: String = getUser(8).fold( | |
error => error.errorMessage, | |
user => user.printIt | |
) | |
// Mesma coisa que o res1 | |
val res2: String = getUser(5) match { | |
case Right(u) => u.printIt | |
case Left(error) => error.errorMessage | |
} | |
// Aqui modifica soh os erros | |
val res3: Either[String, User] = getUser(4).left.map({ | |
case HttpError(_, code) => s"Bad error code: $code" | |
case DbError(_, dbName) => s"Real bad player not found in DB: $dbName" | |
}) |
Em vez de "Sem Either, usando Exception" não seria "Sem Either, usando Try"? A Exception tá deixando o polimorfismo mais semântico no caso, mas não substitui o Either.
O novo código tá substituindo uma monad (Either) por outra (Try) que nesse caso até faz sentido já que as chamadas são sempre passíveis de uma exceção (HTTP e DB). Mas tem situações que o Either seria melhor por ser mais flexível, por exemplo num caso aonde o erro é de regra de negócio (ex: se a função for chamada mais de 5 vezes não retorne o dado, retorne um erro) aonde usar uma exceção não seria o ideal.
@junior-ales: Nao exatamente, o Try tá sendo no último level apenas, nao na api... ali é a mesma coisa substituir por um try/catch.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Sem Either, usando Exception:
https://gist.github.com/jcsantosbr/86fb5dde063dc6edf8a2357a942f2d53