SlideShare una empresa de Scribd logo
Manejo de errores con typelevel.cats
El recorrido
● Error y Excepción.
● El excepcionalismo imperativo.
● Encapsular excepciones en Try.
● Errores como parte del dominio.
● Manejo de errores con Scala Either.
● Acumular errores con Validated.
● Reportar errores y aciertos con Ior.
● Conclusiones.
Error y Excepción
● Error: resultado no deseado de la evaluación de un programa.
● Excepción: condición excepcional del programa en tiempo de
ejecución.
El excepcionalismo imperativo
● Durante la evaluación de un método, si se encuentra un error se arroja
una excepción.
● Este paradigma puede tener su origen en:
○ Lenguajes imperativos sin un sistema de tipos robusto.
○ Considerando lo anterior, carencia de tipos de datos (datatypes) que
permitan manejar los errores.
● Se requiere try/catch para manejar los métodos que puedan arrojar
excepciones.
El dominio
case class Book(isbn: String, title: String, author: String, genre: Genre)
trait Genre extends Product with Serializable
object Genre {
case object Fiction extends Genre
case object ScienceFiction extends Genre
case object HistoricNovel extends Genre
case object InvalidGenre extends Genre
}
val theFountainhead = Book("ISBN: 978-1-4028-9462-6","The Fountainhead","Ayn Rand",Genre.Fiction)
val atlasShrugged = Book("ISBN-13 978-1-4028-9462-6","Atlas Shrugged","Ayn Rand",Genre.Fiction)
val theCountOfMontecristo = Book("ISBN-13 978-1-4028-9462","The Count Of Montecristo","Alexandre
Dumas",Genre.HistoricNovel)
val titlelessBook = Book("ISBN-13 978-1-4028-9462-6","","Unknown",Genre.InvalidGenre)
Un libro con isbn, título, autor y género.
El excepcionalismo imperativo
private def validateGenre(g: Genre): Unit =
if ( g == Genre.InvalidGenre ) throw new InvalidParameter("Book has invalid genre")
private def validateIsbn(isbn: String): Unit = isbn match {
case isbnRegex(all @ _*) => ()
case _ => throw new InvalidParameter("isbn has not a valid format")
}
private def validateTitle(title: String): Unit =
if (title.isEmpty || title == null) throw new InvalidParameter("title must not be empty")
private def validateAuthor(author: String): Unit =
if (author.isEmpty || author == null) throw new InvalidParameter("author must not be empty")
class InvalidParameter(message: String) extends Exception(message)
class EmptyBookList(message: String) extends Exception(message)
El excepcionalismo imperativo
def validateBook(book: Book): Book = {
validateGenre(book.genre)
validateIsbn(book.isbn)
validateTitle(book.title)
validateAuthor(book.author)
book
}
def validateBooks(books: List[Book]): List[Book] =
if (books == Nil) throw new EmptyBookList("Book list was empty")
else {
val booksBuffer = new ListBuffer[Book]
for (book <- books) {
try booksBuffer += validateBook(book) catch { case ex: Exception => println(s"Error $ex") }
}
booksBuffer.toList
}
Encapsulando excepciones con Try
● El tipo Try[A] es utilizado para manejar excepciones en métodos.
● Encapsula el resultado en dos subtipos: Success y Failure.
● Success contiene el resultado del método.
● Failure contiene la excepción arrojada.
● Nos permite usar for comprehension.
● Es fail fast en Failure.
Encapsulando excepciones con Try
private def validateGenre(g: Genre): Try[Genre] = Try {
g match {
case Genre.InvalidGenre => throw new InvalidParameter("Book has invalid genre")
case genre => genre
}
}
private def validateIsbn(isbn: String): Try[String] = Try {
isbn match {
case isbnRegex(all @ _*) => isbn
case _ => throw new InvalidParameter("isbn has not a valid format")
}
}
private def validateTitle(title: String): Try[String] = Try {
if (Option(title).forall(_.isEmpty)) throw new InvalidParameter("title must not be empty") else title
}
private def validateAuthor(author: String): Try[String] = Try {
if (Option(author).forall(_.isEmpty)) throw new InvalidParameter("author must not be empty") else author
}
Encapsulando excepciones con Try
import cats.syntax.semigroup._
//Valida los libros y devuelve una lista no vacía en el caso Success
def validateBook(b: Book): Try[NonEmptyList[Book]] =
for {
i <- validateIsbn(b.isbn)
a <- validateAuthor(b.author)
t <- validateTitle(b.title)
g <- validateGenre(b.genre)
} yield NonEmptyList.of(Book(i, t, a, g))
//Combina los resultados exitosos del Try en una lista no vacía
def validateBooks(bs: List[Book]): Try[NonEmptyList[Book]] = bs match {
case Nil => Failure(new EmptyBookList("Book list was empty"))
case books => books map validateBook reduce (_ |+| _)
}
Encapsulando excepciones con Try
"BookValidation" should {
"Validate a book" in {
val validated = validateBook(theFountainhead)
validated should === (Success(NonEmptyList(theFountainhead, Nil)))
}
"Validate books" in {
val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged))
validatedBooks should === (Success(NonEmptyList(theFountainhead, atlasShrugged :: Nil)))
}
"Fail fast error on books" in {
val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead))
inside(validatedBooks) { case Failure(ex) => ex.getMessage shouldBe "title must not be empty" }
}
}
Errores como parte del dominio
● Un error en una función no debe tratarse como algo excepcional.
● Excepciones para interacciones con la capa de infraestructura.
● Excepciones rompen con type safety.
● Los errores también son parte del dominio.
//No es cierto que validateBook siempre devuelve un Book
def validateBook(book: Book): Book = {
validateGenre(book.genre)
validateIsbn(book.isbn)
validateTitle(book.title)
validateAuthor(book.author)
book
}
Errores como parte del dominio
sealed trait Error extends Product with Serializable {
val message: String
}
case class InvalidParameter(message: String) extends Error
case class EmptyBookList(message: String) extends Error
Definimos las excepciones anteriormente usadas como ADTs de Error.
Manejo de errores con Scala Either
● El tipo Either[A, B] representa el valor de dos tipos posibles: Left o Right
● Convencionalmente se usa el Left para representar errores y Right para
representar los aciertos.
● Nos facilita manejar los errores modelados como parte del dominio.
● Se puede usar for comprehension.
● Es fail fast en Left.
Manejo de errores con Scala Either
private def validateGenre(g: Genre): Either[InvalidParameter, Genre] = g match {
case InvalidGenre => Left(InvalidParameter("Book has invalid genre"))
case genre => Right(genre)
}
private def validateIsbn(isbn: String): Either[InvalidParameter, String] = isbn match {
case isbnRegex(all @ _*) => Right(isbn)
case _ => Left(InvalidParameter("isbn has not a valid format"))
}
private def validateTitle(title: String): Either[InvalidParameter, String] =
if (Option(title).forall(_.isEmpty)) Left(InvalidParameter("title must not be empty")) else Right(title)
private def validateAuthor(author: String): Either[InvalidParameter, String] =
if (Option(author).forall(_.isEmpty)) Left(InvalidParameter("author must not be empty")) else Right(author)
Manejo de errores con Scala Either
import cats.syntax.semigroup._
//Valida secuencialmente todos los campos, se detiene en el primer error encontrado.
def validateBook(b: Book): Either[InvalidParameter, NonEmptyList[Book]] =
for {
i <- validateIsbn(b.isbn)
a <- validateAuthor(b.author)
t <- validateTitle(b.title)
g <- validateGenre(b.genre)
} yield NonEmptyList.of(Book(i, t, a, g))
//Por ser fail fast, reporta el primer error encontrado pero acumula todos los aciertos.
def validateBooks(bs: List[Book]): Either[Error, NonEmptyList[Book]] = bs match {
case Nil => Left(EmptyBookList("Book list was empty"))
case books => books map validateBook reduce (_ |+| _)
}
Manejo de errores con Scala Either
"BookValidation" should {
"Validate a book" in {
val validated = validateBook(theFountainhead)
validated should === (Right(NonEmptyList(theFountainhead, Nil)))
}
"Validate books" in {
val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged))
validatedBooks should === (Right(NonEmptyList(theFountainhead, atlasShrugged :: Nil)))
}
"Fail fast error on books" in {
val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead))
validatedBooks should === (Left(InvalidParameter("title must not be empty")))
}
}
Manejo de errores con Cats Validated
● El tipo Validated[A, B] representa el valor de dos tipos posibles: Valid e
Invalid.
● Desde el punto de vista semántico, es obvio que Invalid es utilizado para
representar los errores y Valid los aciertos.
● Nos facilita manejar los errores modelados como parte del dominio.
● No se puede utilizar en for comprehension.
● Acumula errores en Invalid ( type ValidatedNel[A, B] =
Validated[NonEmptyList[A], B] ).
Manejo de errores con Cats Validated
private def validateGenre(g: Genre): ValidatedNel[InvalidParameter, Genre] = g match {
case InvalidGenre => InvalidParameter("Book has invalid genre").invalidNel
case genre => genre.validNel
}
private def validateIsbn(isbn: String): ValidatedNel[InvalidParameter, String] = isbn match {
case isbnRegex(all @ _*) => isbn.validNel
case _ => InvalidParameter("isbn has not a valid format").invalidNel
}
private def validateTitle(title: String): ValidatedNel[InvalidParameter, String] =
if (Option(title).exists(_.isEmpty)) InvalidParameter("title must not be empty").invalidNel else title.validNel
private def validateAuthor(author: String): ValidatedNel[InvalidParameter, String] =
if (Option(author).exists(_.isEmpty)) InvalidParameter("author must not be empty").invalidNel
else author.validNel
Manejo de errores con Cats Validated
import cats.syntax.cartesian._
import cats.syntax.semigroup._
//Valida en el producto cartesiano, acumula los errores en cada validación.
def validateBook(b: Book): ValidatedNel[InvalidParameter, NonEmptyList[Book]] = (
validateIsbn(b.isbn) |@|
validateAuthor(b.author) |@|
validateTitle(b.title) |@|
validateGenre(b.genre) ) map {
case (isbn, author, title, genre) =>
NonEmptyList.of(Book(isbn, title, author, genre))
}
//Puede acumular todos los errores o acumular todos los aciertos.
def validateBooks(bs: List[Book]): ValidatedNel[Error, NonEmptyList[Book]] = bs match {
case Nil => EmptyBookList("Book list was empty").invalidNel
case books => books map validateBook reduce (_ |+| _)
}
Manejo de errores con Cats Validated
"BookValidation" should {
"Validate books" in {
val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged))
validatedBooks should === (Valid(NonEmptyList(theFountainhead, atlasShrugged :: Nil)))
}
"Accumulate errors on books" in {
val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead))
validatedBooks should === (
Invalid(
NonEmptyList(InvalidParameter("title must not be empty"),
InvalidParameter("Book has invalid genre") :: InvalidParameter("isbn has not a valid format") :: Nil)
)
)
}
}
Manejo de errores con Cats Ior
● El tipo Ior[A, B] representa el valor de tres tipos posibles: Ior.Right,
Ior.Left e Ior.Both.
● La convención con Ior.Left e Ior.Right es igual a la de Either con respecto
a la representación de errores y aciertos.
● Ior.Both permite incluir simultáneamente los errores y aciertos
● Nos facilita manejar los errores modelados como parte del dominio.
● Se puede utilizar en for comprehension.
● Es fail fast en Ior.Left y acumula errores en Ior.Both.
Manejo de errores con Cats Ior
private def validateGenre(g: Genre): IorNel[InvalidParameter, Genre] = g match {
case InvalidGenre => Ior.left(NonEmptyList.of(InvalidParameter("Book has invalid genre")))
case genre => Ior.right(genre)
}
private def validateIsbn(isbn: String): IorNel[InvalidParameter, String] = isbn match {
case isbnRegex(all @ _*) => Ior.right(isbn)
case _ => Ior.left(NonEmptyList.of(InvalidParameter("isbn has not a valid format")))
}
private def validateTitle(title: String): IorNel[InvalidParameter, String] =
if (Option(title).exists(_.isEmpty)) Ior.left(NonEmptyList.of(InvalidParameter("title must not be empty")))
else Ior.right(title)
private def validateAuthor(author: String): IorNel[InvalidParameter, String] =
if (Option(author).exists(_.isEmpty)) Ior.left(NonEmptyList.of(InvalidParameter("author must not be empty")))
else Ior.right(author)
Manejo de errores con Cats Ior
import cats.syntax.semigroup._
//Valida los campos secuencialmente, se detiene en el primer error.
def validateBook(b: Book): IorNel[InvalidParameter, NonEmptyList[Book]] =
for {
i <- validateIsbn(b.isbn)
a <- validateAuthor(b.author)
t <- validateTitle(b.title)
g <- validateGenre(b.genre)
} yield NonEmptyList.of(Book(i, t, a, g))
//A diferencia de Validated, puede acumular errores y aciertos en Ior.Both
def validateBooks(bs: List[Book]): IorNel[Error, NonEmptyList[Book]] = bs match {
case Nil => Ior.left(EmptyBookList("Book list was empty"))
case books => books map validateBook reduce (_ |+| _)
}
Manejo de errores con Cats Ior
"BookValidation" should {
"Validate books" in {
val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged))
validatedBooks should === (Ior.Right(NonEmptyList(theFountainhead, atlasShrugged :: Nil)))
}
"Fail fast error on books" in {
val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead, atlasShrugged))
validatedBooks should === (
Ior.Both(
NonEmptyList(InvalidParameter("title must not be empty"),InvalidParameter("isbn has not a valid format") :: Nil),
NonEmptyList(theFountainhead, atlasShrugged :: Nil)
)
)
}
}
Conclusiones
● En una función no se deben arrojar excepciones, se pierde transparencia
referencial.
● Se favorece la modelación de errores en el dominio.
● Try es fail fast, no es expresivo en cuanto a los errores que encapsula y
se puede usar cuando se depende de métodos de librerías java.
● Either es fail fast y puede acumular aciertos.
● Validated acumula errores, no se puede usar en for comprehensions y
puede acumular aciertos.
● Ior es el más flexible: es fail fast en Ior.Left, acumula errores en Ior.Both y
puede acumular aciertos en Ior.Right e Ior.Both.
¿Preguntas?

Más contenido relacionado

Destacado

незмінювані іменники
незмінювані іменникинезмінювані іменники
незмінювані іменники
milona14
 
Total Rewards Spectrum Health
Total Rewards Spectrum Health Total Rewards Spectrum Health
Total Rewards Spectrum Health
Laura Steffer
 
парад талантов
парад талантовпарад талантов
парад талантов
peshkova_anastasiya
 
Santa Fe Avenue Streetscape-Survey #2 Results
Santa Fe Avenue Streetscape-Survey #2 ResultsSanta Fe Avenue Streetscape-Survey #2 Results
Santa Fe Avenue Streetscape-Survey #2 Results
City of Salina
 
Rassegna stampa 28 marzo del Teatro Franco Parenti
Rassegna stampa 28 marzo del Teatro Franco Parenti Rassegna stampa 28 marzo del Teatro Franco Parenti
Rassegna stampa 28 marzo del Teatro Franco Parenti
Francesco Malcangio
 
Trip to the museum of London
Trip to the museum of LondonTrip to the museum of London
Trip to the museum of London
leonaoti
 
Reach.UrFaculty - Govt. Jobs Update Mar 27
Reach.UrFaculty - Govt. Jobs Update Mar 27Reach.UrFaculty - Govt. Jobs Update Mar 27
Reach.UrFaculty - Govt. Jobs Update Mar 27
Reshmaurfaculty
 
7. evaluation(2)
7. evaluation(2)7. evaluation(2)
7. evaluation(2)
louis harman
 
Presentation on Online Learning at UET Peshawar
Presentation on Online Learning at UET PeshawarPresentation on Online Learning at UET Peshawar
Presentation on Online Learning at UET Peshawar
Atif Ur Rahman
 
Information of the senses
Information of the sensesInformation of the senses
Information of the senses
Škola Futura
 
Investing in Portugal - Portuguese Company [Episode 04]
Investing in Portugal - Portuguese Company [Episode 04]Investing in Portugal - Portuguese Company [Episode 04]
Investing in Portugal - Portuguese Company [Episode 04]
UWU Solutions, Lda.
 
Case study WhatsNext
Case study WhatsNextCase study WhatsNext
Case study WhatsNext
Margot Deliperi
 
Analytics in Online Retail
Analytics in Online RetailAnalytics in Online Retail
Executive Summary of 2017 African Commercial Vehicle Industry
Executive Summary of 2017 African Commercial Vehicle IndustryExecutive Summary of 2017 African Commercial Vehicle Industry
Executive Summary of 2017 African Commercial Vehicle Industry
Lakshmi Narayanan Ramanujam
 

Destacado (14)

незмінювані іменники
незмінювані іменникинезмінювані іменники
незмінювані іменники
 
Total Rewards Spectrum Health
Total Rewards Spectrum Health Total Rewards Spectrum Health
Total Rewards Spectrum Health
 
парад талантов
парад талантовпарад талантов
парад талантов
 
Santa Fe Avenue Streetscape-Survey #2 Results
Santa Fe Avenue Streetscape-Survey #2 ResultsSanta Fe Avenue Streetscape-Survey #2 Results
Santa Fe Avenue Streetscape-Survey #2 Results
 
Rassegna stampa 28 marzo del Teatro Franco Parenti
Rassegna stampa 28 marzo del Teatro Franco Parenti Rassegna stampa 28 marzo del Teatro Franco Parenti
Rassegna stampa 28 marzo del Teatro Franco Parenti
 
Trip to the museum of London
Trip to the museum of LondonTrip to the museum of London
Trip to the museum of London
 
Reach.UrFaculty - Govt. Jobs Update Mar 27
Reach.UrFaculty - Govt. Jobs Update Mar 27Reach.UrFaculty - Govt. Jobs Update Mar 27
Reach.UrFaculty - Govt. Jobs Update Mar 27
 
7. evaluation(2)
7. evaluation(2)7. evaluation(2)
7. evaluation(2)
 
Presentation on Online Learning at UET Peshawar
Presentation on Online Learning at UET PeshawarPresentation on Online Learning at UET Peshawar
Presentation on Online Learning at UET Peshawar
 
Information of the senses
Information of the sensesInformation of the senses
Information of the senses
 
Investing in Portugal - Portuguese Company [Episode 04]
Investing in Portugal - Portuguese Company [Episode 04]Investing in Portugal - Portuguese Company [Episode 04]
Investing in Portugal - Portuguese Company [Episode 04]
 
Case study WhatsNext
Case study WhatsNextCase study WhatsNext
Case study WhatsNext
 
Analytics in Online Retail
Analytics in Online RetailAnalytics in Online Retail
Analytics in Online Retail
 
Executive Summary of 2017 African Commercial Vehicle Industry
Executive Summary of 2017 African Commercial Vehicle IndustryExecutive Summary of 2017 African Commercial Vehicle Industry
Executive Summary of 2017 African Commercial Vehicle Industry
 

Similar a Manejo de errores con typelevel.cats

Tema2[php]
Tema2[php]Tema2[php]
Tema2[php]
96elnoble14
 
Elementos del Hardware y Software
Elementos del Hardware y SoftwareElementos del Hardware y Software
Elementos del Hardware y Software
carlosadrianev
 
Ruby
Ruby Ruby
Ruby 01
Ruby 01Ruby 01
Php
PhpPhp
RegExp JavaScript Expresiones Regulares
RegExp JavaScript Expresiones RegularesRegExp JavaScript Expresiones Regulares
RegExp JavaScript Expresiones Regulares
Isabel Gómez
 
Javascript C#
Javascript C#Javascript C#
Javascript C#
Manuel Antonio
 
Metaprogramación (en Ruby): programas que escriben programas
Metaprogramación (en Ruby): programas que escriben programasMetaprogramación (en Ruby): programas que escriben programas
Metaprogramación (en Ruby): programas que escriben programas
Sergio Gil
 

Similar a Manejo de errores con typelevel.cats (8)

Tema2[php]
Tema2[php]Tema2[php]
Tema2[php]
 
Elementos del Hardware y Software
Elementos del Hardware y SoftwareElementos del Hardware y Software
Elementos del Hardware y Software
 
Ruby
Ruby Ruby
Ruby
 
Ruby 01
Ruby 01Ruby 01
Ruby 01
 
Php
PhpPhp
Php
 
RegExp JavaScript Expresiones Regulares
RegExp JavaScript Expresiones RegularesRegExp JavaScript Expresiones Regulares
RegExp JavaScript Expresiones Regulares
 
Javascript C#
Javascript C#Javascript C#
Javascript C#
 
Metaprogramación (en Ruby): programas que escriben programas
Metaprogramación (en Ruby): programas que escriben programasMetaprogramación (en Ruby): programas que escriben programas
Metaprogramación (en Ruby): programas que escriben programas
 

Último

Presentación Seguridad Digital Profesional Azul Oscuro (1).pdf
Presentación Seguridad Digital Profesional Azul Oscuro (1).pdfPresentación Seguridad Digital Profesional Azul Oscuro (1).pdf
Presentación Seguridad Digital Profesional Azul Oscuro (1).pdf
giampierdiaz5
 
Slideshare: definiciòn, registrarse, presentaciones, ventajas y desventajas
Slideshare: definiciòn, registrarse, presentaciones, ventajas y desventajasSlideshare: definiciòn, registrarse, presentaciones, ventajas y desventajas
Slideshare: definiciòn, registrarse, presentaciones, ventajas y desventajas
AdrianaRengifo14
 
Inteligencia Artificial
Inteligencia ArtificialInteligencia Artificial
Inteligencia Artificial
YashiraPaye
 
Uso de las Tics en la vida cotidiana.pptx
Uso de las Tics en la vida cotidiana.pptxUso de las Tics en la vida cotidiana.pptx
Uso de las Tics en la vida cotidiana.pptx
231485414
 
Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)
Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)
Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)
codesiret
 
Manual de soporte y mantenimiento de equipo de cómputo
Manual de soporte y mantenimiento de equipo de cómputoManual de soporte y mantenimiento de equipo de cómputo
Manual de soporte y mantenimiento de equipo de cómputo
doctorsoluciones34
 
El uso de las TIC en la vida cotidiana.pptx
El uso de las TIC en la vida cotidiana.pptxEl uso de las TIC en la vida cotidiana.pptx
El uso de las TIC en la vida cotidiana.pptx
jgvanessa23
 
Nuevos tiempos, nuevos espacios.docxdsdsad
Nuevos tiempos, nuevos espacios.docxdsdsadNuevos tiempos, nuevos espacios.docxdsdsad
Nuevos tiempos, nuevos espacios.docxdsdsad
larapalaciosmonzon28
 
625204013-64-Camino-a-----La-Lectura.pdf
625204013-64-Camino-a-----La-Lectura.pdf625204013-64-Camino-a-----La-Lectura.pdf
625204013-64-Camino-a-----La-Lectura.pdf
yuberpalma
 
CURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdf
CURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdfCURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdf
CURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdf
LagsSolucSoporteTecn
 
edublogs info.docx asdasfasfsawqrdqwfqwfqwfq
edublogs info.docx asdasfasfsawqrdqwfqwfqwfqedublogs info.docx asdasfasfsawqrdqwfqwfqwfq
edublogs info.docx asdasfasfsawqrdqwfqwfqwfq
larapalaciosmonzon28
 
Presentación de Tic en educación y sobre blogger
Presentación de Tic en educación y sobre bloggerPresentación de Tic en educación y sobre blogger
Presentación de Tic en educación y sobre blogger
larapalaciosmonzon28
 
Second Life, informe de actividad del maestro Tapia
Second Life, informe de actividad del maestro TapiaSecond Life, informe de actividad del maestro Tapia
Second Life, informe de actividad del maestro Tapia
al050121024
 
El uso de las TIC por Cecilia Pozos S..pptx
El uso de las TIC  por Cecilia Pozos S..pptxEl uso de las TIC  por Cecilia Pozos S..pptx
El uso de las TIC por Cecilia Pozos S..pptx
cecypozos703
 
El uso de las TIC's en la vida cotidiana
El uso de las TIC's en la vida cotidianaEl uso de las TIC's en la vida cotidiana
El uso de las TIC's en la vida cotidiana
231458066
 
trabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdk
trabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdktrabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdk
trabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdk
KukiiSanchez
 
Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)
Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)
Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)
AbrahamCastillo42
 
La Inteligencia Artificial en la actualidad.docx
La Inteligencia Artificial en la actualidad.docxLa Inteligencia Artificial en la actualidad.docx
La Inteligencia Artificial en la actualidad.docx
luiscohailatenazoa0
 
UML_clase_02_UML_casos_de_uso_05 EN DIAGRAMA
UML_clase_02_UML_casos_de_uso_05 EN DIAGRAMAUML_clase_02_UML_casos_de_uso_05 EN DIAGRAMA
UML_clase_02_UML_casos_de_uso_05 EN DIAGRAMA
martinezluis17
 
TIC en educacion.rtf.docxlolololololololo
TIC en educacion.rtf.docxlolololololololoTIC en educacion.rtf.docxlolololololololo
TIC en educacion.rtf.docxlolololololololo
KukiiSanchez
 

Último (20)

Presentación Seguridad Digital Profesional Azul Oscuro (1).pdf
Presentación Seguridad Digital Profesional Azul Oscuro (1).pdfPresentación Seguridad Digital Profesional Azul Oscuro (1).pdf
Presentación Seguridad Digital Profesional Azul Oscuro (1).pdf
 
Slideshare: definiciòn, registrarse, presentaciones, ventajas y desventajas
Slideshare: definiciòn, registrarse, presentaciones, ventajas y desventajasSlideshare: definiciòn, registrarse, presentaciones, ventajas y desventajas
Slideshare: definiciòn, registrarse, presentaciones, ventajas y desventajas
 
Inteligencia Artificial
Inteligencia ArtificialInteligencia Artificial
Inteligencia Artificial
 
Uso de las Tics en la vida cotidiana.pptx
Uso de las Tics en la vida cotidiana.pptxUso de las Tics en la vida cotidiana.pptx
Uso de las Tics en la vida cotidiana.pptx
 
Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)
Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)
Infografia TCP/IP (Transmission Control Protocol/Internet Protocol)
 
Manual de soporte y mantenimiento de equipo de cómputo
Manual de soporte y mantenimiento de equipo de cómputoManual de soporte y mantenimiento de equipo de cómputo
Manual de soporte y mantenimiento de equipo de cómputo
 
El uso de las TIC en la vida cotidiana.pptx
El uso de las TIC en la vida cotidiana.pptxEl uso de las TIC en la vida cotidiana.pptx
El uso de las TIC en la vida cotidiana.pptx
 
Nuevos tiempos, nuevos espacios.docxdsdsad
Nuevos tiempos, nuevos espacios.docxdsdsadNuevos tiempos, nuevos espacios.docxdsdsad
Nuevos tiempos, nuevos espacios.docxdsdsad
 
625204013-64-Camino-a-----La-Lectura.pdf
625204013-64-Camino-a-----La-Lectura.pdf625204013-64-Camino-a-----La-Lectura.pdf
625204013-64-Camino-a-----La-Lectura.pdf
 
CURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdf
CURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdfCURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdf
CURSO CAMARAS DE SEGURIDAD 2023 FINAL .pdf
 
edublogs info.docx asdasfasfsawqrdqwfqwfqwfq
edublogs info.docx asdasfasfsawqrdqwfqwfqwfqedublogs info.docx asdasfasfsawqrdqwfqwfqwfq
edublogs info.docx asdasfasfsawqrdqwfqwfqwfq
 
Presentación de Tic en educación y sobre blogger
Presentación de Tic en educación y sobre bloggerPresentación de Tic en educación y sobre blogger
Presentación de Tic en educación y sobre blogger
 
Second Life, informe de actividad del maestro Tapia
Second Life, informe de actividad del maestro TapiaSecond Life, informe de actividad del maestro Tapia
Second Life, informe de actividad del maestro Tapia
 
El uso de las TIC por Cecilia Pozos S..pptx
El uso de las TIC  por Cecilia Pozos S..pptxEl uso de las TIC  por Cecilia Pozos S..pptx
El uso de las TIC por Cecilia Pozos S..pptx
 
El uso de las TIC's en la vida cotidiana
El uso de las TIC's en la vida cotidianaEl uso de las TIC's en la vida cotidiana
El uso de las TIC's en la vida cotidiana
 
trabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdk
trabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdktrabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdk
trabajo práctico kuikikiikkidfsmdklfskdnfklsdnfknsdk
 
Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)
Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)
Todo sobre la tarjeta de video (Bienvenidos a mi blog personal)
 
La Inteligencia Artificial en la actualidad.docx
La Inteligencia Artificial en la actualidad.docxLa Inteligencia Artificial en la actualidad.docx
La Inteligencia Artificial en la actualidad.docx
 
UML_clase_02_UML_casos_de_uso_05 EN DIAGRAMA
UML_clase_02_UML_casos_de_uso_05 EN DIAGRAMAUML_clase_02_UML_casos_de_uso_05 EN DIAGRAMA
UML_clase_02_UML_casos_de_uso_05 EN DIAGRAMA
 
TIC en educacion.rtf.docxlolololololololo
TIC en educacion.rtf.docxlolololololololoTIC en educacion.rtf.docxlolololololololo
TIC en educacion.rtf.docxlolololololololo
 

Manejo de errores con typelevel.cats

  • 1. Manejo de errores con typelevel.cats
  • 2. El recorrido ● Error y Excepción. ● El excepcionalismo imperativo. ● Encapsular excepciones en Try. ● Errores como parte del dominio. ● Manejo de errores con Scala Either. ● Acumular errores con Validated. ● Reportar errores y aciertos con Ior. ● Conclusiones.
  • 3. Error y Excepción ● Error: resultado no deseado de la evaluación de un programa. ● Excepción: condición excepcional del programa en tiempo de ejecución.
  • 4. El excepcionalismo imperativo ● Durante la evaluación de un método, si se encuentra un error se arroja una excepción. ● Este paradigma puede tener su origen en: ○ Lenguajes imperativos sin un sistema de tipos robusto. ○ Considerando lo anterior, carencia de tipos de datos (datatypes) que permitan manejar los errores. ● Se requiere try/catch para manejar los métodos que puedan arrojar excepciones.
  • 5. El dominio case class Book(isbn: String, title: String, author: String, genre: Genre) trait Genre extends Product with Serializable object Genre { case object Fiction extends Genre case object ScienceFiction extends Genre case object HistoricNovel extends Genre case object InvalidGenre extends Genre } val theFountainhead = Book("ISBN: 978-1-4028-9462-6","The Fountainhead","Ayn Rand",Genre.Fiction) val atlasShrugged = Book("ISBN-13 978-1-4028-9462-6","Atlas Shrugged","Ayn Rand",Genre.Fiction) val theCountOfMontecristo = Book("ISBN-13 978-1-4028-9462","The Count Of Montecristo","Alexandre Dumas",Genre.HistoricNovel) val titlelessBook = Book("ISBN-13 978-1-4028-9462-6","","Unknown",Genre.InvalidGenre) Un libro con isbn, título, autor y género.
  • 6. El excepcionalismo imperativo private def validateGenre(g: Genre): Unit = if ( g == Genre.InvalidGenre ) throw new InvalidParameter("Book has invalid genre") private def validateIsbn(isbn: String): Unit = isbn match { case isbnRegex(all @ _*) => () case _ => throw new InvalidParameter("isbn has not a valid format") } private def validateTitle(title: String): Unit = if (title.isEmpty || title == null) throw new InvalidParameter("title must not be empty") private def validateAuthor(author: String): Unit = if (author.isEmpty || author == null) throw new InvalidParameter("author must not be empty") class InvalidParameter(message: String) extends Exception(message) class EmptyBookList(message: String) extends Exception(message)
  • 7. El excepcionalismo imperativo def validateBook(book: Book): Book = { validateGenre(book.genre) validateIsbn(book.isbn) validateTitle(book.title) validateAuthor(book.author) book } def validateBooks(books: List[Book]): List[Book] = if (books == Nil) throw new EmptyBookList("Book list was empty") else { val booksBuffer = new ListBuffer[Book] for (book <- books) { try booksBuffer += validateBook(book) catch { case ex: Exception => println(s"Error $ex") } } booksBuffer.toList }
  • 8. Encapsulando excepciones con Try ● El tipo Try[A] es utilizado para manejar excepciones en métodos. ● Encapsula el resultado en dos subtipos: Success y Failure. ● Success contiene el resultado del método. ● Failure contiene la excepción arrojada. ● Nos permite usar for comprehension. ● Es fail fast en Failure.
  • 9. Encapsulando excepciones con Try private def validateGenre(g: Genre): Try[Genre] = Try { g match { case Genre.InvalidGenre => throw new InvalidParameter("Book has invalid genre") case genre => genre } } private def validateIsbn(isbn: String): Try[String] = Try { isbn match { case isbnRegex(all @ _*) => isbn case _ => throw new InvalidParameter("isbn has not a valid format") } } private def validateTitle(title: String): Try[String] = Try { if (Option(title).forall(_.isEmpty)) throw new InvalidParameter("title must not be empty") else title } private def validateAuthor(author: String): Try[String] = Try { if (Option(author).forall(_.isEmpty)) throw new InvalidParameter("author must not be empty") else author }
  • 10. Encapsulando excepciones con Try import cats.syntax.semigroup._ //Valida los libros y devuelve una lista no vacía en el caso Success def validateBook(b: Book): Try[NonEmptyList[Book]] = for { i <- validateIsbn(b.isbn) a <- validateAuthor(b.author) t <- validateTitle(b.title) g <- validateGenre(b.genre) } yield NonEmptyList.of(Book(i, t, a, g)) //Combina los resultados exitosos del Try en una lista no vacía def validateBooks(bs: List[Book]): Try[NonEmptyList[Book]] = bs match { case Nil => Failure(new EmptyBookList("Book list was empty")) case books => books map validateBook reduce (_ |+| _) }
  • 11. Encapsulando excepciones con Try "BookValidation" should { "Validate a book" in { val validated = validateBook(theFountainhead) validated should === (Success(NonEmptyList(theFountainhead, Nil))) } "Validate books" in { val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged)) validatedBooks should === (Success(NonEmptyList(theFountainhead, atlasShrugged :: Nil))) } "Fail fast error on books" in { val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead)) inside(validatedBooks) { case Failure(ex) => ex.getMessage shouldBe "title must not be empty" } } }
  • 12. Errores como parte del dominio ● Un error en una función no debe tratarse como algo excepcional. ● Excepciones para interacciones con la capa de infraestructura. ● Excepciones rompen con type safety. ● Los errores también son parte del dominio. //No es cierto que validateBook siempre devuelve un Book def validateBook(book: Book): Book = { validateGenre(book.genre) validateIsbn(book.isbn) validateTitle(book.title) validateAuthor(book.author) book }
  • 13. Errores como parte del dominio sealed trait Error extends Product with Serializable { val message: String } case class InvalidParameter(message: String) extends Error case class EmptyBookList(message: String) extends Error Definimos las excepciones anteriormente usadas como ADTs de Error.
  • 14. Manejo de errores con Scala Either ● El tipo Either[A, B] representa el valor de dos tipos posibles: Left o Right ● Convencionalmente se usa el Left para representar errores y Right para representar los aciertos. ● Nos facilita manejar los errores modelados como parte del dominio. ● Se puede usar for comprehension. ● Es fail fast en Left.
  • 15. Manejo de errores con Scala Either private def validateGenre(g: Genre): Either[InvalidParameter, Genre] = g match { case InvalidGenre => Left(InvalidParameter("Book has invalid genre")) case genre => Right(genre) } private def validateIsbn(isbn: String): Either[InvalidParameter, String] = isbn match { case isbnRegex(all @ _*) => Right(isbn) case _ => Left(InvalidParameter("isbn has not a valid format")) } private def validateTitle(title: String): Either[InvalidParameter, String] = if (Option(title).forall(_.isEmpty)) Left(InvalidParameter("title must not be empty")) else Right(title) private def validateAuthor(author: String): Either[InvalidParameter, String] = if (Option(author).forall(_.isEmpty)) Left(InvalidParameter("author must not be empty")) else Right(author)
  • 16. Manejo de errores con Scala Either import cats.syntax.semigroup._ //Valida secuencialmente todos los campos, se detiene en el primer error encontrado. def validateBook(b: Book): Either[InvalidParameter, NonEmptyList[Book]] = for { i <- validateIsbn(b.isbn) a <- validateAuthor(b.author) t <- validateTitle(b.title) g <- validateGenre(b.genre) } yield NonEmptyList.of(Book(i, t, a, g)) //Por ser fail fast, reporta el primer error encontrado pero acumula todos los aciertos. def validateBooks(bs: List[Book]): Either[Error, NonEmptyList[Book]] = bs match { case Nil => Left(EmptyBookList("Book list was empty")) case books => books map validateBook reduce (_ |+| _) }
  • 17. Manejo de errores con Scala Either "BookValidation" should { "Validate a book" in { val validated = validateBook(theFountainhead) validated should === (Right(NonEmptyList(theFountainhead, Nil))) } "Validate books" in { val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged)) validatedBooks should === (Right(NonEmptyList(theFountainhead, atlasShrugged :: Nil))) } "Fail fast error on books" in { val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead)) validatedBooks should === (Left(InvalidParameter("title must not be empty"))) } }
  • 18. Manejo de errores con Cats Validated ● El tipo Validated[A, B] representa el valor de dos tipos posibles: Valid e Invalid. ● Desde el punto de vista semántico, es obvio que Invalid es utilizado para representar los errores y Valid los aciertos. ● Nos facilita manejar los errores modelados como parte del dominio. ● No se puede utilizar en for comprehension. ● Acumula errores en Invalid ( type ValidatedNel[A, B] = Validated[NonEmptyList[A], B] ).
  • 19. Manejo de errores con Cats Validated private def validateGenre(g: Genre): ValidatedNel[InvalidParameter, Genre] = g match { case InvalidGenre => InvalidParameter("Book has invalid genre").invalidNel case genre => genre.validNel } private def validateIsbn(isbn: String): ValidatedNel[InvalidParameter, String] = isbn match { case isbnRegex(all @ _*) => isbn.validNel case _ => InvalidParameter("isbn has not a valid format").invalidNel } private def validateTitle(title: String): ValidatedNel[InvalidParameter, String] = if (Option(title).exists(_.isEmpty)) InvalidParameter("title must not be empty").invalidNel else title.validNel private def validateAuthor(author: String): ValidatedNel[InvalidParameter, String] = if (Option(author).exists(_.isEmpty)) InvalidParameter("author must not be empty").invalidNel else author.validNel
  • 20. Manejo de errores con Cats Validated import cats.syntax.cartesian._ import cats.syntax.semigroup._ //Valida en el producto cartesiano, acumula los errores en cada validación. def validateBook(b: Book): ValidatedNel[InvalidParameter, NonEmptyList[Book]] = ( validateIsbn(b.isbn) |@| validateAuthor(b.author) |@| validateTitle(b.title) |@| validateGenre(b.genre) ) map { case (isbn, author, title, genre) => NonEmptyList.of(Book(isbn, title, author, genre)) } //Puede acumular todos los errores o acumular todos los aciertos. def validateBooks(bs: List[Book]): ValidatedNel[Error, NonEmptyList[Book]] = bs match { case Nil => EmptyBookList("Book list was empty").invalidNel case books => books map validateBook reduce (_ |+| _) }
  • 21. Manejo de errores con Cats Validated "BookValidation" should { "Validate books" in { val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged)) validatedBooks should === (Valid(NonEmptyList(theFountainhead, atlasShrugged :: Nil))) } "Accumulate errors on books" in { val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead)) validatedBooks should === ( Invalid( NonEmptyList(InvalidParameter("title must not be empty"), InvalidParameter("Book has invalid genre") :: InvalidParameter("isbn has not a valid format") :: Nil) ) ) } }
  • 22. Manejo de errores con Cats Ior ● El tipo Ior[A, B] representa el valor de tres tipos posibles: Ior.Right, Ior.Left e Ior.Both. ● La convención con Ior.Left e Ior.Right es igual a la de Either con respecto a la representación de errores y aciertos. ● Ior.Both permite incluir simultáneamente los errores y aciertos ● Nos facilita manejar los errores modelados como parte del dominio. ● Se puede utilizar en for comprehension. ● Es fail fast en Ior.Left y acumula errores en Ior.Both.
  • 23. Manejo de errores con Cats Ior private def validateGenre(g: Genre): IorNel[InvalidParameter, Genre] = g match { case InvalidGenre => Ior.left(NonEmptyList.of(InvalidParameter("Book has invalid genre"))) case genre => Ior.right(genre) } private def validateIsbn(isbn: String): IorNel[InvalidParameter, String] = isbn match { case isbnRegex(all @ _*) => Ior.right(isbn) case _ => Ior.left(NonEmptyList.of(InvalidParameter("isbn has not a valid format"))) } private def validateTitle(title: String): IorNel[InvalidParameter, String] = if (Option(title).exists(_.isEmpty)) Ior.left(NonEmptyList.of(InvalidParameter("title must not be empty"))) else Ior.right(title) private def validateAuthor(author: String): IorNel[InvalidParameter, String] = if (Option(author).exists(_.isEmpty)) Ior.left(NonEmptyList.of(InvalidParameter("author must not be empty"))) else Ior.right(author)
  • 24. Manejo de errores con Cats Ior import cats.syntax.semigroup._ //Valida los campos secuencialmente, se detiene en el primer error. def validateBook(b: Book): IorNel[InvalidParameter, NonEmptyList[Book]] = for { i <- validateIsbn(b.isbn) a <- validateAuthor(b.author) t <- validateTitle(b.title) g <- validateGenre(b.genre) } yield NonEmptyList.of(Book(i, t, a, g)) //A diferencia de Validated, puede acumular errores y aciertos en Ior.Both def validateBooks(bs: List[Book]): IorNel[Error, NonEmptyList[Book]] = bs match { case Nil => Ior.left(EmptyBookList("Book list was empty")) case books => books map validateBook reduce (_ |+| _) }
  • 25. Manejo de errores con Cats Ior "BookValidation" should { "Validate books" in { val validatedBooks = validateBooks(List(theFountainhead, atlasShrugged)) validatedBooks should === (Ior.Right(NonEmptyList(theFountainhead, atlasShrugged :: Nil))) } "Fail fast error on books" in { val validatedBooks = validateBooks(List(titlelessBook, theCountOfMontecristo, theFountainhead, atlasShrugged)) validatedBooks should === ( Ior.Both( NonEmptyList(InvalidParameter("title must not be empty"),InvalidParameter("isbn has not a valid format") :: Nil), NonEmptyList(theFountainhead, atlasShrugged :: Nil) ) ) } }
  • 26. Conclusiones ● En una función no se deben arrojar excepciones, se pierde transparencia referencial. ● Se favorece la modelación de errores en el dominio. ● Try es fail fast, no es expresivo en cuanto a los errores que encapsula y se puede usar cuando se depende de métodos de librerías java. ● Either es fail fast y puede acumular aciertos. ● Validated acumula errores, no se puede usar en for comprehensions y puede acumular aciertos. ● Ior es el más flexible: es fail fast en Ior.Left, acumula errores en Ior.Both y puede acumular aciertos en Ior.Right e Ior.Both.