Translate

martes, 3 de septiembre de 2019

Optional, la solución de Java 8 para NullPointerException, Parte 3


El patrón Optional es un patrón nacido en los lenguajes funcionales (sobre todo Scala), por lo que usarlo de una manera imperativa hace que no sea eficiente.

Optional<Double> getDurationOfAlbumWithName(String name) {
    Optional<Double> duration = getAlbum(name)
            .flatMap((album) -> getAlbumTracks(album.getName()))
            .map((tracks) -> getTracksDuration(tracks));
    return duration;
}

Usando las funciones map y flatMap acortaríamos un código relativamente complicado a solo 3 lineas, vamos a repasar paso por paso donde está el truco.

Para ello vamos a ver el método map de la clase Optional que es lo que hace:

public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
    Objects.requireNonNull(mapper);
    if (!isPresent())
        return empty();
    else {
        return Optional.ofNullable(mapper.apply(value));
    }
}

Dentro de esa signatura complicada se encuentra algo bastante sencillo, es un método que admite una función, la cual a su vez admite un Optional, esta función ha de devolver un valor del tipo que acepta. Lo que hace la función es más fácil de ver, comprueba si el Optional está vacío, si lo está devuelve un Optional vacío y si no, aplica la función que le hemos pasado por parámetro, pasándole el valor del Optional

Es decir, si el Optional está vacío, el método map no hace nada, esto es primordial para poder concatenar operaciones sin necesidad de comprobar a cada momento si el
Optional está vacío.

Antes de seguir con ejemplo, comentar el uso del método flatMap, y es que cuando queremos encadenar distintas operaciones que devuelvan Optional, es necesario usar
flatMap ya que si no acabaríamos teniendo un Optional<Optional<Double>>

Si lo extraemos paso a paso, podemos ver que no hay magia por ningún lado:

Optional<Album> albumOptional = getAlbum(name);

Optional<List<Track>> listOptional = albumOptional.flatMap((album) ->  getAlbumTracks(album.getName()));

Optional<Double> durationOptional = listOptional.map((tracks) -> getTracksDuration(tracks));


Optional, la solución de Java 8 para NullPointerException, Parte 2

Vamos a ver como podemos usar Optional de manera imperativa, es decir como java fue concebido

Pongamos el caso siguiente, tenemos un método que obtiene un disco a partir de un nombre, puede darse el caso de que no se encuentre ningún disco con ese nombre, sin Optional tendríamos dos opciones:

  • Devolver null en caso de que no encontrásemos el disco. 
  • Lanzar una excepción indicando que no se ha encontrado el disco.


Con Optional se nos abre la tercera opción:

  • public Optional<Album> getAlbum(String artistName)


A la hora de usar este método, de la manera imperativa haríamos lo siguiente.

Album album;
Optional<Album> albumOptional = getAlbum("Random Memory Access");
if(albumOptional.isPresent()){
    album = albumOptional.get();
}else{
    // Avisar al usuario de que no se ha encontrado el album
}

Esto ya es un avance respecto a los null, ya que estamos indicando explícitamente al usuario de la API de que es posible que no se encuentre el album y de que es necesario que actúe en caso de error.

El problema de esto viene cuando queremos ejecutar varias operaciones consecutivas que devuelvan null. Para ilustrar este caso imaginémonos que después de obtener el Album queremos obtener las canciones del album y finalmente obtener la duración total del album.

private static Optional<Double> getDurationOfAlbumWithName(String name) {
    Album album;
    Optional<Album> albumOptional = getAlbum(name);
    if (albumOptional.isPresent()) {
        album = albumOptional.get();
        Optional<List<Track>> tracksOptional = getAlbumTracks(album.getName());
        double duration = 0;
        if (tracksOptional.isPresent()) {
            List<Track> tracks = tracksOptional.get();
            for (Track track : tracks) {
                duration += track.getDuration();
            }
            return Optional.of(duration);
        } else {
            return Optional.empty();
        }
    } else {
        return Optional.empty();
    }

Como podemos observar esto se nos puede ir de las manos muy rápidamente, cada operación sucesiva que hagamos sobre un método que puede devolver un valor vacío se convierte en un nivel más de anidación.

Llegados a este punto podemos pensar en usar excepciones, las cuales al menos nos permiten tener todas las acciones a la misma altura dentro de un try y resolver los distintos errores en el catch. Pero esto no es tan flexible tampoco, es hora de pensar en funcional.


Optional, la solución de Java 8 para NullPointerException

Quien no ha sufrido un NullPointerException, no ha programado en Java, a veces en partes del código donde parece imposible que sucedan, posiblemente ese NullPointerException se ha estado gestando desde otras partes lejanas de la aplicación.

Para corregir estos errores, algunos lenguajes han decidido eliminar por completo los temidos null, pero para aquellos lenguajes que en su momento lo incluyeron, no es tan fácil. De ahí la existencia de alternativas cómo el patrón Optional, el cual nos permite mostrar de manera explicita (mediante el sistema de tipos) la posibilidad de que un método pueda no devolver el valor deseado. Esto nos obliga a controlar la posible ausencia de valor de manera explicita, permitiéndonos elegir un valor alternativo en caso de dicha ausencia o simplemente realizar otra acción.

En Java 8 este patrón se encapsula en la clase Optional, la cual incluye muchos de los métodos necesarios para trabajar con este patrón.

public final class Optional<T>{}

Lo más importante es la signatura de la clase, en la cual podemos ver que es una clase genérica que nos permite que el objeto que contenga (o no) sea de cualquier clase.

Optional tiene un constructor privado, y nos proporciona tres métodos factoría estáticos para instanciar la clase. Siendo el método .of el que nos permite recubrir cualquier objeto en un optional.

public static<T> Optional<T> empty()
public static <T> Optional<T> ofNullable(T value)
public static <T> Optional<T> of(T value)

Los otros dos métodos nos permiten recubrir un valor nulo o devolver un objeto Optional vacío en caso de que queramos avisar de la ausencia de valor. La opción de recubrir un nulo viene dada principalmente para permitirnos trabajar con APIs que hacen uso de nulos para avisar de estas ausencias de valor.

El método isPresent es el equivalente a variable == null y cómo el propio nombre indica nos dice si el objeto Optional contiene un valor o está vacío. Este método se usa principalmente si trabajamos de manera imperativa con Optional. Y el método get es el encargado de devolvernos el valor, devolviendo una excepción si no estuviera presente.

  • public Optional<T> filter(Function f)
  • public<U> Optional<U> map(Function f)
  • public<U> Optional<U> flatMap(Function f)


Estos tres métodos hacen que trabajar con Optional sea verdaderamente interesante, nos da la posibilidad de encadenar distintas operaciones que devuelvan Optional sin tener que estar comprobando si el valor está presente después de cada operación.

  • public T orElse(T other)
  • public T orElseGet(Function f)
  • public <X extends Throwable> T orElseThrow(Function f)

Finalmente estos métodos nos permiten finalizar una serie de operaciones, teniendo tres maneras:

  • La primera orElse nos devuelve el valor o si no devolverá el valor que le demos. 
  • orElseGet, nos devolverá el valor si está presente y si no, invocará la función que le pasemos por parámetro y devolverá el resultado de dicha función. 
  • Y finalmente orElseThrow, nos devolverá el valor si está presente y si invocará la función que le pasemos, la cual tiene que devolver una excepción y lanzará dicha excepción. Esto nos ayudará a trabajar en conjunción con APIs que todavía usen excepciones.



domingo, 1 de septiembre de 2019

Inyección de dependencia de tiempo de compilación parte 2


Y como dije en el post anterior vamos a ver el cake pattern.



En algún momento, crear todo el grafo de objetos de "todo el mundo" será poco práctico y el código será grande y difícil de leer. Entonces deberíamos dividirlo de alguna manera en pedazos más pequeños. Afortunadamente, los trait de Scala encajan perfectamente para esa tarea; se pueden usar para dividir el código de creación del grafo de objetos.

En cada trait, que para el propósito de esta tarea también se llama "módulo", se crea parte del grafo de objetos. Todo se vuelve a combinar más tarde al unir todos los traits necesarios.

Puede haber varias reglas sobre cómo dividir el código en módulos. Un buen lugar para comenzar es considerar crear un módulo precableado por paquete. Cada paquete debe contener un grupo de clases que compartan o implementen alguna funcionalidad específica. Lo más probable es que estas clases cooperen de alguna manera y, por lo tanto, pueden conectarse.

El beneficio adicional de enviar un paquete no solo con el código, sino también con un fragmento de grafo de objeto conectado, es que es más claro cómo se debe usar el código. No hay requisitos para usar el módulo.

Sin embargo, tales módulos generalmente no pueden existir de manera independiente: muy a menudo dependerán de algunas clases de otros módulos. Hay dos formas de expresar dependencias.

Expresar dependencias a través de miembros abstractos
Como cada módulo es un trait, es posible dejar algunas dependencias sin definir, como miembros abstractos. Dichos miembros abstractos se pueden usar al realizar la conección (ya sea manualmente o mediante la macro de MacWire), pero no es necesario dar la implementación específica.

Cuando todos los módulos se combinan en la aplicación final, el compilador verificará que todas las dependencias definidas como miembros abstractos estén definidas.

Tenga en cuenta que podemos declarar a todos los miembros abstractos como defs, ya que pueden implementarse más tarde como vals, vals lazy o dejarse como defs. Usar un def mantiene todas las opciones posibles.

La conexión para nuestro código de ejemplo lo vamos a dividir de la siguiente manera; las clases ahora se agrupan en paquetes:

package shunting {
   class PointSwitcher()
   class TrainCarCoupler()
   class TrainShunter(
      pointSwitcher: PointSwitcher,
      trainCarCoupler: TrainCarCoupler)
}

package loading {
   class CraneController()
   class TrainLoader(
      craneController: CraneController,
      pointSwitcher: PointSwitcher)
}

package station {
   class TrainDispatch()

   class TrainStation(
      trainShunter: TrainShunter,
      trainLoader: TrainLoader,
      trainDispatch: TrainDispatch) {

      def prepareAndDispatchNextTrain() { ... }
   }
}

Cada paquete tiene un módulo de trait correspondiente. Tenga en cuenta que la dependencia entre los paquetes de derivación y carga se expresa utilizando un miembro abstracto:

package shunting {
   trait ShuntingModule {
      lazy val pointSwitcher = wire[PointSwitcher]
      lazy val trainCarCoupler = wire[TrainCarCoupler]
      lazy val trainShunter = wire[TrainShunter]
   }
}

package loading {
   trait LoadingModule {
      lazy val craneController = wire[CraneController]
      lazy val trainLoader = wire[TrainLoader]

      // dependency of the module
      def pointSwitcher: PointSwitcher
   }
}

package station {
   trait StationModule {
      lazy val trainDispatch = wire[TrainDispatch]

      lazy val trainStation = wire[TrainStation]

      // dependencies of the module
      def trainShunter: TrainShunter
      def trainLoader: TrainLoader
   }
}

object TrainStation extends App {
   val modules = new ShuntingModule
      with LoadingModule
      with StationModule

   modules.trainStation.prepareAndDispatchNextTrain() 
}

Para implementar dependencias de esta manera, se necesita una convención de nomenclatura coherente, ya que el miembro abstracto se concilia con el nombre de implementación. Nombrar los valores igual que las clases, pero con la letra inicial en minúscula es un buen ejemplo de tal convención.


Expresar dependencias a través de autotipos
Otra forma de expresar dependencias es mediante auto-tipos o extendiendo otros módulos de traits. De esta manera, se crea una conexión mucho más fuerte entre los dos módulos, en lugar del enfoque de miembro abstracto acoplado más flexible, sin embargo, en algunas situaciones es deseable (por ejemplo, cuando se tiene una interfaz de módulo con implementaciones múltiples).

Por ejemplo, podríamos expresar la dependencia entre los módulos de derivación y carga y el módulo de estación extendiendo el módulo de rasgos, en lugar de usar los miembros abstractos:

package shunting {
   trait ShuntingModule {
      lazy val pointSwitcher = wire[PointSwitcher]
      lazy val trainCarCoupler = wire[TrainCarCoupler]
      lazy val trainShunter = wire[TrainShunter]
   }
}

package loading {
   trait LoadingModule {
      lazy val craneController = wire[CraneController]
      lazy val trainLoader = wire[TrainLoader]

      // dependency expressed using an abstract member
      def pointSwitcher: PointSwitcher
   }
}

package station {
   // dependencies expressed using extends
   trait StationModule extends ShuntingModule with LoadingModule {
      lazy val trainDispatch = wire[TrainDispatch]

      lazy val trainStation = wire[TrainStation]
   }
}

object TrainStation extends App {
   val modules = new ShuntingModule
      with LoadingModule
      with StationModule

   modules.trainStation.prepareAndDispatchNextTrain() 


Se lograría un efecto muy similar utilizando un auto-tipo.

Este enfoque también puede ser útil para crear módulos más grandes a partir de múltiples más pequeños, sin la necesidad de volver a expresar las dependencias de los módulos más pequeños. Simplemente defina un trait de módulo más grande que extienda un número de trait de módulo más pequeño.

Composing modules
Los módulos también se pueden combinar usando la composición, es decir, puede anidar módulos como miembros y usar dependencias definidas en los módulos anidados para conectar objetos.

Por ejemplo, podemos agregar un complemento a nuestra aplicación de gestión de trenes que permitirá recopilar estadísticas:

package stats {
   class LoadingStats(trainLoader: TrainLoader)
   class ShuntingStats(trainShunter: TrainShunter)

   class StatsModule(
      shuntingModule: ShuntingModule,
      loadingModule: LoadingModule) {

      import shuntingModule._
      import loadingModule._

      lazy val loadingStats = wire[LoadingStats]
      lazy val shuntingStats = wire[ShuntingStats]    
   }   
}

Tenga en cuenta las declaraciones de importación, que traen cualquier dependencia definida en los módulos anidados al alcance.

Esto se puede acortar aún más mediante el uso de una anotación experimental @Module para los rasgos / clases del módulo; Los miembros de módulos anidados con esa anotación se tendrán en cuenta automáticamente durante la inyección:

package loading {
   @Module
   trait LoadingModule { ... }
}

package shunting {
   @Module
   trait ShuntingModule { ... }
}

package stats {
   class LoadingStats(trainLoader: TrainLoader)
   class ShuntingStats(trainShunter: TrainShunter)

   class StatsModule(
      shuntingModule: ShuntingModule,
      loadingModule: LoadingModule) {

      lazy val loadingStats = wire[LoadingStats]
      lazy val shuntingStats = wire[ShuntingStats]    
   }   
}

En este escenario, no se necesitan importaciones.


Factor y pila

Muchas veces necesitamos cambiar la pila o reorganizarla para eso tenemos muchas palabras: dup , drop , nip , swap , over , rot , y pick. Veamos con ejemplos como podemos utilizarlas :

IN: scratchpad 1 dup ! duplica el valor
--- Data stack:
1
1
IN: scratchpad clear

IN: scratchpad 1 2 drop ! Elimina el ultimo valor (el tope de la pila)
--- Data stack:
1
IN: scratchpad clear

IN: scratchpad 1 2 nip ! borra el segundo valor
--- Data stack:
2
IN: scratchpad clear

IN: scratchpad 1 2 swap ! cambia de posición 2 valores
--- Data stack:
2
1
IN: scratchpad clear

IN: scratchpad 1 2 over ! duplica el segundo valor y lo pone al tope de la pila
--- Data stack:
1
2
1
IN: scratchpad clear

IN: scratchpad 1 2 3 rot ! rota los valores
--- Data stack:
2
3
1

Citas y condiciones en Factor


Similar a otros lenguajes, las funciones pueden ser mantenidas en variables, bueno en la pila. Estas clausuras se denominan “quotation” o citas y se escribe delimitado por [ ] .

[ 42 + ]

Veamos un ejemplo :

IN: scratchpad 20
--- Data stack:
20

IN: scratchpad [ 42 + ]
--- Data stack:
20
[ 42 + ]

IN: scratchpad call
--- Data stack:
62

Las citas son importantes y se utilizan para las condiciones.

La palabra if recibe como parámetro 1 condición y 2 citas y ejecuta el primero si es verdadero y el segundo de lo contrario :

IN: scratchpad 10 0 > [ "pos" ] [ "neg" ] if .
"pos"
IN: scratchpad -5 0 > [ "pos" ] [ "neg" ] if .
"neg"
IN: scratchpad "cool" [ "yes" ] [ "no" ] if .
"yes"

Por si hay dudas el if tiene la forma :

<condition> <true branch> <false branch> if

También podemos utilizar la palabra ? :

IN: scratchpad 10 0 > "pos" "neg" ? .
"pos"
IN: scratchpad -5 0 > "pos" "neg" ? .
"neg"

La palabra when y unless se puede utilizar con una sola cita :

IN: scratchpad 10 0 > [ "pos" . ] when
"pos"
IN: scratchpad -5 0 > [ "neg" . ] unless
"neg"

sábado, 31 de agosto de 2019

Libros de Java Code Geeks

Download IT Guides!

 
Amazon S3 (Simple Storage Service) is a web service offered by Amazon Web Services. Amazon S3 provides storage through web services interfaces (REST, SOAP, and BitTorrent). Amazon...
238c82c3-cdd7-4492-a23c-39e18a1f8c21.png
 
 
JUnit is a unit testing framework to write repeatable tests. JUnit has been important in the development of test-driven development, and is one of a family of unit testing frameworks...
238c82c3-cdd7-4492-a23c-39e18a1f8c21.png
 
 
Apache Tomcat, often referred to as Tomcat, is an open-source web server developed by the Apache Software Foundation (ASF). Tomcat implements several Java EE specifications including Java...
238c82c3-cdd7-4492-a23c-39e18a1f8c21.png
 
 
With no doubts, Java 8 release is the greatest thing in the Java world since Java 5 (released quite a while ago, back in 2004). It brings tons of new features to the Java as a language,...
238c82c3-cdd7-4492-a23c-39e18a1f8c21.png
 

martes, 27 de agosto de 2019

Datos en Factor

Sigo con Factor y sus pilas.

Factor usa datos estandar como String, números, booleans y secuencias.
Veamos :

Tenemos booleanos:

IN: scratchpad 4 2 = .
f

IN: scratchpad 4 2 > .
t

IN: scratchpad "same" "same" = .
t

IN: scratchpad "same" length "diff" length = .
t

En Factor cualquier valor excepto f es considerado como true, incluyendo 0, el string vacio o la secuencia vacia.

Factor soporta una secuencia como un tipo de datos. Se puede crear una lista con { } y los valores separados por espacio un ejemplo sería :  { 4 3 2 1 } Es necesario el espacio luego de la llaves, similar a lisp.

Los mapas son colecciones key-value, veamos un ejemplo :

{ { "one" 1 } { "two" 2 } { "three" 3 } { "four" 4 } }

Con la palabra of y at podemos acceder a el valor con una key :

IN: scratchpad { { "one" 1 } { "two" 2 } { "three" 3 } } "one" of .
1
IN: scratchpad "two" { { "one" 1 } { "two" 2 } { "three" 3 } } at .
2


Inyección de dependencia de tiempo de compilación

Spring proporciona un mecanismo para la inyección de dependencias en tiempo de ejecución, es decir, la inyección de dependencias donde las dependencias no están conectadas hasta el tiempo de ejecución. Este enfoque tiene ventajas y desventajas, las principales ventajas son la minimización del código repetitivo, la principal desventaja es que la construcción de la aplicación no se valida en tiempo de compilación.

Un enfoque alternativo que es popular en el desarrollo de Scala es utilizar la inyección de dependencia de tiempo de compilación. Esta técnica se puede lograr mediante la construcción manual y el cableado de dependencias. Existen otras técnicas y herramientas más avanzadas, como herramientas de cableado automático basadas en macros, técnicas de cableado automático implícito y varias formas del cake pattern.

Inyectar dependencias en tiempo de compilación permite aprovechar el compilador para verificar que cada controlador en su aplicación tenga acceso a todos los componentes que necesita. Eso significa que no necesita preocuparse por los errores de tiempo de ejecución que causan bloqueos y una mala experiencia para sus usuarios. De hecho, la DI en tiempo de compilación (y la tipificación estática en general) pueden reducir la necesidad de un subconjunto de tipos comunes de pruebas unitarias.

El uso de parámetros de constructor es un enfoque simple y directo para definir dependencias en tiempo de compilación. Veamos un ejemplo del framework play:

class Controller( val controllerComponents: ControllerComponents,
  userModel: UserModel) extends BaseController {

  def user() = Action {
   request => Ok(Json.toJson(userModel.getUsernames()))
  }
}

Se puede decir que la siguiente clase "depende de" una instancia de ControllerComponents y una instancia de UserModel. Esto es tan simple como especificar dependencias. No hay magia, solo dices qué componente quieres y lo obtienes. Configurar cómo se proporcionan las dependencias requiere un poco más de trabajo. Aquí es donde entra el cargador de aplicaciones de play.

class Loader extends ApplicationLoader {
  def load(context: Context): Application = {
    LoggerConfigurator(context.environment.classLoader).foreach {
      _.configure(context.environment)
    }
    new Components(context).application
  }
}

class Components(context: Context) extends BuiltInComponentsFromContext(context) {
  override lazy val httpFilters = Nil
  Lazy val userModel: UserModel = new UserModel()
  lazy val controller: Controller = new Controller(controllerComponents, userModel)
  lazy val router: Router = new Routes(httpErrorHandler, controller)
}

La clase Loader se requiere principalmente para garantizar que la aplicación esté configurada correctamente cuando se carga. La inyección de dependencias ocurre en la clase Componentes. Una vez más, no hay magia aquí: simplemente crea y pasa instancias a componentes que las necesitan. BuiltInComponentsFromContext proporciona un puñado de componentes de Play predeterminados que son útiles. En este caso, uso el componente ControllerComponents para nuestro controlador y un HttpErrorHandler para el constructor de Rutas.

Para aplicaciones simples, la inyección manual de dependencias es bastante simple. Sin embargo, incluso en aplicaciones simples, agregar una dependencia a un controlador requiere que modifique tanto el controlador como el cargador de aplicaciones. Este proceso se ve exacerbado por el constructor de Rutas que genera Play. Cada clase a la que haga referencia en conf / routes se traducirá en un parámetro constructor del objeto Routes. Eso significa que agregar una clase de controlador requiere que crees una instancia de la clase y la pases explícitamente al constructor de Rutas. Para empeorar las cosas, si reordena su archivo conf / routes o agrega una nueva ruta en algún lugar en el medio, su objeto Routes generado tendrá un nuevo orden para sus parámetros de constructor, y tendrá que arreglarlo manualmente también.

La inyección manual en tiempo de compilación no es escalable y creará mucho trabajo adicional en aplicaciones más complejas. Aquí es donde entra MacWire.

MacWire es una macro muy ligera que genera automáticamente llamadas de constructores. Eso es casi todo lo que hace (está bien, tiene algunas otras características, pero solo nos importa esta por ahora). Usando MacWire, cambié la clase de Componentes anterior a la siguiente:

class Components(context: Context) extends BuiltInComponentsFromContext(context) {
  override lazy val httpFilters = Nil
  lazy val userModel: UserModel = wire[UserModel]
  lazy val controller: Controller = wire[Controller]
  lazy val router: Router = {
    val prefix = "/"
    wire[Routes]
  }
}

Notarás dos cambios importantes.

Primero, todas las llamadas "nuevas" han sido reemplazadas por wire [ClassName]. Esta es la macro que genera las llamadas "nuevas". Para ello, examina el constructor predeterminado para la clase especificada y luego busca valores del mismo tipo en el ámbito actual. El wire [Controlador] se expandirá a un nuevo Controlador (controllerComponents, userModel). Ese es exactamente el mismo código que escribimos manualmente arriba. Wire sigue las reglas normales de alcance con las que ya está familiarizado en Scala. Si hay varias instancias que cumplirán una dependencia, el cable fallará en tiempo de compilación diciendo que no puede decidir qué instancia usar. Tendrá que resolver esta ambigüedad manualmente. MacWire proporciona calificadores para simplificar este proceso cuando sea necesario.

En segundo lugar, la definición de enrutador cambió. El constructor predeterminado de Rutas requiere un argumento de prefijo de cadena, mientras que el constructor utilizado manualmente en nuestro ejemplo original anterior no es el constructor predeterminado y no requiere este argumento. Envolví el prefijo en el alcance del bloque de la llamada por cable para no filtrar accidentalmente el prefijo en otros componentes que podrían necesitar un parámetro de cadena. En proyectos más grandes, esto se vuelve más valioso. En este ejemplo, todo habría funcionado bien si definiera el prefijo fuera del bloque Router.

Ahora, agregar una dependencia (o eliminar una dependencia) de un controlador solo requiere que modifique el controlador en sí. Entonces, si necesita acceso a la configuración de la aplicación, puede agregar un parámetro de constructor con el tipo Configuración al controlador y, como por arte de magia, inyectará un objeto de Configuración. Aún mejor, agregar, eliminar o reordenar rutas en conf / routes se vuelve mucho más fácil porque ya no tiene que preocuparse por el orden de los parámetros de Rutas o cualquier cosa más allá de las clases específicas para las que necesita proporcionar instancias.

Una última nota sobre MacWire: se debe usar lazy val. Esto permite especificar dependencias complicadas sin preocuparse por el orden de inicialización entre los diferentes componentes. Todos se crearán a pedido y evitará posibles excepciones de puntero nulo. También puede usar defs si prefiere que cada clase que depende de su def obtenga una nueva instancia en lugar de una instancia compartida.

Y me quedo relargo el post en otro vamos a ver el cake pattern.


Indice TIOBE de agosto

Hace rato que no publico el indice tiobe de lenguajes, veamos :






Como se puede ver Python va subiendo tranquilo, a mi entender esto viene de la mano de las tecnologías de machine learnig que cada vez están más presentes y todas las librerías están en Python.

Otro lenguaje que viene creciendo es Groovy, a mi entender gracias a Spring y pivotal

Dejo link:
https://www.tiobe.com/tiobe-index/

sábado, 24 de agosto de 2019

Matematicas en Factor

Seguimos con Factor

La palabras +, -, * y / toman dos valores de la pila y retorna el valor a la pila. El . toma un valor de la pila y lo imprime.

IN: scratchpad 40 2 + .
42
IN: scratchpad 40 2 - .
38
IN: scratchpad 20 9 * 5.0 / 32 + .
68.0

Muy similar a lisp pero utiliza notación postfija.

IN: scratchpad 5 4 * 20 + .
40
IN: scratchpad 20 5 + 4 * .
100

Como utiliza notación postfija no existe ambiguedad.

viernes, 23 de agosto de 2019

¿Cuál es la diferencia entre un closure y una lambda?

Muchas veces he visto que closure y lambda se toman como sinonimos pero pero no lo son. Veamos cuales son las diferencias.

Una lambda es solo una función anónima, una función definida sin nombre. En algunos lenguajes, como Scheme, son equivalentes a funciones con nombre. De hecho, la definición de la función se reescribe como un enlace interno de una lambda a una variable. En otros lenguajes, como Python, hay algunas distinciones (bastante innecesarias) entre ellos, pero de lo contrario se comportan de la misma manera.

Un closure es cualquier función que se cierra sobre el entorno en el que se definió. Esto significa que puede acceder a variables que no están en su lista de parámetros. Ejemplos:

def func (): return h

def otrofunc (h):
   return func ()

Esto provocará un error, porque func no se cierra sobre el entorno en otrofunc - h no está definido. func solo cierra sobre el entorno global. Esto funcionará de esta manera :

def otrofunc (h):
    def func (): retorno h
    return func ()

Porque aquí, func se define en otrofunc.

Otro punto importante: func continuará cerrándose sobre el entorno de otrofunc incluso cuando ya no se evalúe en otrofunc. Este código también funcionará:

def anotherfunc(h):
    def func(): return h
    return func

print anotherfunc(10)()

Esto imprimirá 10.

Esto no tiene nada que ver con las lambdas: son dos conceptos diferentes (aunque relacionados).

sábado, 17 de agosto de 2019

Factor un lenguaje de programación orientado a pilas

Sigo con Factor y sus pilas.

Vamos a hacer un “hola mundo” en Factor. Empezamos indicando el vocabulario “scratchpad”, pero por ahora no vamos a profundizar en eso. Luego vamos a escribir nuestro “hola mundo”

IN: scratchpad "Hello, world" print
Hello, world

Factor introduce a “Hola Mundo” a la pila y la función print toma de la pila el parametro y se ejecuta.

Introduciendo clear, factor limpia la pila y luego si ejecutamos “Hola Mundo”. Factor nos indica que esto se encuentra en la pila:

IN: scratchpad clear
IN: scratchpad "Hello, world"
--- Data stack:
"Hello, world"

Podemos introducir otro string a la pila :

IN: scratchpad "Hello, Factor"
--- Data stack:
"Hello, world"
"Hello, Factor"

Si ahora intentamos imprimir Factor va utilizar el ultimo valor insertado en la pila :

IN: scratchpad print
Hello, Factor
--- Data stack:
"Hello, world"

Si ejecutamos una funcion que retorne un valor, factor pondra ese valor en la pila.

IN: scratchpad length
--- Data stack:
12

La palabra (recuerden que las funciones se denominan "palabras") length tomó "Hello, world" de la pila y retorno la longitud de la cadena de nuevo y la puso en la pila. Cada palabra en Factor toma cero o más valores de la pila y llena cero o más valores en la pila. La siguiente palabra luego funciona con la pila resultante, y así sucesivamente.

Cuando se ejecuta un programa Factor, el efecto neto de todas las palabras reunidas juntas debe ser consistente, con cada palabra que tenga al menos tantos valores en la pila como esperan extraer, y eliminar tantos valores como afirman. Cuando la pila contiene más valores de los que necesita usar una palabra, los valores adicionales simplemente permanecen en la pila.

Un dato más los comentarios comienzan con un ! seguido de un espacio, veamos un ejemplo :

! This is a comment
"Hello, world" print ! This prints "Hello, world"


Curso de Angular Gratuito!!!


Me llego la invitación a un curso de angular gratuito, es una muy buena posibilidad para aprender este framework tan utilizado. La invitación dice lo siguiente :

Angular es un framework de desarrollo para JavaScript creado por Google. Su finalidad es la de facilitar el desarrollo de aplicaciones web SPA (Single Page Application, Aplicación de Página Única) proporcionando herramientas para trabajar con los elementos de una web de una manera más sencilla y óptima.

Inicio del Curso: 19 de Agosto 2019
Duración: 2 meses
Modalidad: 100% OnLine (SUTIA e-Learning)
Costo: ¡¡¡Gratuito!!! (por lanzamiento de la Plataforma SUTIA e-Learning)

Dejo link: http://sutia.com.ar/angular2019/

Entendiendo el Execution Plan en MySql


No sabia que Mysql tenia la clausula  PLAN EXPLAIN y la tiene! Pero para que sirve?

Dependiendo de los detalles de sus tablas, columnas, índices y las condiciones en su cláusula WHERE, el optimizador MySQL considera muchas técnicas para realizar eficientemente las búsquedas involucradas en una consulta SQL.

Se puede realizar una consulta en una tabla enorme sin leer todas las filas; se puede realizar una unión que involucre varias tablas sin comparar cada combinación de filas. El conjunto de operaciones que el optimizador elige para realizar la consulta más eficiente se denomina "plan de ejecución de consultas", y este se puede ver ejecutando el PLAN EXPLAIN. Sus objetivos son reconocer los aspectos que indican que una consulta está bien optimizada y aprender la sintaxis SQL y las técnicas de indexación para mejorar el plan si hay algunas operaciones ineficientes.

La declaración EXPLAIN proporciona información sobre cómo MySQL ejecuta las consultas.

Cuando precede a una instrucción SELECT con la palabra clave EXPLAIN, MySQL muestra información del optimizador sobre el plan de ejecución de la instrucción. Es decir, MySQL explica cómo procesaría la declaración, incluida la información sobre cómo se unen las tablas y en qué or

Con la ayuda de EXPLAIN, puede ver dónde debe agregar índices a las tablas para que la instrucción se ejecute más rápido mediante el uso de índices para buscar filas. También puede usar EXPLAIN para verificar si el optimizador se une a las tablas en un orden óptimo. Para dar una pista al optimizador para que use un orden de unión correspondiente al orden en que se nombran las tablas en una instrucción SELECT, comience la instrucción con SELECT STRAIGHT_JOIN en lugar de solo SELECT.

Si tenemos un problema con los índices que no se usan cuando sabemos que deberían ser usados, debemos ejecutar ANALYZE TABLE para actualizar las estadísticas de la tabla, como la cardinalidad de las claves, que pueden afectar las elecciones que realiza el optimizador.

EXPLAIN devuelve una fila de información para cada tabla utilizada en la instrucción SELECT. Enumera las tablas en la salida en el orden en que MySQL las leería mientras procesa la declaración. MySQL resuelve todas las uniones utilizando un método de unión de bucle anidado. Esto significa que MySQL lee una fila de la primera tabla y luego encuentra una fila coincidente en la segunda tabla, la tercera tabla, etc. Cuando se procesan todas las tablas, MySQL genera las columnas seleccionadas y retrocede a través de la lista de tablas hasta que se encuentra una tabla para la cual hay más filas coincidentes. La siguiente fila se lee de esta tabla y el proceso continúa con la siguiente tabla.

Cuando se usa la palabra clave EXTENDED, EXPLAIN produce información adicional que se puede ver emitiendo una declaración SHOW WARNINGS después de la declaración EXPLAIN. EXPLAIN EXTENDED también muestra la columna filtrada.

En la mayoría de los casos, puede estimar el rendimiento de la consulta contando las búsquedas de disco. Para tablas pequeñas, generalmente puede encontrar una fila en una búsqueda de disco (porque el índice probablemente está en caché). Para tablas más grandes, puede estimar que, utilizando índices de árbol B, necesita esta cantidad de búsquedas para encontrar una fila: log (row_count) / log (index_block_length / 3 * 2 / (index_length + data_pointer_length)) + 1.

En MySQL, un bloque de índice suele tener 1.024 bytes y el puntero de datos suele tener cuatro bytes. Para una tabla de 500,000 filas con una longitud de valor clave de tres bytes (el tamaño de MEDIUMINT), la fórmula indica log (500,000) / log (1024/3 * 2 / (3 + 4)) + 1 = 4 búsquedas.

Este índice requeriría un almacenamiento de aproximadamente 500,000 * 7 * 3/2 = 5.2MB (suponiendo una relación de llenado del búfer de índice típico de 2/3), por lo que probablemente tenga gran parte del índice en la memoria y, por lo tanto, solo necesite una o dos llamadas para leer datos para encontrar la fila.

Sin embargo, para las escrituras, necesita cuatro solicitudes de búsqueda para encontrar dónde colocar un nuevo valor de índice y normalmente dos buscar y actualizar el índice y escribir la fila.

La discusión anterior no significa que el rendimiento de su aplicación se degenere lentamente por el registro N. Mientras el sistema operativo o el servidor MySQL guarden en caché todo, las cosas se vuelven un poco más lentas a medida que la tabla se hace más grande. Después de que los datos se vuelven demasiado grandes para ser almacenados en caché, las cosas comienzan a ir mucho más lentamente hasta que sus aplicaciones están unidas solo por búsquedas de disco (que aumentan por log N). Para evitar esto, aumente el tamaño de la caché de claves a medida que crecen los datos. Para las tablas MyISAM, el tamaño del caché de claves está controlado por la variable de sistema key_buffer_size.

Por ahora eso es todo sobre nuestro querido explain, dejo link :
https://dev.mysql.com/doc/refman/8.0/en/explain.html
https://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html