Translate

sábado, 2 de julio de 2022

Mónadas en Cats parte 14

cats.Eval es una mónada que nos permite abstraernos sobre diferentes modelos de evaluación. Por lo general, hablamos de dos modelos de este tipo: eager y lazy, también llamados llamada por valor y llamada por nombre, respectivamente. Eval también permite memorizar un resultado, lo que nos brinda una evaluación de llamada por necesidad. Eval también es seguro para la pila, lo que significa que podemos usarlo en recursiones muy profundas sin explotar la pila.

¿Qué significan estos términos para modelos de evaluación? Veamos algunos ejemplos. Veamos primero Scala vals. Podemos ver el modelo de evaluación utilizando un cálculo con un efecto secundario visible. En el siguiente ejemplo, el código para calcular el valor de x ocurre en el lugar donde se define en lugar de acceder. Acceder a x recupera el valor almacenado sin volver a ejecutar el código.

val x = {

    println("Computing X")

    math.random

}

// Computing X

// x: Double = 0.0396922778013471

x // first access

// res0: Double = 0.0396922778013471

x // second access

// res1: Double = 0.0396922778013471


Este es un ejemplo de evaluación de llamada por valor:

• el cómputo se evalúa en el punto donde se define (eager); y

• el cálculo se evalúa una vez (se memoriza).

Veamos un ejemplo usando un def. El código para calcular y a continuación no se ejecuta hasta que lo usamos y se vuelve a ejecutar en cada acceso:


def y = {

    println("Computing Y")

    math.random

}

y // first access

// Computing Y

// res2: Double = 0.5270290953284378 

y // second access

// Computing Y

// res3: Double = 0.348549829974959


Estas son las propiedades de la evaluación llamada por nombre:

• el cálculo se evalúa en el punto de uso (lazy); y

• el cálculo se evalúa cada vez que se utiliza (no se memoriza).

Por último, pero no menos importante, los valores perezosos son un ejemplo de evaluación de llamada por necesidad. El código para calcular z a continuación no se ejecuta hasta que lo usamos por primera vez (perezoso). Luego, el resultado se almacena en caché y se reutiliza en accesos posteriores (memorizados):


lazy val z = {

    println("Computing Z")

    math.random

}

z // first access

// Computing Z

// res4: Double = 0.6672110951657263 // first access

z // second access

// res5: Double = 0.6672110951657263


Resumamos. Hay dos propiedades de interés:

• evaluación en el punto de definición (ansioso) versus en el punto de uso (perezoso); y

• los valores se guardan una vez evaluados (memorizados) o no (no memorizados).

Hay tres posibles combinaciones de estas propiedades:

• llamada por valor que está ansiosa y memorizada;

• llamada por nombre que es perezosa y no memorizada; y

• llamar por necesidad, que es perezoso y memorizado.

La combinación final, ansiosa y no memorizada, no es posible.


Eval tiene tres subtipos: Now, Always, y Later. Corresponden a llamada por valor, llamada por nombre y llamada por necesidad, respectivamente. Los construimos con tres métodos constructores, que crean instancias de las tres clases y las devuelven escritas como Eval:

import cats.Eval

val now = Eval.now(math.random + 1000)

// now: Eval[Double] = Now(1000.7009661848473)

val always = Eval.always(math.random + 3000)

// always: Eval[Double] = cats.Always@2a4e7955

val later = Eval.later(math.random + 2000)

// later: Eval[Double] = cats.Later@7684da18


Podemos extraer el resultado de un Eval usando su método de valor:


now.value

// res6: Double = 1000.7009661848473

always.value

// res7: Double = 3000.5158510235524

later.value

// res8: Double = 2000.6995448328964


Cada tipo de Eval calcula su resultado utilizando uno de los modelos de evaluación definidos anteriormente. Eval.now captura un valor ahora mismo. Su semántica es similar a un val: ansioso y memorizado:

val x = Eval.now{

println("Computing X")

math.random

}

// Computing X

// x: Eval[Double] = Now(0.6969571260771719)

x.value // first access

// res10: Double = 0.6969571260771719 // first access

x.value // second access

// res11: Double = 0.6969571260771719


Eval.always captura un cálculo perezoso, similar a una definición:


val y = Eval.always{

println("Computing Y")

math.random

}

// y: Eval[Double] = cats.Always@6d355284

y.value // first access

// Computing Y

// res12: Double = 0.8575236846076497 // first access

y.value // second access

// Computing Y

// res13: Double = 0.15716382484701563


Finalmente, Eval.later captura un cálculo memorizado perezoso, similar a un valor perezoso:


val z = Eval.later{

println("Computing Z")

math.random

}

// z: Eval[Double] = cats.Later@3429dabc

z.value // first access

// Computing Z

// res14: Double = 0.5149108999064906 // first access

z.value // second access

// res15: Double = 0.5149108999064906



viernes, 1 de julio de 2022

[eBook] The Secret to Modern Application Security

 

EBOOK

[eBook] The Secret to Modern Application Security

Hi Emanuel,

Every business strives for sustained agility. Many see the benefits of a distributed microservices architecture, using modern applications and APIs to keep pace with the competition and customer demand. In fact, 85% of new workloads are deployed in containers and 83% of internet traffic is made up of API calls. In this eBook you will learn how NGINX App Protect WAF can be deployed with NGINX Ingress Controller to protect your apps and APIs in Kubernetes clusters, enforce security policies, inspect traffic, and eliminate threats before they cross the perimeter, allowing you to innovate at speed without compromising on security.

In this eBook you will learn:

  • Why integrating security automation into your CI/CD pipeline is key to the agile software development of your applications and APIs
  • Ways the performance of your application directly impacts customer experience and sales
  • About implementing strong security into an application’s operating system using NGINX App Protect WAF, which supports multiple modern application deployment topologies
  • How NGINX App Protect WAF works with NGINX Ingress Controller as the gatekeeper for an entire Kubernetes cluster and supports enforcing policies at a granular level within the cluster

martes, 28 de junio de 2022

Mónadas en Cats parte 13

Cats proporciona una class type adicional llamada MonadError que abstrae los tipos de datos similares a los que se usan para el manejo de errores. MonadError proporciona operaciones adicionales para generar y manejar errores.

package cats

trait MonadError[F[_], E] extends Monad[F] {

// Lift an error into the `F` context:

def raiseError[A](e: E): F[A]

// Handle an error, potentially recovering from it:

def handleErrorWith[A](fa: F[A])(f: E => F[A]): F[A]

// Handle all errors, recovering from them:

def handleError[A](fa: F[A])(f: E => A): F[A]

// Test an instance of `F`,

// failing if the predicate is not satisfied:

def ensure[A](fa: F[A])(e: E)(f: A => Boolean): F[A]

}


MonadError se define en términos de dos parámetros de tipo:

• F es el tipo de la mónada;

• E es el tipo de error contenido en F.

Para demostrar cómo encajan estos parámetros, aquí hay un ejemplo en el que instanciamos la clase de tipo Either:


import cats.MonadError

import cats.instances.either._ // for MonadError

type ErrorOr[A] = Either[String, A]

val monadError = MonadError[ErrorOr, String]


Los dos métodos más importantes de MonadError son raiseError y handleErrorWith. raiseError es como el método puro para Monad excepto que crea una instancia que representa una falla:


val success = monadError.pure(42)

// success: ErrorOr[Int] = Right(42)

val failure = monadError.raiseError("Badness")

// failure: ErrorOr[Nothing] = Left("Badness")


handleErrorWith es el complemento de raiseError. Nos permite consumir un error y (posiblemente) convertirlo en un éxito, similar al método de recuperación de Future:


monadError.handleErrorWith(failure) {

case "Badness" =>

monadError.pure("It's ok")

case _ =>

monadError.raiseError("It's not ok")

}

// res0: ErrorOr[String] = Right("It's ok")


Si sabemos que podemos manejar todos los errores posibles, podemos usar handleWith.


monadError.handleError(failure) {

case "Badness" => 42

case _ => -1

}

// res1: ErrorOr[Int] = Right(42)


Hay otro método útil llamado ensure que implementa un comportamiento similar al de un filtro. Probamos el valor de una mónada exitosa con un predicado y especificamos un error para generar si el predicado devuelve falso:


monadError.ensure(success)("Number too low!")(_ > 1000)

// res2: ErrorOr[Int] = Left("Number too low!")


Cats proporciona instancias de MonadError para numerosos tipos de datos, incluidos Either, Future y Try. La instancia de Either se puede personalizar para cualquier tipo de error, mientras que las instancias de Future y Try, siempre representan errores como Throwables:


import scala.util.Try

import cats.instances.try_._ // for MonadError

val exn: Throwable = new RuntimeException("It's all gone wrong")

exn.raiseError[Try, Int]

// res6: Try[Int] = Failure(java.lang.RuntimeException: It's all gone wrong)

sábado, 25 de junio de 2022

Resultado de la encuesta 2022 de StackOverflow

StackOverflow hace una encuesta cada año a los desarrolladores y es un buen termómetro para ver como va evolucionando la industria: 

Cosas a destacar o que me llamaron la atención:

Lenguajes de programación más usados: Javascript, Python, Typescript y Java. Acá me llamo la atención que Typescript le gane a java. 


Base de datos: Mysql, postgresql, SQLite, mongodb. SQLite le gana a mongo, eso es raro.


Más amados y más odiados aparezca Delphi


Y por último entre los lenguajes mejor pagos, hay 6 lenguajes funcionales (no me llamo la atención pero lo quiero marcar) :  

Y te llamo la atención algo más? 

Dejo link: 

https://survey.stackoverflow.co/2022/?utm_source=so-owned&utm_medium=announcement-banner&utm_campaign=dev-survey-2022&utm_content=results

jueves, 23 de junio de 2022

Agregar código java a un proyecto Clojure en Leiningen


 Quiero hacer unas clases en java y utilizarlas en mis funciones clojure. Es muy fácil, tengo que agregar   :java-source-paths a mi proyecto y ya toma las clases.  

Veamos un ejemplo

(defproject ejemplo "0.1.0-SNAPSHOT"

  :description "FIXME: write description"

  :url "http://example.com/FIXME"

  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"

            :url "https://www.eclipse.org/legal/epl-2.0/"}

  :dependencies [[org.clojure/clojure "1.10.3"],

                 ...                 ]

  :java-source-paths ["src-java"]

  :main com.assembly.ejemplo.core

  :aot :all

  :target-path "target/%s"

  :profiles {:uberjar {:aot :all

                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})


Y listo!!

martes, 21 de junio de 2022

Como chequear si un registro esta siendo cacheado por Hibernate en una aplicación Spring boot.


Necesitaba ver si un registro estaba siendo cacheado por hibernate es decir JPA, en una aplicación spring boot. 

Hice lo que cualquiera hubiera hecho, puse show-sql en true, corrí un test que busca 2 veces el registro y me fije en el log que no hubiera 2 selects. Fácil pero poco científico, estaría bueno hacer un test que pruebe esto, y bueno hice esto : 


@RunWith(SpringJUnit4ClassRunner::class)

@SpringBootTest(classes = [Application::class])

class EjemploRepositoryTest {


    @Autowired

    lateinit var ejemploRepository: EjemploRepository


    @Autowired

    lateinit var entityManagerFactory: EntityManagerFactory


    @Test

    fun `find a Ejemplo from Empty cache`() {

        val ejemplo= getEjemplo()

        val cache = entityManagerFactory.cache

        Assert.assertFalse(cache.contains(Ejemplo::class.java, ejemplo.id))

    }


    @Test

    fun `find a Ejemplo from cache`() {

        val ejemplo= getEjemplo()

        saveAndFind(ejemplo)


        val cache = entityManagerFactory.cache


        Assert.assertTrue(cache.contains(Ejemplo::class.java, ejemplo.id))

    }


    private fun saveAndFind(ejemplo: Ejemplo): Ejemplo{

        ejemploRepository.save(ejemplo)

        return ejemploRepository.findById(ejemplo.id).get()

    }


    private fun getEjemplo(): Ejemplo{

        return  ... //Aca construimos un ejemplo 

    }


}

Y listo!!

lunes, 20 de junio de 2022

Mónadas en Cats parte 12

Either se usa típicamente para implementar el manejo de errores rápidos. Secuenciamos los cálculos utilizando flatMap como de costumbre. Si un cálculo falla, los cálculos restantes no se ejecutan:

for {

a <- 1.asRight[String]

b <- 0.asRight[String]

c <- if(b == 0) "DIV0".asLeft[Int]

else (a / b).asRight[String]

} yield c * 100

// res21: Either[String, Int] = Left("DIV0")

Cuando usamos Either para el manejo de errores, necesitamos determinar qué tipo queremos usar para representar los errores. Podríamos usar Throwable para esto:


type Result[A] = Either[Throwable, A]


Esto nos da una semántica similar a scala.util.Try. El problema, sin embargo, es que Throwable es un tipo extremadamente amplio. No tenemos (casi) idea de qué tipo de error ocurrió.

Otro enfoque es definir un tipo de datos algebraicos para representar los errores que pueden ocurrir en nuestro programa:

object wrapper {

   sealed trait LoginError extends Product with Serializable

   final case class UserNotFound(username: String) extends LoginError

   final case class PasswordIncorrect(username: String) extends LoginError

   case object UnexpectedError extends LoginError

}; 

import wrapper._


case class User(username: String, password: String)

type LoginResult = Either[LoginError, User]


Este enfoque resuelve los problemas que vimos con Throwable. Nos da un conjunto fijo de tipos de errores esperados. También obtenemos la seguridad de la comprobación exhaustiva de cualquier coincidencia de patrones que hagamos:

// Choose error-handling behaviour based on type:

def handleError(error: LoginError): Unit =

    error match {

        case UserNotFound(u) => println(s"User not found: $u")

        case PasswordIncorrect(u) => println(s"Password incorrect: $u")

        case UnexpectedError => println(s"Unexpected error")

    }

val result1: LoginResult = User("dave", "passw0rd").asRight

// result1: LoginResult = Right(User("dave", "passw0rd"))

val result2: LoginResult = UserNotFound("dave").asLeft

// result2: LoginResult = Left(UserNotFound("dave"))

result1.fold(handleError, println)

// User(dave,passw0rd)

result2.fold(handleError, println)

// User not found: dave


sábado, 18 de junio de 2022

Crear un proyecto Spring boot, con Leiningen y Clojure


La idea es crear un proyecto spring boot, con Clojure y Leiningen. (ya lo dice el titulo)

Primero hacemos un proyecto hello word con Leiningen (ojo tienen que tener Leiningen instalado, esta bueno instalarlo con sdkman, así :  sdk install leiningen) 

lein new app ejemplo

Luego agregamos las dependencias de spring boot al proyecto, para que quede algo así: 

(defproject github "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.10.3"],
                 [org.springframework.boot/spring-boot-starter-web "2.6.7"],
                 [org.springframework.boot/spring-boot-configuration-processor "2.6.7"]]
  :main com.assembly.example.core
  :aot :all
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})

Ojo, tambien hay que agregar :aot y :all 

Ahora hacemos el Application, yo modifique el hello wold que vino por default, pero si lo hacen tengan cuidado de ponerlo en un paquete. 

(ns com.assembly.example.core
  (:import (org.springframework.boot SpringApplication))
  (:gen-class
    :name ^{org.springframework.boot.autoconfigure.SpringBootApplication []
            org.springframework.context.annotation.ComponentScan {:basePackages ["com.assembly.example"]}}
    com.assembly.example.core.Application
    :main true)
  )

(defn -main []
  (SpringApplication/run (Class/forName "com.assembly.example.core.Application") (into-array String '()))
  )

Y ahora hacemos un endpoint, en este ejemplo voy a hacer un hola mundo : 

(ns com.assembly.exanple.controller.greet

  (:import (org.springframework.web.bind.annotation PathVariable RequestMapping RequestMethod RestController)

           (org.springframework.http ResponseEntity))

  )


(gen-class

  :name ^{RestController {}

          RequestMapping {:value ["/v1/greet"]}} com.assembly.exanple.controller.greet.GreeterEndPoint

  :methods [[^{RequestMapping {:value ["/hello"]

                               :method [RequestMethod/GET]}} sayHello [] Object ]

            [^{RequestMapping {:value ["/helloto/{name}"]

                               :method [RequestMethod/GET]}} sayHelloTo [^{PathVariable {:value "name"}} String] Object ]

            ]

  :state injected

  :init init

)


(defn -init

  "Initialize the class by setting the state to an empty map, which can be populated with injected dependencies."

  []

  [[] (atom {})])


(defn -sayHello

  [this]

  (ResponseEntity/ok "Hello"))


(defn -sayHelloTo

  [this name]

  (ResponseEntity/ok (str "Hello " name)))


Y listo, si corremos el main, vamos a levantar el tomcat embebido de spring y vamos a : 

http://localhost:8080/v1/greet/hello

y veremos como nos saluda spring boot con clojure!! 

viernes, 17 de junio de 2022

[FREE EBOOK] Understanding Databases (Free eBook)

 

Start Today

 

Free eBook:  Understanding Databases 


Deploy High-Performance Database Clusters in Modern Applications. Develop a high-level understanding of industry-standard databases, the design of database architectures, and different deployment methods in the cloud.


 
Download Now
Your Suggestions
Any ideas or suggestions? Shoot us an email at support@webcodegeeks.com

[O’Reilly Ebook] The Complete NGINX Cookbook – 2022 Edition

 

EBOOK

[O’Reilly Ebook] The Complete NGINX Cookbook – 2022 Edition

Hi Emanuel,

The NGINX Cookbook is the “go-to” guide to NGINX configurations, updated for 2022 with new chapters on optimizing container environments and using NGINX Instance Manager. Check out these brand-new recipes as well as updates for the most popular NGINX deployments: load balancing, security, cloud deployment, containers and microservices, service mesh, API gateway, automation, and more.

In this eBook you will learn:

  • Updated solutions for more than 100 real-world, modern application delivery use cases
  • How to secure your applications and APIs and mitigate DDoS and Layer 7 attacks
  • How to optimize and secure microservices and container environments
  • About using NGINX Instance Manager to automate your management of NGINX instances

[eBook] Managing Kubernetes Traffic with NGINX: A Practical Guide

 

EBOOK

https://interact.f5.com/rs/653-SMC-783/images/EBK - Managing Kubernetes Traffic with F5 NGINX - 760x284.png

Hi Emanuel,

Learn everything you need to deploy and manage a production-grade Kubernetes environment with NGINX Ingress Controller and NGINX Service Mesh. Our new eBook includes thorough explanations, diagrams, and code samples for a broad range of use cases, including traffic control and splitting, tracing and monitoring, and single sign-on.

In this eBook you will learn:

  • How to install and configure NGINX Ingress Controller and NGINX Service Mesh and how to migrate from the Kubernetes community's Ingress controller
  • Techniques for traffic control and splitting, including rate limiting, blue‑green deployment, and A/B testing
  • About integrating with third‑party tracing and monitoring tools like Jaeger, Prometheus, and AWS CloudWatch
  • How to protect Kubernetes apps with identity solutions and NGINX App Protect WAF