Quantcast
Channel: Planeta Código
Viewing all 2718 articles
Browse latest View live

Variable not found: Enlaces interesantes 370

$
0
0
Enlaces interesantesAhí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET / .NET Core

ASP.NET / ASP.NET Core

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin

Otros

Publicado en Variable not found.

Variable not found: await Task.WhenAll(family, relax, sleep, beach)

$
0
0
Siempre llego a estas fechas hecho fosfatina, con la sensación de que las últimas semanas antes de las vacaciones son como una cuesta arriba que parece no acabar nunca. Pero afortunadamente no es así, y al final acaba llegando el ansiado momento de colgar los hábitos durante una pequeña temporada :)

Así pues, me complace anunciaros que voy a dedicar algunas semanas a tomar aire fresco y formatear un poco la mente. Mis planes son muy simples: al principio un par de semanas de familia, playita y descanso, y el resto a seguir trabajando, pero a un ritmo más tranquilo y dejándome libres los fines de semana, que es cuando suelo aprovechar para escribir en el blog.

¡Nos vemos a la vuelta, ya en septiembre!

Playa
Playa de Costa Ballena, Rota (Cádiz). Imagen: Hotel Elba

Publicado en Variable not found.

Mascando Bits: Aprende a programar en Python – Introducción – 0

$
0
0

Llevaba tiempo mascando esta serie de entradas para aprender a programar en Python, para las cuales no quise quedarme en algo del tipo mira, aprende y copia. El curso tiene un enfoque práctico con su parte de teoría y ejercicios donde corresponda. Atendiendo a las actuales necesidades formativas he decidido que el curso y su material podrá ser trabajado de manera online utilizando únicamente un navegador web.

Para ello he creado un repositorio en GitHub con dos herramientas que podréis elegir usar de manera online:

Ambos proyectos usan como base el intérprete de Brython, un proyecto que intenta emular el interprete de Python que puedes instalarte en tu equipo. Este proyecto permite saltarse el problema de no poder instalar el interprete de Python debido a restricciones en el equipo que uses, por ejemplo si dependes del departamento de Sistemas para instalarlo, o simplemente si quieres retomar el curso en cualquier instante sin necesidad de instalar nada.

El proyecto de la Consola Python Online es una consola que se comporta de manera similar a la que puedes tener cuando lanzas Python desde una consola de comandos. El proyecto IDE Python Online es un entorno de desarrollo integrado donde podrás en su parte izquierda realizar la programación con realce de sintaxis y ayuda de autocompletado predictivo de código; y en su parte derecha podrás ver el resultado del código escrito a la izquierda tras darle al botón «▶ Run» de la parte superior. Con estas dos herramientas tendrás lo que te hace falta para seguir el curso.

Este proyecto es de carácter Open Source, siendo posible contribuir en el propio repositorio a la mejora de los fragmentos de código, ejercicios y herramientas.

Antes de empezar quisiera explicarte qué es Python y ofrecerte una pequeña aproximación de su historia. Python es un lenguaje de programación interpretado, lo que significa que no necesita compilarse y generar un binario para funcionar, se interpreta el código y el encargado de hacerlo (el intérprete), lo traducen a lenguaje máquina. Esto quiere decir también que con vuestro código en Python sólo necesitáis que un intérprete de Python esté instalado en la máquina para ejecutar el código, o usar las herramientas que anteriormente presentaba 😉 .

Python es un excelente lenguaje de programación si quieres aprender una herramienta que potencie o complemente tu trabajo, como es el caso del clásico Excel. O simplemente como tu primer lenguaje de programación, debido a que su curva de aprendizaje es mucho más baja a diferencia de otros lenguajes, haciendo hincapié en una sintaxis que favorece la legibilidad del código. Además Python es multiparadigma, lo que significa que puede acomodarse a distintos enfoques y necesidades de programación, incluyendo el buen diseño por defecto en la propia sintaxis y evolución del lenguaje.

Actualmente Python se encuentra en un proceso de migración de Python 2 a Python 3, debido a que el soporte de Python 2 acaba el 1 de enero de 2020, terminando con un estado de segmentación del lenguaje que llevaba varios años produciéndose. El salto de Python 2 a Python 3 supone el cambio del diseño de cierta parte de la sintaxis que rompe la compatibilidad y evitaba a Python avanzar hacia el Python que hoy conocemos y que tanta penetración tiene en los sectores técnicos y no tan técnicos. No obstante existen herramientas como 2to3 que realizan la adaptación automática de la sintaxis de Python 2 a Python3. Obviamente no es perfecto y queda en manos del programador el terminar de pulir la migración. La versión del lenguaje que aprenderás aquí, por supuesto es Python 3 😉 .

Para ir abriendo boca voy a mostrarte el clásico programa de inicio «Hello World!» o «Hola Mundo!» en español:

Si le das al botón «▶ Run» leerás en la derecha «Hello World» seguido del tiempo que ha tardado en ejecutarse nuestro programa (lo que hay en el panel izquierdo).

Ahora te propongo un simple ejercicio hasta la próxima entrada. Partiendo del siguiente código:

Intenta que imprima en el lado derecho «Hello World«. Es fácil y seguro que lo consigues 😉 .

Con esto cerramos el capítulo de introducción donde hemos conocido las herramientas que vamos a usar para el curso, hemos presentado Python y hemos ejecutado nuestro primer programa.

Blog Bitix: Publicación y suscripción de eventos con Guava EventBus en una aplicación Java

$
0
0

Guava EventBus es una solución simple para la publicación y suscripción de eventos en una misma aplicación y como tal no posee muchas de las capacidades que si tiene JMS o RabbitMQ, sin embargo, en algunos casos puede ser muy útil, una solución sencilla y sin requerimientos adicionales de infraesrtuctura.

Java

En programación los eventos son una buena forma de comunicación que permite desacoplar el emisor del evento del receptor o receptores. Los eventos permiten reaccionar a situaciones que se producen a la aplicación. El emisor los lanza cuando considera adecuado y los receptores se suscriben a los eventos que quieren recibir y actúan según su funcionalidad.

Hay herramientas especificas para eventos en Java está JMS si la aplicación está basada en la plataforma en Java EE, en caso de necesitar un servidor de mensajes adecuado para múltiples plataformas y lenguajes uno de los más conocidos es RabbitMQ. Estas opciones permiten que el emisor y los receptores estén aplicaciones distintas.

En el caso de que el emisor y receptor estén en la misma aplicación una opción más sencilla por no requerir un servidor de mensajería es usando la librería Guava y su funcionalidad de Event Bus. Una de las ventajas de Guava Event Bus es que el receptor no requiere un registro explícito en el emisor como ocurre en algunas de las soluciones con clases Listener de Java.

Para hacer uso de Guava Event Bus hay que obtener una referencia a la clase EventBus que usando Spring se puede definir como un bean singleton en el contenedor de dependencias y ser inyectado en las clases que lo necesiten. Los eventos se envían a haciendo uso del método post() con el objeto que representa el evento como argumento. Los manejadores de los eventos o listener son simplemente un método anotado con @Suscribe y el tipo del evento como argumento, la clases listener han de registrarse en el EventBus y una misma clase con múltiples métodos anotados puede manejar diferentes eventos.

En el contenedor de Spring se define como un bean la clase EventBus que es inicializada con las clases listener con métodos anotados con @Suscribe registradas con el método register().

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
packageio.github.picodotdev.blogbitix.guava;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;importorg.springframework.context.annotation.Bean;importcom.google.common.eventbus.EventBus;@SpringBootApplicationpublicclassMain{@BeanpublicEventBuseventBus(){EventBuseventbus=newEventBus();eventbus.register(newEventListener());returneventbus;}publicstaticvoidmain(String[]args){SpringApplication.run(Main.class,args);}}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
packageio.github.picodotdev.blogbitix.guava;importcom.google.common.eventbus.Subscribe;publicclassEventListener{@SubscribepublicvoidonEvent(Eventevent){System.out.printf("Event: %s%n",event.getMessage());}}

En este ejemplo sencillo se lanza un evento cuando se realiza una petición y como reacción a este evento se imprime un mensaje en la salida. Una aplicación real del EventBus será más complicada pero este ejemplo muestra perfectamente el mecanismo de lanzado y recepción de eventos en una misma aplicación. La clase que se lanza como evento en este caso es un POJO sin ningún requerimiento especial.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
packageio.github.picodotdev.blogbitix.guava;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.RequestParam;importorg.springframework.web.bind.annotation.RestController;importorg.springframework.web.bind.annotation.RequestMapping;importcom.google.common.eventbus.EventBus;@RestControllerpublicclassDefaultRestController{@AutowiredprivateEventBuseventbus;@RequestMapping("/")publicEventhello(@RequestParam(value="message",defaultValue="Hello World!")Stringmessage){Eventevent=newEvent(message);eventbus.post(event);returnevent;}}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
packageio.github.picodotdev.blogbitix.guava;publicclassEvent{privateStringmessage;publicEvent(Stringmessage){this.message=message;}publicStringgetMessage(){returnmessage;}}

Al realizar peticiones a la aplicación el controlador emite un evento que es recibido por listener al procesar el evento, en la salida de la aplicación aparecen los mensajes.

1
2
Event: Hello World!
Event: A message

En el proyecto hay que incluir como dependencia la librería Guava en este caso usando Gradle.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
plugins{id'java'id'application'id'org.springframework.boot'version'2.1.6.RELEASE'}group='io.github.picodotdev.blogbitix'version='0.0.1-SNAPSHOT'sourceCompatibility=11mainClassName='io.github.picodotdev.blogbitix.guava.Main'repositories{mavenCentral()}dependencies{implementationplatform("org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE")implementation('org.springframework.boot:spring-boot-starter-web')implementation('org.springframework.boot:spring-boot-starter-jersey')implementation('com.google.guava:guava:28.0-jre')}

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradlew run.

Fixed Buffer: La potencia de la Reflexión en C# (Parte 4: Métodos)

$
0
0
Imagen con el logo de C# para la entrada de reflexión para métodos

Aquí estamos una semana más hablando de la reflexión, y hoy les toca el turno a los métodos. Echando la vista atrás, hemos hablado sobre la reflexión en general y las propiedades, sobre como trabajar con ensamblados, y en la última semana hablamos sobre cómo utilizar los constructores mediante reflexión.

Hoy es el turno de trabajar con reflexión en métodos. A estas alturas, seguramente puedas imaginar cómo los vamos a obtener, puesto que es muy parecido a obtener los constructores. Salvo que esta vez, en vez de obtener un ConstructorInfo, vamos a tener un MethodInfo. (Aunque las dos clases en profundidad tienen sus diferencias, ambas heredan de MemberInfo). Además, lo hemos utilizado para probar el código en las entradas anteriores.

Obteniendo un método por reflexión

Como en todos los casos anteriores, lo que vamos a partir es del tipo (Type), pero esta vez vamos a llamar al método GetMethod() indicándole el nombre del método que queremos buscar. Adicionalmente, le podemos indicar también los modificadores y los parámetros, en caso de que tengamos varios métodos que se llaman igual, pero cambia la firma. Por ejemplo:

var className = "PostReflexion.ClaseEjemplo";
var assembly = Assembly.GetAssembly(typeof(Program));
var type = assembly.GetType(className);

//Obtenemos un método público
var publicMethod = type.GetMethod("Multiplicar");
//Obtenemos un método privado
var privateMethod = type.GetMethod("ResetValor", BindingFlags.Instance | BindingFlags.NonPublic);
//Obtenemos un método estático
var staticMethod = type.GetMethod("Sumar", BindingFlags.Static | BindingFlags.NonPublic);


public class ClaseEjemplo
{
    private int _valor;
    public ClaseEjemplo(int valor)
    {
        _valor = valor;
    }

    public int Multiplicar(int por)
    {
        return _valor * por;
    }

    private void ResetValor()
    {
        _valor = 0;
    }

    static int Sumar(int a, int b)
    {
        return a + b;
    }
}

Invocando nuestro método

Una vez que tenemos nuestro MethodInfo, al igual que veíamos con los constructores, basta que llamemos a Invoke pasándole los parámetros, y ya hemos conseguido ejecutar nuestro código:

var className = "PostReflexion.ClaseEjemplo";
var assembly = Assembly.GetAssembly(typeof(Program));
var type = assembly.GetType(className);

//Obtenemos los constructores
var constructorConParametros = type.GetConstructor(new[] { typeof(int) }); //Contructor con parametro int
var constructorSinParametros = type.GetConstructor(Type.EmptyTypes); //Constructor genérico

//Creamos el objeto de manera dinámica
var objetoConParametros = constructorConParametros.Invoke(new object[] { 2 });

// Creamos una referencia al método   
var m = assembly.GetType(className).GetMethod("Multiplicar");

//Llamamos al método pasandole el objeto creado dinámicamente y los argumentos dentro de un object[]
var retConstructorParamatrizado = m.Invoke(objetoConParametros, new object[] { 3 });

Con esto tan sencillo, ya hemos conseguido ejecutar métodos por reflexión en C#. ¡Y esto es todo! ¿O no…?

El coste de la reflexión

Estamos ya por la cuarta entrada, y siempre diciendo que la reflexión es cara, pero…. ¿Cuánto más cuesta procesar nuestro código por reflexión?,¿es mucho…? ¿poco…? La respuesta es: muchísimo, vamos a poner unos números:

La imagen muestra un benchmark comparando la llamada normal al método y la llamada por reflexión, viendo que esta última es más de 3500 veces más lenta

Vaya… con estos números, parece que la reflexión no sirve, es demasiado lenta, no podemos meter reflexión en nuestro código más allá de para facilitarnos las pruebas unitarias.

La reflexión es muy útil para testing, hoy sin ir más lejos la he utilizado para poder testear cierta parte del código de un proyecto que es privada porque así debe serlo, y he podido saltarme las restricciones de acceso y he podido añadir tests para ese código que prueba solo lo que tiene que probar.

Muy acertadamente en los comentarios de una entrada anterior, planteaban una alternativa para mejorar el rendimiento, que consiste crear el objeto mediante el constructor por reflexión, y a partir de ahí utilizar dynamic. Para quién no lo conozca, dynamic es un tipo especial de objeto que evita la comprobación de tipos en compilación utilizando Dynamic Language Runtime, delegando al runtime ese trabajo, lo que nos permite hacer algo como esto:

var className = "PostReflexion.ClaseEjemplo";
var assembly = Assembly.GetAssembly(typeof(Program));
var type = assembly.GetType(className);

//Obtenemos el constructor
var constructorConParametros = type.GetConstructor(new[] { typeof(int) }); 

//Creamos el objeto de manera dinámica y de tipo "dynamic"
dynamic objetoDinamicoConParametros = constructorConParametros.Invoke(new object[] { 2 });

//Llamamos al método como si fuese un objeto tipado
var retConstructorParamatrizado = objetoDinamicoConParametros.Multiplicar(3);

Con este pequeño cambio, hemos conseguido mejorar los tiempos:

La imagen muestra como utilizar "dynamic" es cerca de 23 veces más rápido que utilizar reflexión, aunque sigue siendo 150 veces más lento que una llamada normal

Los dos principales problemas de esto, son que hemos perdido la flexibilidad que teníamos para buscar los métodos, ya que ahora el nombre tiene que coincidir, no tenemos ese margen para buscar (además de que volvemos a regirnos por los modificadores de acceso), y sobre todo, sigue siendo 150 más lento que hacer una llamada convencional (aunque hemos mejorado mucho respecto a la llamada por reflexión). De todos modos, si queremos utilizar la reflexión para cargar código que puede cambiar, sigue siendo demasiado lento. Llegados a este punto, ¿tenemos que tirar la toalla con la reflexión?

Creando delegados de métodos obtenido por reflexión

Un delegado, no es más que la referencia a un método desde la cual vamos a poder llamar a ese método sin necesidad de tener acceso al objeto que lo contiene, ya que este va implícito en la referencia a donde apunta el delegado:

// Declaramos la firma del delegado
delegate void MyDelegado(string str);

// Declaramos un método con la misma firma del delegado
static void Notify(string message)
{
    Console.WriteLine(message);
}

// Creamos una instancia del delegado.
MyDelegado del1 = new MyDelegado(Notify);

// Llamamos al método a través del delegado.
del1("Llamada desde un delegado");

Ahora, si unimos esto con la reflexión, lo que podemos hacer es crear un delegado que apunte hacia nuestro método por reflexión. Para ello, siguiendo con nuestro ejemplo, vamos a utilizar el delegado «Func<int,int>» (recordemos que nuestro método recibía un entero como parámetro y devolvía otro entero), pero si fuese necesario, podemos definir el delegado que nos haga falta.

Para construirlo, vamos a aprovecharnos de Delegate.CreateDelegate, y le vamos a indicar el tipo, el objeto al que hacemos referencia, y el nombre del método al que queremos hacer el delegado:

Func<int, int> delegateMethod = (Func<int, int>)Delegate.CreateDelegate(typeof(Func<int, int>), target, "Multiplicar");

Delegate.CreateDelegate tiene diferentes parámetros en función de lo que queramos hacer, por ejemplo, si queremos crear un delegado a un método estático, tendríamos que utilizar el objeto MethodInfo directamente, te recomiendo que le eches un ojo a sus posibilidades.

Además, como conocemos el tipo del delegado a la perfección (sabemos que esperar, o podemos consultarlo sobre el MethodInfo para saber que delegado aplicarle), podemos hacer un cast al tipo de delegado concreto, por ejemplo, el código completo sería algo así:

var className = "PostReflexion.ClaseEjemplo";
var assembly = Assembly.GetAssembly(typeof(Program));
var type = assembly.GetType(className);

//Obtenemos el constructor
var constructorConParametros = type.GetConstructor(new[] { typeof(int) }); 

//Creamos el objeto de manera dinámica            
object objetoDinamicoConParametros = constructorConParametros.Invoke(new object[] { 2 });
            
//Creamos el delegado pasandole el tipo, una referencia al objeto sobre el que va a trabajar, y el nombre del metodo
//Delegate.CreateDelegate tiene diferentes parámetros en función de lo que queramos hacer
Func<int, int> delegateMethod = (Func<int, int>)Delegate.CreateDelegate(typeof(Func<int, int>), objetoDinamicoConParametros, "Multiplicar");

//Llamamos al método 
var retDelegado = delegateMethod(3);

Si ejecutas este código, veras que funciona perfectamente (Como siempre, he dejado actualizado el repositorio en GitHub para poder descargárselo y tocarlo). Además, este modo si nos permite saltarnos los limitadores de acceso, en caso de que estemos haciendo pruebas al código.

Vale, es todo muy bonito, pero a simple vista, solo supone más trabajo porque tenemos que gestionar un delegado también, ¿esto aporta algo?, vamos a ver los números:

La imagen muestra el resultado del benchmark de los 4 métodos, viendose: Llamada convencional 0.02 ns, llamada por reflexión 213.90 ns, llamada con dynamic 9.89 ns y llamada con delegado 1.74 ns

Como se puede comprobar, después de hacer una llamada convencional, utilizar delegados es lo siguiente más rápido, siendo 5,7 veces más rápido que utilizar «dynamic».

Los tiempos son solo orientativos (de hecho, han ido variando ligeramente durante los diferentes benchmark)

Conclusiones

Si bien es cierto que no podemos conseguir los tiempos que conseguiríamos con una llamada convencional. Cuando se recurre a la reflexión es precisamente cuando las llamadas convencionales no están disponibles por una razón u otra. Como se puede comprobar de los números, la reflexión es cara, pero existen maneras de hacerla más liviana.

Como decíamos en la entrada de los constructores, un gran poder conlleva una gran responsabilidad. La reflexión es algo que debemos utilizar con cabeza y criterio, pero no es algo prohibido que no hay que tocar. Como he dicho varias veces, es una herramienta especialmente útil para hacer testing por ejemplo, cuando hay cosas donde necesitamos acceder y no podemos.

**La entrada La potencia de la Reflexión en C# (Parte 4: Métodos) se publicó primero en Fixed Buffer.**

Blog Bitix: Obtener los primeros, los últimos o los caracteres anteriores y posteriores de un archivo y el número de ocurrencias con head, tail y grep

$
0
0
GNU
Linux

Algunos archivos de texto tienen un tamaño de cientos de megas, a veces incluso sin ningún salto de línea. Visualizar el contenido de estos archivos en una aplicación con interfaz gráfica no suele ser posible porque la aplicación se queda bloqueada al intentar cargar tan enormes archivos. Incluso tampoco puede ser posible con un editor mucho más ligero como vim. Hacer un cat del archivo tampoco es útil.

Sin embargo, sigue siendo necesario ver parte del contenido de estos archivos de texto grande para validar que el contenido de los mismos es el correcto. La opción que se puede utilizar es ver los primeros o últimos caracteres o lineas con los comandos head o tail usándolos de la siguiente forma.

1
2
3
4
5
6
$ # Primeros o últimos 100 caracteres de un archivo
$ head -c 100 archivo.txt
Lorem ipsum dolor sit amet consectetur adipiscing elit pulvinar et praesent, egestas fermentum mauri
$ tail -c 100 archivo.txt
ultricies, a dictumst velit dapibus leo pellentesque dictum dui ligula aliquam eu dignissim rhoncus.
1
2
3
4
5
6
7
$ # Primeras o últimas 2 lineas de un archivo
$ head -n 2 archivo.txt
Lorem ipsum dolor sit amet consectetur adipiscing elit pulvinar et praesent, egestas fermentum mauris phasellus non nec rutrum nibh accumsan, placerat natoque interdum dui duis viverra molestie id parturient. Imperdiet commodo viverra arcu ridiculus blandit interdum litora bibendum felis ac purus, eu facilisi habitasse ultrices nisl magnis lobortis phasellus turpis velit vestibulum faucibus, auctor sagittis consequat quis cubilia inceptos donec enim gravida mus. Lacinia felis cras leo porta imperdiet tellus ridiculus convallis praesent ante, dapibus laoreet nibh dictumst penatibus a euismod nisi nulla, luctus lacus porttitor neque magnis sed molestie curae quisque. Hac volutpat curabitur laoreet ultrices est nibh parturient quam libero, faucibus ac metus gravida quis venenatis aliquam placerat cubilia, vel ligula litora dapibus dignissim auctor rhoncus at.
$ tail -n 2 archivo.txt
Bibendum hendrerit sociosqu id libero neque, ad mollis donec consequat sagittis, tempus litora morbi nisi. Augue gravida aliquet rhoncus porta odio dui auctor velit erat lectus magna phasellus fringilla, quam praesent class cursus blandit nulla curabitur nostra feugiat consequat egestas cubilia, tortor magnis senectus volutpat ad urna semper himenaeos nascetur luctus posuere interdum. Nam quisque aliquet convallis taciti maecenas euismod vulputate mauris commodo et eleifend vel duis ultricies, a dictumst velit dapibus leo pellentesque dictum dui ligula aliquam eu dignissim rhoncus.
1
2
3
4
5
6
7
Lorem ipsum dolor sit amet consectetur adipiscing elit pulvinar et praesent, egestas fermentum mauris phasellus non nec rutrum nibh accumsan, placerat natoque interdum dui duis viverra molestie id parturient. Imperdiet commodo viverra arcu ridiculus blandit interdum litora bibendum felis ac purus, eu facilisi habitasse ultrices nisl magnis lobortis phasellus turpis velit vestibulum faucibus, auctor sagittis consequat quis cubilia inceptos donec enim gravida mus. Lacinia felis cras leo porta imperdiet tellus ridiculus convallis praesent ante, dapibus laoreet nibh dictumst penatibus a euismod nisi nulla, luctus lacus porttitor neque magnis sed molestie curae quisque. Hac volutpat curabitur laoreet ultrices est nibh parturient quam libero, faucibus ac metus gravida quis venenatis aliquam placerat cubilia, vel ligula litora dapibus dignissim auctor rhoncus at.
Proin sapien viverra nisl posuere dapibus commodo senectus aptent dui nam est tempor primis, dignissim vehicula pharetra et augue hendrerit tincidunt metus mauris curae mus eu. Quam habitasse natoque gravida cras class porttitor fringilla facilisi, phasellus mauris hendrerit et montes enim libero, suspendisse id fermentum lacus molestie purus blandit. Vivamus interdum nisi eleifend suscipit vulputate faucibus suspendisse felis curae, sodales pharetra cubilia vehicula proin velit turpis sapien ad, cursus molestie erat aliquam ridiculus rhoncus duis eu.
Mollis venenatis felis suscipit mauris fusce at massa sociosqu conubia, hac sociis aptent ut netus vestibulum nostra sed dictumst, nec non eget magna vulputate cum pellentesque arcu. Congue pharetra luctus justo curabitur turpis mi semper nibh laoreet fames, vehicula quam maecenas dui magna scelerisque dictum diam tortor, sociis massa facilisi cum viverra duis erat urna fusce. Urna interdum nisl class fames quam cum suscipit ultrices hendrerit ullamcorper, sagittis nullam aliquam porta tellus aptent fringilla iaculis vitae, vivamus vestibulum conubia elementum semper id himenaeos nunc convallis.
Bibendum hendrerit sociosqu id libero neque, ad mollis donec consequat sagittis, tempus litora morbi nisi. Augue gravida aliquet rhoncus porta odio dui auctor velit erat lectus magna phasellus fringilla, quam praesent class cursus blandit nulla curabitur nostra feugiat consequat egestas cubilia, tortor magnis senectus volutpat ad urna semper himenaeos nascetur luctus posuere interdum. Nam quisque aliquet convallis taciti maecenas euismod vulputate mauris commodo et eleifend vel duis ultricies, a dictumst velit dapibus leo pellentesque dictum dui ligula aliquam eu dignissim rhoncus.

Como programador no es raro trabajar con archivos de más de 100 MiB en los que el texto no contiene saltos de línea y el contenido es una sola línea como es el caso de un archivo en formato XML utilizado para intercambiar información entre dos aplicaciones. Estos archivos por su tamaño y sin saltos de línea se les atragantan a los editores de texto gráficos como Visual Studio Code e incluso a la opción más ligera basada en texto como vim.

En ete caso también es necesaria una forma de comprobar el contenido del archivo o contar el número de ocurrencias de un determinado patrón. La herramienta de línea de comandos grep es una gran ayuda en estos dos casos. Suponiendo un archivo XML que contiene elementos con un tag de precio se desea comprobar que estos elementos tienen un valor válido. Utilizando grep y una expresión regular se obtienen las etiquetas price, una en cada línea. El parámetro -E indica que se utilizan una expresión regular y el parámetro -o indica que cada coincidencia se emita en una línea nueva.

1
2
3
4
$ grep -E -o "<price>[^<]*</price>" archivo.xml
<price>1.0</price>
<price>2.0</price>
<price>3.0</price>
1
2
<?xml version="1.0" encoding="UTF-8"?><products><product><name>A</name><price>1.0</price></product><product><name>B</name><price>2.0</price></product><product><name>C</name><price>3.0</price></product></products>

En caso de no ser un archivo estructurado como XML o querer obtener los 15 caracteres anteriores o posteriores de una coincidencia se utiliza un comando grep similar cambiando la expresión regular.

1
2
3
4
$ grep -E -o ".{0,15}price.{0,15}" archivo.xml
<name>A</name><price>1.0</price></p
<name>B</name><price>2.0</price></p
<name>C</name><price>3.0</price></p

Para contar el número de coincidencias en el archivo se puede combinar el comando grep utilizando la opción -o para que emita cada coincidencia en cada línea y el comando wc con la opción -l para que cuente el número de líneas de entrada. Utilizando una tubería entre ambos comandos es posible contar el número de coincidencias en un archivo.

1
2
$ grep -E -o "<product>" archivo.xml | wc -l
3

En este caso el XML es muy pequeño y un editor de texto es capaz de abrirlo perfectamente pero un archivo de texto a partir unas cuantas decenas de MiB se le atraganta a los editores incluso a los basados en texto y en el caso querer hacer comprobaciones una buena alternativa o la única es recurrir a los comandos head, tail, grep y wc.

Arragonán: Sobre el rediseño

$
0
0

Hace un par de meses publiqué el rediseño de la home de mi web personal y de paso de este blog.

Versión 2013

El anterior diseño, de José Luis Lizano y maquetado por Guillermo Latorre, databa de inicios de 2013 y estaba enfocado a ser un portfolio de algunos de mis trabajos como desarrollador freelance hasta ese momento. Tenía el objetivo de dar a conocer el tipo de trabajos para el que se me podía contratar, objetivo que había perdido sentido hacía tiempo.

A su vez el blog lo maqueté yo basándome en el trabajo que hicieron ellos en la home, aún siendo un resultado medianamente digno, se evidenciaban mis limitaciones.

Pantallazo el diseño previo del blog

Originalmente, tanto la web como el blog estaban sobre Wordpress en un hosting compartido, así que tocaba ir haciendo actualizaciones y mantenimiento de vez en cuando… Normalmente tarde y mal. Así que a mediados de 2017 lo migré a Jekyll en Github Pages, integrando Disqus para los comentarios y así poder olvidarme de eso. En ese momento me tocó andar revisando la parte responsive para que no se viera el diseño totalmente roto accediendo desde móviles, algo que hasta entonces no le había dedicado atención.

Versión 2019

Tras mucho tiempo con ello en la cabeza, finalmente nos pusimos a darle una vuelta con Vanessa Rubio al rediseño. Sin tener objetivos en sí mismos, las ideas principales eran:

  • Cambio en el enfoque de comunicación, quería que la home fuera algo más parecido a una carta de presentación. Romper con el enfoque de portfolio para pasar a contar qué cosas hago, qué he hecho, mis intereses, etc.
  • Ganar en legibilidad, ya que el anterior diseño de la home estaba planteado para textos cortos y la adaptación que hice para el blog arrastraba por ello algunos problemas. Quería volver a darle protagonismo a este blog escribiendo más en él y dejando de publicar en Medium.
  • Tener un diseño pensado para consumir contenido desde dispositivos móviles, por razones evidentes.

Boceto inicial del diseño del blog tanto versión escritorio como móvil

Para ponerlo en común trabajamos sobre bocetos en papel iterando rápido hasta llegar a la imagen de este post, que usó Vanessa como base para diseñar ya la parte visual entrando a detalle junto a contenido que fui evolucionando.

Una vez diseñada la parte visual, empezó a trabajar en la maquetación responsive sobre un fork del repositorio de git. Incorporando los cambios directamente en el Jekyll existente, con el contenido real y sincronizando alguno de mis cambios en cuanto a copys. Además, aprovechando que Jekyll lo soporta de serie, en el camino migró los estilos de Less a Sass.

Para finalizar, estas son algunas explicaciones de decisiones sobre el rediseño de Vanessa:

La idea era rediseñar sin perder la identidad actual. Para eso mantuve los principales elementos identificativos, como el logo, los colores y la tipografía.

Como queríamos facilitar la lectura de textos largos, le di más peso al blanco (sustituyéndolo como color de fondo) y dejé el negro principalmente para las zonas de navegación y la intro de la home. Para hacerla también más cómoda, especialmente en dispositivos móviles, aumenté el tamaño de fuente y del interlineado; añadiendo además espacios entre apartados para facilitar la lectura en diagonal.

Quería que fuera un espacio limpio, sin elementos que pudieran distraer la lectura. Para eso eliminé la barra derecha del blog ampliando así el espacio del cuerpo del post y dejé bastante aire alrededor para relajar la vista y centrar la atención en el contenido.

Por último, también quería destacar los CTAs más importantes del blog (como el de enviar comentarios o navegar entre páginas) convirtiéndolos en botones y unificando al mismo tiempo esos mismos estilos con los de la home para mantener la coherencia entre elementos similares.

Personalmente estoy muy contento con el resultado :)

Blog Bitix: Administrar secretos y proteger datos sensibles con Vault

$
0
0

Herramientas de aprovisionamiento como Chef, Puppet y Ansible solucionan el problema de la seguridad de los secretos de forma similar, utilizando una única clave de cifrado. Los datos cifrados están siempre a un secreto (contraseña, clave, …) de ser descifrados y generalmente no está bien protegido dado que en un entorno elástico cada servidor necesita disponer de este secreto para descifrar los datos. Adicionalmente el acceso a los datos cifrados no está registrado de modo que si hay una intrusión no está claro que dato ha sido accedido y por quien. Utilizar variables de entorno para proporcionar secretos tampoco es seguro, y en Docker suele usarse.

Vault
HashiCorp

La seguridad es un aspecto muy importante de los sistemas informáticos, no darle la consideración necesaria puede dar lugar a caídas de servicio y robo de datos potencialmente ocasionando importantes pérdidas de dinero, sanciones y pérdida de confianza de los clientes y proveedores de una organización.

La seguridad se mantiene mediante mecanismos de autenticación identifican al solicitante solicitante, de autorización permitiendo realiza únicamente las acciones para las que se tienen permisos y mediante firma y cifrado para impedir la modificación de los datos y el acceso a la información sin las credenciales y autorización requerida.

La infraestructura informática de los sistemas actuales es cada vez más compleja por el número y tipo de las distintas de piezas que emplean como bases de datos, sistemas de mensajes u otros servicios, también por el aspecto efímero en la tendencia actual de microservicios como por la utilización de entornos en la nube con una infraestructura no confiable al estar fuera del control de una organización y estar compartida con otras organizaciones.

No es seguro utilizar archivos sin cifrar aún utilizando los permisos del sistema de archivos dado que una intrusión en el sistema posibilita el acceso al secreto. Cifrarlos los archivos es el mismo caso de herramientas como Chef, Puppet y Ansible. Utilizar variables de entorno para proporcionar secretos tampoco es seguro ya que aunque los secretos no están en el sistema de archivos se pueden inspeccionar las variables de entorno de un proceso.

1
2
3
$ env | grep SECRET
$ docker inspect
$ sudo cat /proc/$pid/environ

Por otra parte las contraseñas y claves han de rotarse regularmente para limitar en el tiempo el acceso ante el filtrado de las credenciales en un sistema o para denegar el acceso a una persona que en algún momento haya tenido credenciales de acceso como un empleado que ya no pertenece a la compañía.

Vault

Vault es una herramienta para acceder de forma segura a secretos. Un secreto es cualquier cosa a la que se quiera tener severamente controlado como claves de API, contraseñas y certificados. Vault proporciona una interfaz para cualquier secreto a la vez que mantiene un control de acceso y un log de acceso detallado.

Las características principales de Vault se engloban en tres aspectos de la seguridad: cifrado, control de acceso y ciclo de vida.

  • Almacenamiento seguro de secretos: se pueden almacenar secretos arbitrarios clave/valor. Los secretos son cifrados previamente a ser almacenados en el almacenamiento persistente de modo que obtener acceso al almacenamiento persistente no es suficiente para acceder a los secretos. Vault puede almacenar los secretos en disco, Consul y más.
  • Secretos dinámicos: puede generar secretos bajo demanda para algunos sistemas como AWS o bases de datos SQL. Por ejemplo, cuando una aplicación necesita acceso a una base de datos SQL solicita a Vault unas credenciales, Vault genera unas credenciales con los permisos adecuados. Después de crear estos secretos dinámicos también los revoca automáticamente una vez pasado su tiempo de concesión.
  • Cifrado de datos: puede cifrar y descifrar datos sin almacenarlos. Esto permite definir parámetros de seguridad y los desarrolladores almacenar los datos cifrados en localizaciones como bases de datos sin tener que diseñar sus propios métodos de cifrado.
  • Concesión y renovación: todos los secretos en Vault tienen un tiempo de concesión asociado. Al finalizar la concesión Vault los revoca automáticamente, los clientes pueden solicitar renovar las concesiones mediante las API disponibles de Vault.
  • Revocación: integra la funcionalidad de revocación, no solo secretos individuales sino jerarquías de secretos. La revocación asiste en la rotación de las claves así como cerrar el sistema en caso de intrusión.

Conceptos

Los motores de secretos son uno de los conceptos en el ámbito de Vault. Son componentes que permite almacenar, generar o cifrar datos. Algunos motores de secretos simplemente almacenan y leen datos, otros se conectan a otros servicios y generan credenciales dinámicamente bajo demanda. Otros motores de secretos proporcionan el cifrado como servicio, tokens de un solo uso, certificados y mucho más.

Otro concepto es la autenticación. Permiten realizar la autenticación y son responsables de asignar una identidad y un conjunto de policies a un usuario. Por ejemplo, para los desarrolladores el método de autenticación de GitHub es fácil de usar pero para servidores el método AppRole es el recomendado

Los secretos necesitan almacenamiento. Algunos tipos de almacenamiento son mejores para la alta disponibilidad y otros facilitan la copia de seguridad y la restauración. Puede ser en memoria, sistema de archivos, una herramienta como Consul o varias bases de datos entre ellas bases de datos relacionales.

La auditoria permite obtener una trazabilidad de las operaciones que se han realizado, dado que todas las operaciones se realizan mediante una API el log de auditoría es simplemente cada interacción autenticada con Vault, incluidas los errores. Puede ser un archivo o un socket.

Todo en Vault está basado en paths. Las policies permiten o deniegan el acceso a ciertos paths. Poseen la siguiente sintaxis, donde las capabilities son las operaciones CRUD permitidas.

1
2
3
path "secret/*" {
capabilities = ["create", "read", "update", "delete", "list"]
}

Instalación y un caso de uso

La instalación de Vault es muy sencilla ya que es un único binario sin más dependencias. En una distribución GNU/Linux estará en los repositorios oficiales. En Arch Linux se instala con el comando.

1
$ sudo pacman -S vault

En el siguiente ejemplo en modo desarrollo de uso de Vault se inicia, se realiza la autenticación con el tokenroot de superusuario y se crea un secreto. Aquí solo se muestra el caso de uso de guardar y recuperar secretos, otros son generar credenciales para conectarse a una base de datos y proporcionar cifrado y descifrado como servicio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
$ vault server -dev
==> Vault server configuration:
Api Address: http://127.0.0.1:8200
Cgo: disabled
Cluster Address: https://127.0.0.1:8201
Listener 1: tcp (addr: "127.0.0.1:8200", cluster address: "127.0.0.1:8201", max_request_duration: "1m30s", max_request_size: "33554432", tls: "disabled")
Log Level: info
Mlock: supported: true, enabled: false
Storage: inmem
Version: Vault v1.1.1
Version Sha: a3dcd63451cf6da1d04928b601bbe9748d53842e
WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.
You may need to set the following environment variable:
$ exportVAULT_ADDR='http://127.0.0.1:8200'
The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.
Unseal Key: R6MKrMxcJtTTUuIjeQjwDxnv4sHbKtjmuRn0Fok98zk=
Root Token: s.hQoeIivTHHgl1AtsoVz1UF1G
Development mode should NOT be used in production installations!
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
$ exportVAULT_ADDR='http://127.0.0.1:8200'
$ vault kv put secret/key key=s3cr3t
Key Value
--- -----
created_time 2019-07-27T17:30:29.559274833Z
deletion_time n/a
destroyed false
version 1
$ vault kv get secret/key
======Metadata======
Key Value
--- -----
created_time 2019-07-27T17:30:29.559274833Z
deletion_time n/a
destroyed false
version 1===Data===
Key Value
--- -----
key s3cr3t

Vault al igual que otras de las herramientas de HashiCorp como Consul y Nomad posee una interfaz gráfica accesible mediante el navegador que permite realizar las mismas operaciones que a través de la API o desde la linea de comandos.

Interfaz gráfica de Vault

Vault a igual que otras de las herramientas de HashiCorp tiene una muy buena documentación en formato de guía y en formato de documentación. En una aplicación Java el proyecto Spring facilita su uso con Spring Vault y Spring Cloud Vault.


Picando Código: Agenda PyCon Latam 2019

$
0
0

Está disponible online la agenda para PyCon Latam 2019. Esta versión de la conferencia PyCon de 3 días comienza el 29 de Agosto y termina el 31 en Puerto Vallarta, México.

PyCon Latam 2019

Hay charlas en inglés y español y se trata de una conferencia multi-track. Tiene pinta que va a ser una excelente conferencia. Hay charlas sobre ambientes de desarrollo para Pythonistas, concurrencia y paralelismo, Web scraping, arquitectura, Internet of Things, packaging, BlockChain, Open Source, manejo de dependencias, trabajo remoto, microservicios y mucho más.

Pueden ver la agenda completa en este enlace y comprar su boleto por acá.

Picando Código: Versión 1.0 de ci_uy: La gema Ruby para validar números de cédula de identidad

$
0
0

Actualicé la gema ci_uy a la versión 1.0.0. Bueno en verdad después de publicarla a RubyGems le agregué unos metadatos al archivo gemspec para que enlazara al Changelog y otros recursos, tuve que «yankear» 1.0.0 y subir una versión nueva. Así que la versión actual es 1.0.1. La funcionalidad de la gema sigue más o menos igual desde hace años, pero dados unos cambios recientes, decidí definir la nueva versión como «estable».

Los cambios en código fueron para usar frozen string literals, usando strings inmutables y en vez de ir cambiando los Strings, hacer todo con funciones. También agregué documentación en español al README. Por costumbre, trabajo y demás, siempre tiendo a programar y publicar todo en inglés. Pero estoy seguro que el 99.9% de los usuarios de esta gema son hispanohablantes. ¡Además tenemos que luchar contra la hegemonía del inglés! Voy a intentar aplicar esos pequeños cambios cuando tenga sentido…

Otro cambio interesante es que escribí un CHANGELOG (en inglés y español). Fue interesante hacerlo porque tuve que ir al historial de commits para ir viendo qué cambió en cada versión. Pero ahora que ya está hecho, voy a mantenerlo actualizado.

No sé qué tanto cambiará el código en futuras versiones, supongo que ir confirmando que funciona en nuevas versiones de Ruby. Pero en funcionalidad por ahora no creo que haya mucho cambio. En algún momento seguramente deje de darle soporte a Ruby 1.9.3.

Para terminar el post, un screenshot de cómo se veía RubyGems en 2013 cuando publiqué la primera versión de la gema:

 

ci_uy en RubyGems

ci_uy en RubyGems

Picando Código: The Trials of Shazam!

$
0
0

The Trials of Shazam!Hace mucho tiempo que tenía pendiente leer The Trials of Shazam!, cómic de uno de mis superhéroes favoritos: Shazam. Era medio difícil conseguir la serie entera, pero este mes DC publicó una colección nueva que reúne los 12 números: The Trials of Shazam: The Complete Series (en Amazon.es y en Amazon.com). Estaba a un precio bastante conveniente así que aproveché para comprarla y leerla.

Fue escrito por Judd Winick y el arte estuvo a cargo de Howard Porter y Mauro Cascioli. El arte está bien los primeros números por Howard Porter, a veces un poco irregular. Pero los últimos números con arte por Cascioli están excelentes. Aparentemente el cómic tuvo la maldición de atrasos que ataca a los cómics de Shazam. Howard Porter estaba a cargo del dibujo, entintado y color, y dada la presión es entendible que haya tenido algunos atrasos. Supongo que las partes irregulares se pueden atribuir a ésto. Más adelante Porter sufrió una lesión en el pulgar de la mano con la que dibuja y tuvo que obtener ayuda para terminar el trabajo. (La serie actual viene sufriendo atrasos también, va por el número 6 y el número 7 va a estar disponible 11 semanas más tarde de lo definido inicialmente).

En la época de publicación de esta serie (2006-2008), el Gran Queso Rojo todavía se llamaba Capitán Marvel y Shazam era el Mago que le había brindado los poderes. La historia se sitúa después de Infinite Crisis y Superman/Shazam: First Thunder. En Day of Vengeance, la serie limitada que condujo a Infinite Crisis, el mago Shazam es asesinado por El Espectro y el Capitán Marvel asume su lugar en la Roca de la Eternidad.

La historia en general está bastante entretenida. Al haber muerto Shazam, el mundo de la magia pierde el balance. Empiezan a aparecer Monstruos y criaturas místicas por todos lados, y el Capitán Marvel empieza a notar cambios en sus poderes. Los integrantes de la Familia Marvel, Mary Marvel y Captain Marvel Jr. pierden sus poderes mientras que Billy Batson sufre una transformación y tiene que ocupar el lugar del mago Shazam vigilando la Roca de la Eternidad. Por lo tanto, la tierra pierde a su defensor contra estos cambios y desequilibrios en el mundo de la magia.

Captain Marvel

Freddie Freeman, Captain Marvel Jr. y amigo de Billy, es elegido para ocupar el lugar del protector de la Tierra. Pero para llegar a ser el nuevo Captain Marvel, tiene que pasar por una serie de pruebas para obtener los poderes de cada uno de los dioses que dan nombre a Shazam: Salomón, Hércules, Atlas, Zeus, Aquiles y Mercurio (no en ese orden). Billy le presenta a Freddie un guía que lo va a ayudar a pasar por las pruebas y lo acompaña en esta odisea. Los dioses adquirieron forma humana en la Tierra, y Freddie tiene que ir uno por uno superando pruebas para obtener cada poder.

La aventura es bastante divertida, me leí los 12 números en dos tandas. A lo largo del camino se encuentran con varios desafíos y un grupo villanoso con la misma misión de obtener los poderes de Shazam ahora que están disponibles. Cuando parece que la historia se va a volver repetitiva, las pruebas se vuelven más diversas y vemos varios otros personajes del universo mágico de Shazam y DC. En los últimos números la acción sube varios niveles, acompañada por el excelente arte de Mauro Cascioli que comentaba antes, y termina muy arriba en cuanto a acción y desenlace.

Captain Marvel y Shazam (Bill y Freddie)

Fue un intento de tantos de presentar al Capitán Marvel a nuevas audiencias, pero fracasó. La serie deja el status quo cambiado, y podría haber dado lugar a aventuras muy interesantes en el contexto de Shazam y el mundo mágico, pero con condiciones distintas a lo que estamos acostumbrados. Había planes de mantener una serie mensual de haber sido exitosa. Pero parece que no vendió tan bien. Lo que pasó en esta historia fue revertido poco después, pero bien se podría haber continuado una saga de historias de Shazam en un universo alternativo al «principal».

Como conclusión, es una historia entretenida y recomendable. Es distinta, divertida y tiene mucha magia y acción. Otro buen cómic de Shazam para la colección.

 

Navegapolis: El talento se da mejor en las empresas en las que no se confrontan egos, sino ideas.

$
0
0

thumb reuniones agilesEn algunas empresas es arriesgado expresar abiertamente opiniones y críticas. En ellas la creatividad ágil no fluye, porque la falta de seguridad para manifestar las ideas propias y cuestionar las de otros produce pensamiento de grupo: organizaciones con personas que se acostumbran a modelar su opinión según lo que consideran que es el consenso del grupo, y a apoyar decisiones que individualmente considerarían desaconsejables.

Son empresas que pueden producir trabajo, pero no innovación, porque como decía Steve Jobs en "The Lost Interview" los grandes productos surgen en equipos que cuestionan y critican abiertamente las ideas.

 

Pero hay que tener cuidado, porque la crítica sin una cultura basada en la honestidad, el respeto y la confianza, acaba enfrentando a las personas, no a las ideas, y sólo produce tensión y desgaste.

Las siguientes citas de Ed Catmull, fundador y presidente de PixarAnimation y Disney Animation, extraídas del capítulo 5 (Sinceridad y franqueza) de su libro "CREATIVIDAD, S.A." describen muy bien el ecosistema de comunicación y la cultura necesaria para producir ideas y productos brillantes.

 

Navegapolis: El talento se da mejor si no se confrontan los egos, sino las ideas.

$
0
0

thumb reuniones agilesEn algunas empresas es arriesgado expresar abiertamente opiniones y críticas. En ellas la creatividad ágil no fluye, porque la falta de seguridad para manifestar las ideas propias y cuestionar las de otros produce pensamiento de grupo: organizaciones con personas que se acostumbran a modelar su opinión según lo que consideran que es el consenso del grupo, y a apoyar decisiones que individualmente considerarían desaconsejables.

Son empresas que pueden producir trabajo, pero no innovación, porque como decía Steve Jobs en "The Lost Interview" los grandes productos surgen en equipos en los que se cuestionan y critican abiertamente las ideas.

 

Pero hay que tener cuidado, porque la crítica sin una cultura basada en la honestidad, el respeto y la confianza, acaba enfrentando a las personas, no a las ideas, y sólo produce tensión y desgaste.

Las siguientes citas de Ed Catmull, fundador y presidente de PixarAnimation y Disney Animation, extraídas del capítulo 5 (Sinceridad y franqueza) de su libro "CREATIVIDAD, S.A." describen muy bien el ecosistema de comunicación y la cultura necesaria para producir ideas y productos brillantes.

 

Navegapolis: El talento se da mejor si no se confrontan los personas, sino las ideas.

$
0
0

thumb reuniones agilesEn algunas empresas es arriesgado expresar abiertamente opiniones y críticas. En ellas la creatividad ágil no fluye, porque la falta de seguridad para manifestar las ideas propias y cuestionar las de otros produce pensamiento de grupo: organizaciones con personas que se acostumbran a modelar su opinión según lo que consideran que es el consenso del grupo, y a apoyar decisiones que individualmente considerarían desaconsejables.

Son empresas que pueden producir trabajo, pero no innovación, porque como decía Steve Jobs en "The Lost Interview" los grandes productos surgen en equipos en los que se cuestionan y critican abiertamente las ideas.

 

Pero hay que tener cuidado, porque la crítica sin una cultura basada en la honestidad, el respeto y la confianza, acaba enfrentando a las personas, no a las ideas, y sólo produce tensión y desgaste.

Las siguientes citas de Ed Catmull, fundador y presidente de PixarAnimation y Disney Animation, extraídas del capítulo 5 (Sinceridad y franqueza) de su libro "CREATIVIDAD, S.A." describen muy bien el ecosistema de comunicación y la cultura necesaria para producir ideas y productos brillantes.

 

Navegapolis: Los mejores productos se obtienen al confrontar las ideas, no las personas.

$
0
0

thumb reuniones agilesEn algunas empresas es arriesgado expresar abiertamente opiniones y críticas. En ellas la creatividad ágil no fluye, porque la falta de seguridad para manifestar las ideas propias y cuestionar las de otros produce pensamiento de grupo: organizaciones con personas que se acostumbran a modelar su opinión según lo que consideran que es el consenso del grupo, y a apoyar decisiones que individualmente considerarían desaconsejables.

Son empresas que pueden producir trabajo, pero no innovación, porque como decía Steve Jobs en "The Lost Interview" los grandes productos surgen en equipos en los que se cuestionan y critican abiertamente las ideas.

 

Pero hay que tener cuidado, porque la crítica sin una cultura basada en la honestidad, el respeto y la confianza, acaba enfrentando a las personas, no a las ideas, y sólo produce tensión y desgaste.

Las siguientes citas de Ed Catmull, fundador y presidente de PixarAnimation y Disney Animation, extraídas del capítulo 5 (Sinceridad y franqueza) de su libro "CREATIVIDAD, S.A." describen muy bien el ecosistema de comunicación y la cultura necesaria para producir ideas y productos brillantes.

 


Blog Bitix: Implementar tolerancia a fallos con Resilience4j

$
0
0
Resilience4j
Java

Hystrix ha sido una de las primeras librerías en Java disponibles para implementar varios patrones de tolerancia a fallos en los microservicios. Desde hace un tiempo ha pasado a modo mantenimiento en el que ya no se incluyen nuevas características, una de las librerías recomendadas como sustituta es Resilience4j. Resilience4j proporciona las características similares con algunas ventajas adicionales.

Los patrones útiles para aumentar la tolerancia a fallos debido a problemas de red o fallo de alguno de los múltiples servicios son:

  • Circuit breaker: para dejar de hacer peticiones cuando un servicio invocado está fallando.
  • Retry: realiza reintentos cuando un servicio ha fallado de forma temporal.
  • Bulkhead: limita el número de peticiones concurrentes salientes a un servicio para no sobrecargarlo.
  • Rate limit: limita el número de llamadas que recibe un servicio en un periodo de tiempo.
  • Cache: intenta obtener un valor de la cache y si no está presente de la función de la que lo recupera.
  • Time limiter: limita el tiempo de ejecución de una función para no esperar indifinidamente a una respuesta.
  • Además de la funcionalidad de métricas.

La ventaja de Resilience4j es que todos estos patrones para los microservicios se ejecutan en el mismo hilo que el principal y no en un aparte como en Hystrix. Su uso además no requiere de crear clases específicas para hacer uso de los patrones y pueden emplearse las funciones lambda incorporadas en Java 8.

Este artículo actualiza el ejemplo que usaba Spring Boot y Spring Cloud que implementé en su momento para la serie de artículos sobre Spring Cloud añadiendo una implementación del cliente de un microservicio con Resilience4j.

La configuración de Resilience4j se puede proporcionar mediante código Java, con anotaciones y con la integración para Spring Boot con parámetros en el archivo de configuración de la aplicación. La aplicación además de varias cosas de Spring Cloud para otros artículos de la serie consiste para el de este artículo en un servicio cliente y un servicio servidor que para ser tolerantes a fallos hacen uso de los patrones circuit breaker y time limiter para demostrar su uso.

Resilience4j para implementar los patrones lo que hace es decorar la función objetivo que hace la invocación del servicio. Si se quieren aplicar varios patrones hay que encadenar las decoraciones, por ejemplo, si se quiere limitar el número de llamadas salientes con bulkhead y el patrón circuit breaker hay que aplicar una decoración sobre la otra. En este ejemplo se aplica un time limiter y un circuit breaker usando código Java. La variable get es la que realmente contiene la llamada al servicio.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
packageio.github.picodotdev.blogbitix.springcloud.client;...@ComponentpublicclassResilience4jProxyService{@AutowiredprivateLoadBalancerClientloadBalancer;@AutowiredprivateTracingtracing;@AutowiredprivateTracertracer;privateCircuitBreakerConfigcircuitBreakerConfiguration;privateTimeLimiterConfigtimeLimiterConfiguration;publicResilience4jProxyService(){circuitBreakerConfiguration=CircuitBreakerConfig.custom().failureRateThreshold(50).recordExceptions(IOException.class,TimeoutException.class).build();timeLimiterConfiguration=TimeLimiterConfig.custom().timeoutDuration(Duration.ofMillis(2500)).cancelRunningFuture(true).build();}publicStringget(){ServiceInstanceinstance=loadBalancer.choose("proxy");URIuri=instance.getUri();Stringresource=String.format("%s%s",uri.toString(),"/service");Invocation.Builderbuilder=ClientBuilder.newClient().target(resource).request();Spanspan=tracer.newTrace().start();TraceContext.Injector<Invocation.Builder>injector=tracing.propagation().injector((Invocation.Buildercarrier,Stringkey,Stringvalue)->{carrier.header(key,value);});injector.inject(span.context(),builder);System.out.printf("Client Span (traceId: %s, spanId: %s)%n",span.context().traceIdString(),span.context().spanIdString());CircuitBreakercircuitBreaker=CircuitBreaker.of("resilience4jCircuitBreakerProxyService",circuitBreakerConfiguration);TimeLimitertimeLimiter=TimeLimiter.of(timeLimiterConfiguration);Supplier<CompletableFuture<String>>get=()->{returnCompletableFuture.supplyAsync(()->{returnbuilder.get().readEntity(String.class);});};Callable<String>getLimiter=TimeLimiter.decorateFutureSupplier(timeLimiter,get);Callable<String>getCircuitBreaker=CircuitBreaker.decorateCallable(circuitBreaker,getLimiter);returnTry.of(getCircuitBreaker::call).recover((throwable)->getFallback()).get();}privateStringgetFallback(){return"Fallback";}}

Las dependencias que hay que añadir en el proyecto son:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
plugins{id'application'id'org.springframework.boot'version'2.1.6.RELEASE'}mainClassName='io.github.picodotdev.blogbitix.springcloud.client.Main'dependencies{implementationplatform("org.springframework.boot:spring-boot-dependencies:2.1.6.RELEASE")implementationplatform("org.springframework.cloud:spring-cloud-dependencies:Greenwich.SR1")// Spring
defexcludeSpringBootStarterLogging={exclude(group:'org.springframework.boot',module:'spring-boot-starter-logging')}compile('org.springframework.boot:spring-boot-starter',excludeSpringBootStarterLogging)compile('org.springframework.boot:spring-boot-starter-web',excludeSpringBootStarterLogging)...compile('org.springframework.cloud:spring-cloud-starter-config',excludeSpringBootStarterLogging)...compile('io.github.resilience4j:resilience4j-spring-boot2:0.17.0',excludeSpringBootStarterLogging)compile('io.micrometer:micrometer-registry-prometheus:1.1.5')...}

Resilience4j proporciona añadidos de integración con Spring Boot y exportación de métricas para Prometheus.

El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando el comando ./gradle-run.sh.

Blog Bitix: Smartcards en vez de discos para una futura generación de consolas

$
0
0

Todo indica que el formato físico de los juegos está a punto de desaparecer en una futura generación de consolas no muy lejana como ya ha ocurrido en gran medida con la música o los libros. Pero los juegos digitales crean otros problemas que los juegos físicos no tienen y es el motivo por el que algunos usuarios son contrarios a solo los digitales, ¿sería posible solución a los problemas de los juegos físicos y de los digitales? Aquí teorizo sobre este tema y planteo una solución, las smartcards.

Play Station
Xbox

Hasta recientemente la forma de distribuir los juegos en las consolas y PC ha sido a través de cartuchos y discos CD, DVD, y Blu-Ray, si embargo con la masificación de internet y con anchos de banda asequibles para las conexiones residenciales de los usuarios de entre 30 Mbps, 600 Mbps y en un futuro aún más parece que es el momento de que los fabricantes y algunos usuarios estén prefiriendo un modelo de distribución basado en la descarga digital por internet. De hecho Microsoft con la Xbox One All-Digital ya ni siquiera posee lector de discos y todos los juegos ha de ser adquiridos a través de su tienda, la Play Station de Sony también posee su modelo de distribución digital.

El lector de discos junto con el posible sobrecalentamiento es uno los causantes de el mayor número de averías. Tarde o temprano el lector falla al ser algo mecánico, más temprano cuanto más uso se le da. Es uno de los motivos por los que si yo tuviese una consola me platearía adquirir los juegos digitales en vez de físicos estando a un precio similar o incluso un poco mayor, esto no quiere decir que considere que los digitales deberían ser mas baratos porque la distribución de los mismos es más sencilla y barata. Otro motivo por el prefiero los juegos digitales es porque me ocupan espacio y en mi caso no estoy apegado a tener las cosas tangibles para adorarlas como si fuesen totems de dioses, vamos que no necesito verlas colocadas en una balda cogiendo polvo.

Sin embargo, algunos usuarios prefieren los discos por el apego sentimental que pueden tenerle al objeto por los buenos momentos de diversión que les ha proporcionado. Otros quizá por coleccionismo. Algunos prefieren poseer algo tangible de lo que compran y en algún caso porque con razón consideran que en el caso de los digitales es la empresa la que realmente posee el juego y no quieren que sea la empresa la que tenga ese poder, si desaparece todo los bienes digitales que adquirieron ¿que pasaría con ellos? ¿también desaparecerían? Si Microsoft decide cerrar la división de juegos porque no está obteniendo el rendimiento esperado todas las personas podrían perder sus posesiones digitales.

Las smartcards como hipotética solución

De esto que das un paseo andando o estás cansado a punto de dormir y después de haber un par de vídeos anteriormente o hablado con alguien sobre el tema le das una vuelta y se te ocurre una forma de como solucionar un problema, en este caso el de la posesión física y compatibilizarlo con las descargas digitales. He estado viendo dos vídeos en dos canales de YouTube que hablan precisamente de este tema, uno de tonondor y otro de Vídeo Blog (seguro que hay más de otros usuarios de YouTube), y como solución a los problemas anteriores de fiabilidad del lector de discos y la posesión física frente a la digital se me ha ocurrido que una solución podría ser el reemplazo de los discos por una smartcard.

El concepto de una smartcard es un objeto tangible como una tarjeta de crédito que correspondería a la posesión física de un disco al que reemplazaría, al contrario de los discos no tendría almacenamiento sino que simplemente sería algún tipo de credencial de que su poseedor concede el derecho a usar un juego. Lógicamente esta smartcard debería estar dotada de suficientes medidas de seguridad para que no pueda ser suplantada. El lector de disco con partes mecánicas sería reemplazado por un lector de tarjetas inteligentes por contacto o contacless como ya funciona numerosas tarjetas de crédito y bonos de medios de transporte.

Quedada resuelta la posesión física de los juegos con la smarcard, queda como descargarlos y en este modelo que planteo la descarga se realizaría a través de internet tal como ocurre en los juegos digitales. Una vez descargado el juego ya no sería necesaria la conexión a internet y solo introducir la smartcard en cada inicio del juego, en cada 3 inicios o cada 3 días para evitar la incomodidad de tener que usar la smartcard en cada inicio.

Resuelta la posesión física y la descarga queda como poseer la imagen de juego como si de un disco físico se tratase y podría ser dando la posibilidad de guardar la imagen instalable de juego en un disco duro externo ya sea en una imagen ISO u otro formato de imagen. Nuevamente tanto la smartcard como la imagen de disco debería estar dotada de suficientes medidas de seguridad para que estos no puedan ser alterados, suplantados o usados de forma ilegítima pero si lo han hecho con los discos blu-ray no veo por que no puedan hacerlo con el sistema de smartcard.

Queda resolver como poder descargar las imágenes de los juegos en una fecha tan posterior del lanzamiento de la consola como 20 años después pero mientras la seguridad esté en la posesión de la smartcard como forma de poder jugar al juego en la consola incluso no tendría por que ser Sony, Microsoft o Steam las que distribuyan las imágenes de los juegos y podría ser cualquier otra entidad o usuario incluso mediante torrent.

Con las smartcards el mercado de segunda mano del que se nutren algunas tiendas como forma alternativa de negocio a la venta de juegos nuevos precintados podría seguir funcionando exactamente igual cosa que con los digitales es susceptible de desaparecer. Por supuesto, las smartcards serían algo más pequeñas que los discos, posiblemente tan fáciles de crear y con un coste no muy diferente.

Picando Código: Agenda NotPinkCon 2019 – la conferencia de seguridad informática en Buenos Aires, Argentina

$
0
0

Ya está publicada la lista de oradoras y agenda de NotPinkCon, la conferencia de seguridad informática a realizarse el 30 de agosto en Buenos Aires, Argentina.
NotPinkCon

El evento posee un enfoque técnico y la entrada es libre y gratuita para todas las personas que deseen formar parte. Va a haber charlas en español e inglés sobre varios temas como: ¿qué tan seguro es el código abierto?, herramientas de código abierto para la investigación de amenazas, seguridad en la nube, seguridad móvil, Raspberry Pi, ciberespionaje e Internet Of Things.

Visiten la agenda completa y regístrense por acá. Pueden seguir a @NotPinkCon en Twitter para estar al tanto de todas las novedades.

Fixed Buffer: Descanso (Mode: ON)

$
0
0
La imagen muestra un terreno en mi pueblo y se ve una casita de paja que estoy haciendo.

Después de casi un año, ya tocan unas merecidas vacaciones, así que he pensado en dedicar la entrada de esta semana para avisaros de que me voy a tomar unas pequeñas vacaciones para descansar, estar con la familia, (y terminar la casita de paja de la foto xD).

Después de cojer fuerzas, volveremos en septiembre con varias cosillas interesantes que estoy preparando.

¡Os deseo unas buenas vacaciones a todos, y nos vemos en unas semanas!

**La entrada Descanso (Mode: ON) se publicó primero en Fixed Buffer.**

Picando Código: GNOME y KDE co-organizan el Linux App Summit en Noviembre

$
0
0

La fundación GNOME y KDE e.V se enorgullecen en anunciar Linux App Summit 2019. El Linux App Summit (LAS) se llevará a cabo en Barcelona desde el 12 al 15 de Noviembre de 2019.

Linux App Summit

LAS es el primer evento colaborativo co-organizado por las dos organizaciones desde el Desktop Summit en 2009. Ambas organizaciones están ansiosas por juntar a sus comunidades en construir un ecosistema de aplicaciones que trascienda las distribuciones individuales y amplíe el mercado para todos los involucrados.

KDE y GNOME dejarán de tener un rol pasivo en el sector del escritorio libre. Con la influencia conjunta de ambos proyectos de escritorio, LAS guiará el crecimiento del escritorio Software Libre y de Código Abierto (FOSS) alentando la creación de aplicaciones de calidad, buscando oportunidades de compensación para desarrolladores FOSS, y generando un mercado vibrante para el sistema operativo Linux.

El director ejecutivo de GNOME, Neil McGovern dice, «LAS representa uno de varios pasos hacia un ecosistema de escritorio próspero. Al asociarnos con KDE mostramos el deseo de construir el tipo de ecosistema de aplicaciones que demuestra que el Software Libre y de Código Abierto son importantes; la tecnología y organización que construyamos para alcanzar esto es valiosa y necesaria.«, LAS será la intersección donde desarrolladores de aplicaciones, diseñadores, ingenieros del espacio de usuario y kernel trabajen juntos construyendo un ambiente que apunta a crear un nuevo mercado para aplicaciones en Linux.

«A través de los años hemos construido soluciones geniales que usan millones de personas en el mundo. Ha sido cuando hemos trabajados juntos que hemos logrado ser más grandes que la suma de las partes. En conjunto con NOME, contando con la colaboración de muchas distribuciones y desarrolladores de aplicaciones, tendremos la oportunidad de trabajar lado a lado, compartir nuestras perspectivas y ofrecer la plataforma sobre la que será construida la próxima generación de soluciones.«, Aleix Pol Gonzalez, Vice-Presidente de KDE e.V sobre el esfuerzo inaugural de LAS.

Como la primera conferencia de su tipo, los temas en los que se centrará LAS serán crecer el ecosistema de aplicaciones para Linux así como proveer una plataforma para que otros compartan ideas y tecnología. Con eso en mente, los temas en los que estamos interesados son:

* Crear, empaquetar y distribuir aplicaciones
* Diseño y usabilidad
* Comercialización
* Comunidad / Legal
* Plataforma
* Ecosistema de aplicaciones Linux

El CFP está abiero y cierra el 31 de Agosto. Se pueden enviar ideas de charlas en éste enlace.

«Estoy emocionado de ver a GNOME y KDE trabajando juntos en LAS, y creo que el evento ayudará a sentar bases sólidas para desarrollo colaborativo a través de proyectos que beneficiaría a los usuarios de Linux de todas las distribuciones y en cualquier dispositivo compatible. Espero ver amplio soporte de la comunidad por el evento y, como usuario, ansío cosechar los beneficios de las semillas que se han sembrado.» – Christel Dahlskjaer, líder de proyecto de Private Internet Access y freenode.

Esperamos verlos a todos en Barcelona y construir el ecosistema de aplicaciones juntos.
Para más información sobre LAS, por favor visita el sitio web del evento.

Viewing all 2718 articles
Browse latest View live