Variable not found

Enlaces interesantes 557

febrero 26, 2024 07:05

Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

.NET MAUI / Xamarin

Otros

Publicado en Variable not found.

» Leer más, comentarios, etc...

Blog Bitix

Configurar GNU/Linux para usar forward DNS y el servidor DNS de Consul

febrero 24, 2024 04:00

Una de las cuestiones que tenía pendiente de mirar sobre Consul es como hacer que un nodo con GNU/Linux pueda acceder al catálogo de servicios mediante la interfaz DNS que ofrece Consul. Para esto es necesario configurar el forward DNS.

Continuar leyendo en Blog Bitix

» Leer más, comentarios, etc...

Variable not found

Deserialización y serialización personalizada en .NET con System.Text.Json usando custom converters

febrero 20, 2024 07:18

.NET

Hace poco, andaba enfrascado en el proceso de modernización de una aplicación antigua que, entre otras cosas, guardaba datos en formato JSON en un repositorio de archivos. Dado que se trataba de una aplicación creada con .NET "clásico", la serialización y deserialización de estos datos se realizaba utilizando la popular biblioteca Newtonsoft.Json.

Al pasar a versiones modernas de .NET, esta biblioteca ya no es la mejor opción, pues ya el propio framework nos facilita las herramientas necesarias para realizar estas tareas de forma más eficiente mediante los componentes del espacio de nombres System.Text.Json. Y aquí es donde empiezan a explotar las cosas 😉.

Si habéis trabajado con este tipo de asuntos, probablemente habréis notado que, por defecto, los componentes de deserialización creados por James Newton-King son bastante permisivos y dejan pasar cosas que System.Text.Json no permite. Por ejemplo, si tenemos una clase .NET con una propiedad de tipo string y queremos deserializar un valor JSON numérico sobre ella, Newtonsoft.Json lo hará sin problemas, pero System.Text.Json nos lanzará una excepción. Esa laxitud de Newtonsoft.Json es algo que en ocasiones nos puede venir bien, pero en otras puede puede hacer pasar por alto errores en nuestros datos que luego, al ser procesados por componentes de deserialización distintos, podrían ocasionar problemas.

Por ejemplo, observad el siguiente código:

var json = """
           {
              "Count": "1234"
           }
           """;

// Deserializamos usando Newtonsoft.Json:
var nsj = Newtonsoft.Json.JsonConvert.DeserializeObject<Data>(json);
Console.WriteLine("Newtonsoft: " + nsj.Count);

// Intentamos deserializar usando System.Text.Json
// y se lanzará una excepción:
var stj = System.Text.Json.JsonSerializer.Deserialize<Data>(json);
Console.WriteLine("System.Text.Json: " + stj.Count);
Console.Read();

// La clase de datos utilizada
record Data(int Count);

Para casos como este, nos vendrá bien conocer qué son los custom converters y cómo podemos utilizarlos.

¿Qué es un custom converter?

Un convertidor personalizado o custom converter es un componente que podemos insertar en el proceso de serialización y deserialización de System.Text.Json para que se encargue de convertir valores JSON en objetos .NET y viceversa. Este componente nos permite tener un control muy fino sobre los procesos de serializacón y deserialización, lo que nos puede ser útil en situaciones en las que necesitamos adaptar el comportamiento de System.Text.Json a nuestras necesidades, como por ejemplo cuando nos encontramos casos como el que hemos visto antes.

En la práctica, los custom converters son clases que implementan la interfaz JsonConverter<T>, donde T es el tipo de dato .NET de las propiedades cuya serialización o deserialización queremos controlar. Por ejemplo, en el caso anterior, donde nuestra propiedad era de tipo int, necesitaríamos implementar un JsonConverter<int>.

Esta interfaz requiere la implementación de dos métodos:

public class MyCustomConverter : JsonConverter<T>
{
    public override T Read(ref Utf8JsonReader reader, Type typeToConvert, 
                           JsonSerializerOptions options)
    { 
    }

    public override void Write(Utf8JsonWriter writer, T value, 
                               JsonSerializerOptions options)
    {
    }
}   
  • El tipo genérico T es el tipo de dato hacia o desde el que queremos convertir, según hablemos de deserialización o serialización. Por ejemplo, si usamos un int, el conversor sería utilizado cuando:
    • Se está deserializando y System.Text.Json encuentra una propiedad de tipo int en la que debe almacenar el valor presente en el JSON.
    • Se está serializando y hay que generar la representación JSON de una propiedad de tipo int.
  • Read(): usado durante la deserialización, este método se encarga de obtener el valor JSON entrante y transformarlo en el objeto de tipo T que retorna.
  • Write(): escribe sobre el writer JSON el valor del objeto de tipo T que recibe como parámetro.

Vamos a ver un ejemplo práctico de cómo implementar un custom converter para serializar y deserializar propiedades de tipo int. Para ello, crearemos una clase heredando de JsonConverter<int>, como la siguiente:

public class IntConverter : System.Text.Json.Serialization.JsonConverter<int>
{
    public override int Read(ref Utf8JsonReader reader, Type typeToConvert, 
                             JsonSerializerOptions options)
    {
        // Aquí implementaremos la lógica de deserialización, es decir,
        // convertiremos el valor JSON que recibamos a entero
    }

    public override void Write(Utf8JsonWriter writer, int value,
                               JsonSerializerOptions options)
    {
        // Aquí implementaremos la lógica de serialización,
        // es decir, convertiremos del valor entero a un número JSON
    }
}

No siempre tendremos que implementar ambos métodos. Si, por ejemplo, únicamente vamos a necesitar deserializar de forma personalizada, podríamos dejar el método Write() vacío, o viceversa.

Veamos ahora cómo implementar cada uno de estos métodos.

Deserialización personalizada con custom converters

El método Read() es el encargado de deserializar el valor JSON entrante y convertirlo en un objeto de tipo T. En el caso de nuestro ejemplo, donde estamos trabajando con un int, el método Read() podría ser algo así:

public override int Read(ref Utf8JsonReader reader, Type typeToConvert,
                         JsonSerializerOptions options)
{
    switch (reader.TokenType)
    {
        case JsonTokenType.String:
            return int.TryParse(reader.GetString(), out int stringValueAsInt) 
                   ? stringValueAsInt : 0;
        case JsonTokenType.Number:
            return reader.TryGetInt32(out int numberValueAsInt) ? numberValueAsInt : 0;
        case JsonTokenType.True:
            return 1;
        default:
            return 0;
    }
}

Se trata de un ejemplo básico, pero creo que os valdrá para que os quedéis con la idea de que aquí podríamos implementar cualquier tipo de lógica de deserialización. En este caso, la lógica es muy simple, pues sea cual sea el valor JSON entrante, intentaremos generar un valor entero para él:

  • Si es una cadena, la parsearemos para transformarla en un valor entero.
  • Si es un número, lo usaremos tal cual.
  • Si es un true, devolveremos 1 (porque nos apetece, podríamos haber elegido cualquier otro criterio)
  • En otros casos, siempre retornaremos el valor 0.

Fijaos que podemos acceder al valor JSON entrante usando el objeto reader que nos llega como parámetro. Con él, podemos determinar el tipo de dato que estamos leyendo y actuar en consecuencia: si es un JsonTokenType.String, obtenemos su valor con el método reader.GetString() e intentamos convertir el valor obtenido a entero; en cambio, si es un JsonTokenType.Number, intentamos obtener el valor como entero, mientras que si es un JsonTokenType.True, devolveremos 1. En cualquier otro caso, devolvemos 0.

Para crear deserializadores personalizados robustos, es importante considerar todos los tipos de datos JSON que pueden llegarnos y realizar las acciones de conversión apropiadas para que en todos los casos el método retorne un valor que encaje con lo que necesitamos.

Serialización personalizada con custom converters

La serialización es normalmente más sencilla, pues consiste únicamente en representar con JSON el valor de la propiedad, que nos llega en el parámetro value del método Write().

En nuestro caso, que estamos trabajando con un entero, la implementación de este método sería algo así:

public override void Write(Utf8JsonWriter writer, int value, 
                           JsonSerializerOptions options)
{
    writer.WriteNumberValue(value);
}
Como podéis intuir, el objeto writer dispone de un buen número de métodos WriteXXX() para generar valores JSON de múltiples tipos:  WriteStringValue(), WriteBooleanValue(), WriteNullValue(), etc., por lo que se trata simplemente de usar el o los métodos apropiados en cada caso para emitir el JSON que queramos.

Aplicar el custom converter a operaciones de serialización y deserialización

Seguro que en este punto os habéis dado cuenta de que falta algo, ¿verdad? Hemos implementado nuestro custom converter, pero en ningún sitio le hemos dicho a System.Text.Json que lo utilice, por lo que no tendrá ningún efecto.

Para que se utilice nuestro custom converter tendremos que añadirlo a las opciones de serialización o deserialización que estemos utilizando, materializadas en un objeto de tipo JsonSerializerOptions. Seguro que habéis usado esta clase alguna vez para configurar opciones de casing, ignorar propiedades, etc. Pues bien, también podemos añadir nuestros custom converters a estas opciones.

var options = new JsonSerializerOptions();
options.Converters.Add(new IntConverter());
// Podemos establecer otras opciones aquí, por ejemplo:
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
...

Luego, podemos usar estas opciones tanto para serializar como para deserializar:

var options = new JsonSerializerOptions();
options.Converters.Add(new IntConverter());

// Se usará nuestro custom converter para deserializar las propiedades `int`:
var data = System.Text.Json.JsonSerializer.Deserialize<Data>(json, options);

// Y también para serializarlas:
var json = System.Text.Json.JsonSerializer.Serialize(data, options);

¡Hasta aquí hemos llegado!

Obviamente, lo que hemos visto es sólo el principio. Podemos crear custom converters para cualquier tipo de dato, y no sólo para tipos primitivos, sino también para tipos complejos, como por ejemplo, para deserializar fechas en un formato específico, colecciones, diccionarios, etc.. En algunos casos la cosa se puede llegar a complicar un poco, pero nada que no pueda resolverse en un ratillo de diversión 😉 De hecho, me apunto para ver la implementación de algunos de estos casos algo más complejos en un post futuro.

Espero que os resulte útil en proyectos en los que tengáis que lidiar con JSON, sobre todo si tenéis que ser compatibles con otros sistemas cuyos criterios de serialización o deserialización sean distintos a los proporcionados por defecto por las bibliotecas de .NET.

Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

Cómo conseguir que los parámetros de un constructor primario de C# sean de sólo lectura

febrero 19, 2024 07:27

C#

Hace unos días, veíamos por aquí los constructores primarios de C#, una característica recientemente introducida en el lenguaje que permite omitir el constructor si en éste lo único que hacemos es asignar los valores de sus parámetros a campos de la clase.

Veamos un ejemplo a modo de recordatorio rápido:

// Clase con constructor tradicional
public class Person
{
    private readonly string _name;
    public Person(string name)
    {
        _name = name;
    }
    public override string ToString() => _name;
}

// La misma clase usando el constructor primario:
public class Person(string name)
{
    public override string ToString() => name;
}

Como comentamos en el post, los parámetros del constructor primarios eran internamente convertidos en campos privados de la clase, generados automáticamente e inaccesibles desde el código.

Sin embargo, los valores de los parámetros podían ser modificados desde los miembros de instancia, lo cual podría resultar bastante problemático, sobre todo porque es habitual que los parámetros suministrados a un constructor sean almacenados en campos de sólo lectura, como hemos visto en el ejemplo anterior de uso del constructor tradicional.

Por ejemplo, observemos el siguiente código, donde no podemos asegurar que la salida de ToString() sea el valor suministrado al constructor porque quizás se realizó una llamada previa a Set() y su valor fue modificado:

public class Person(string name)
{
    public override string ToString() => name;
    public void Set() 
    {
        name = "Otro nombre";
    }
}

Podemos comprender mejor por qué se comporta de esta forma si echamos un vistazo al código que genera el compilador durante la construcción del proyecto. En él podemos ver que internamente el método Set() está sobrescribiendo el valor directamente sobre el campo privado autogenerado y, por tanto, cualquier modificación al valor del parámetro afectará al resto de miembros que lo utilicen:

public class Person
{
    [CompilerGenerated]
    private string <name>P;

    public Person(string name)
    {
        <name>P = name;
        base..ctor();
    }

    public override string ToString()
    {
        return <name>P;
    }

    public void Set()
    {
        <name>P = "Otro nombre";
    }
}

Para los que solemos capturar en miembros readonly los parámetros proporcionados a un constructor, esta posibilidad es realmente peligrosa porque puede dar lugar a comportamientos inesperados y fallos difíciles de cazar. Por ello, me ha alegrado descubrir que, aunque obligue a teclear algo más, hay formas sencillas de evitar las modificaciones de los parámetros del constructor primario.

Cómo hacer que un parámetro del constructor primario sea de sólo lectura

Una primera idea consiste en añadir a la clase un campo readonly con el mismo nombre que el parámetro del constructor primario, y asignarle el valor del parámetro recibido. Este escenario será detectado por el compilador, que ya no tendrá necesidad de generar un nuevo campo privado para almacenar el valor del parámetro porque usará el que estamos proporcionando.

Creo que se entiende mejor si lo vemos en código:

public class Person(string name)
{
    private readonly string name = name;
    public override string ToString() => name;
}

Al compilarlo, el código generado será equivalente al siguiente. Observad que ya no existe el campo autogenerado <name>P porque se utiliza directamente el campo name que hemos añadido:

public class Person
{
    private readonly string name;

    public Person(string name)
    {
        this.name = name;
        base..ctor();
    }

    public override string ToString()
    {
        return name;
    }
}

Y obviamente, al tratarse de un campo de sólo lectura, la inserción de un método como el siguiente generará un error de compilación:

public class Person(string name)
{
    private readonly string name = name;
    public override string ToString() => name;
    public void Set()
    {
        name = "Otro nombre"; // Error CS0191: No se puede asignar 
                              // un valor a un campo readonly
    }
}

Una variante de la solución anterior, que además nos viene mejor si seguimos alguna convención específica para el nombrado de campos privados (por ejemplo, usar el guion bajo como prefijo), se basa en insertar el modificador in en el parámetro del constructor primario. Cuando se hace esto, dicho parámetro deja de estar accesible desde los miembros de la clase y, por tanto, sólo podemos usarlo durante la construcción de la instancia. Es decir, el siguiente código fallaría en compilación:

public class Person(in string name)
{
    public override string ToString() => name; // error CS9109: Cannot use ref, out, or in 
                                               // primary constructor parameter 'name' 
                                               // inside an instance member
}

De esta forma aseguramos que el valor del parámetro del constructor primario no será modificado (vaya, ni siquiera leído) desde el código de la clase. Y partiendo de esto, podríamos ahora añadir un campo privado de sólo lectura, con el nombre que nos interese, para poner el valor a disposición del miembro que lo necesite:

public class Person(in string name)
{
    private readonly string _name = name;
    public override string ToString() => _name;
}

Como curiosidad, el código generado por el compilador es el equivalente al siguiente, bastante similar al que vimos al principio del post, en el ejemplo donde usábamos constructores tradicionales:

public class Person
{
    private readonly string _name;

    public Person([In][IsReadOnly] ref string name)
    {
        _name = name;
        base..ctor();
    }

    public override string ToString()
    {
        return _name;
    }
}

¡Espero que os sea de ayuda!

Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

¡Nuevo curso de Blazor 8 en CampusMVP!

febrero 19, 2024 07:27

Blazor

Como seguramente sabréis, Blazor es la gran apuesta de Microsoft para el desarrollo de aplicaciones web con .NET. Sólo hay que ver la cantidad de novedades que han introducido en la última versión para darse cuenta de que están poniendo toda la carne en el asador y, de alguna forma, está convirtiéndose en la opción preferida para el desarrollo de este tipo de aplicaciones.

Pues bien, es un placer anunciaros que, tras varios meses de preparación, hace unos días hemos puesto en marcha el nuevo curso de desarrollo de aplicaciones Web con Blazor en .NET 8, como siempre, en CampusMVP.

Ha sido un trabajo duro, porque esta última versión ha venida cargada de novedades (sobre todo en lo relativo al nuevo modelo unificado propuesto por las Blazor Web Apps) y hemos tenido que revisar en profundidad y reescribir parte del contenido del curso, rehacer ejemplos y regrabar material audiovisual, todo con el objetivo de seguir siendo el mejor y más completo curso de Blazor del mercado.

En este post voy a intentar responder a las siguientes preguntas:

¿Qué es Blazor?

El objetivo de partida de Blazor era bastante ambicioso: ofrecer a los desarrolladores .NET un framework para la construcción de aplicaciones web SPA, similar a otros como Angular, React o Vue, pero usando exclusivamente C#. Vaya, el sueño dorado de aquellos a los que JavaScript siempre les ha parecido la parte más dura de programar para la web ;)

Es decir, a diferencia de las soluciones tradicionales para crear aplicaciones web SPA:

  • Utilizaremos los entornos de desarrollo con los que nos sentimos cómodos los desarrolladores .NET, como Visual Studio, para crear, programar, depurar, testear y distribuir nuestras aplicaciones.
  • O, como ocurre en toda la nueva generación de tecnologías del ecosistema .NET, podremos desarrollar y ejecutar sobre cualquier sistema operativo y usar herramientas más ligeras como Visual Studio Code o la línea de comandos de .NET.
  • Utilizaremos C# en lugar de JavaScript para implementar la capa de presentación, algo que hasta ahora no era posible conseguir, con las ventajas que ello conlleva.
  • Aprovecharemos los conocimientos que ya tenemos de .NET para crear aplicaciones web SPA. Es decir, podremos usar los tipos y clases de .NET con las que llevamos años trabajando, pero para crear aplicaciones que corren en el navegador.
  • Será posible reutilizar código existente en todas las capas de las aplicaciones, así como compartir código entre cliente y servidor, pues ambos utilizarán las mismas tecnologías.

Seguro que alguno pensará que todo esto lo ha escuchado antes, pero el protagonista era el denostado Silverlight. Nada más lejos de eso; no estamos hablando de "incrustar" código .NET en un browser usando tecnologías propietarias como hacíamos años atrás, en la era RIA (Rich Internet Applications), sino en una tecnología respetuosa y alineada con estándares abiertos de la web.

Sólo con lo dicho hasta ahora, las ventajas de Blazor ya podrían ser suficientes para considerarlo una opción a la hora de acometer nuevos proyectos, pero la cosa no queda ahí.

A la vista de la simplicidad, potencia y productividad del modelo de componentes que utiliza, el ámbito de Blazor ha ido creciendo y, en la actualidad, Blazor es mucho más que un framework para crear aplicaciones web SPA.

En la última versión, Blazor ya no sólo permite crear aplicaciones de frontend, sino que Blazor se ha convertido en una plataforma de desarrollo completa o fullstack, con la que podemos crear también aplicaciones ejecutadas por completo en backend (como MVC o Razor Pages, por lo que, de alguna forma, puede llegar a sustituir estas tecnologías).

Puedes leer algo más sobre Blazor en los siguientes artículos:

¿Por qué es interesante aprender a desarrollar con Blazor?

Si trabajáis en la creación de aplicaciones web con tecnologías Microsoft, la respuesta es categórica: sin duda, deberías aprender Blazor. Dejad que os explique por qué.

La imparable popularización de las aplicaciones web SPA ha traído de la mano algunos problemas para los desarrolladores .NET. Incluso los frameworks más modernos y potentes, como ASP.NET Core MVC o Web API, no ofrecen herramientas para la creación de aplicaciones SPA, por lo que nos vemos obligados a:

  • Quedar relegados al desarrollo del backend del que normalmente hacen uso de este tipo de sistemas.
  • Movernos al frontend, aprendiendo a trabajar con frameworks como Angular, React, Vue o cualquiera de los muchos otros disponibles en el ecosistema Javascript.

Si, como es bastante habitual, sois de los que tienen que tocar un poco de todo (aka full-stack developers) probablemente habréis sufrido al elegir esta última opción. Para los desarrolladores .NET, los frameworks de frontend tradicionales suelen ser un territorio hostil e incómodo porque:

  • No es sencillo elegir en cuál de las cestas poner los huevos. Aunque últimamente parece haberse relajado algo la cosa y la propia selección natural ha ido haciendo su trabajo eliminando opciones que no aportaban demasiado, durante años, el mundillo de los frameworks SPA ha vivido constantes terremotos y no era sencillo decantarse por una u otra opción.
  • Debemos utilizar herramientas distintas a las habituales, y veces no se llevan demasiado bien entre ellas, por lo que nos vemos obligados a usar distintos "cinturones de herramientas" en función de lo que vayamos a hacer en cada momento.
  • Todo esto obliga a aprender un modelo de programación completamente nuevo: sintaxis, workflows de trabajo distintos, bibliotecas de clases y componentes totalmente diferentes, herramientas diversas (y a veces poco amigables), etc.
  • Por no hablar del lenguaje... aunque tiene sus cosas buenas, la experiencia de programación con Javascript queda muy lejos de lo que supone utilizar C#, un lenguaje moderno, potente y con un sistema de tipos estricto que nos defienda de nosotros mismos y nuestros constantes errores. (Es cierto que TypeScript ha suavizado algo este asunto, pero, aún así, la experiencia no está a la altura.)

Con Blazor podremos desarrollar aplicaciones web (SPA y no SPA) profesionales, solventando todos los problemas anteriores de un plumazo:

  • La experiencia desde Visual Studio es exactamente como la conocemos: compilación, ejecución, depuración, testing, etc. Todo lo haremos usando las mismas herramientas de siempre, con las que ya somos productivos.
  • ... aunque, si lo preferimos, podremos programar utilizando Visual Studio Code o cualquier otro editor ligero al que estemos acostumbrados y usar la línea de comandos para compilar, ejecutar, testear o distribuir.
  • En lugar de JavaScript, implementaréis la lógica de la interfaz de usuario en C#, y utilizaréis la biblioteca de clases de .NET que ya conocéis de sobra.
  • Lo anterior ya hace que la curva de aprendizaje sea suave, pero, aún hay más:
    • Si conocéis Razor de ASP.NET MVC, ASP.NET Core o Razor Pages, os sentiréis muy cómodos porque es la misma sintaxis usada para crear componentes Blazor.
    • También encontraréis que una de las formas en las que podemos ejecutar aplicaciones Blazor, llamada Blazor Server, es conceptualmente similar a ASP.NET Web Forms (aunque por supuesto sin sus conocidos problemas), por lo que no os costará mucho trabajo entenderlo si partís desde ese punto.

Obviamente tendréis que aprender a trabajar con Blazor, pero al menos no deberéis dedicar tiempo a conocer a fondo el entorno, las herramientas, las bibliotecas base o el lenguaje para sacarle partido: esa lección ya la traéis aprendida de casa ;)

Pero no sólo eso. Una vez conocemos Blazor, nos damos cuenta de que está construido sobre elementos muy sencillos, pensados disparar nuestra productividad desde el minuto uno. Una vez conocéis algunos fundamentos básicos, veréis que se pueden crear componentes, o elementos visuales reutilizables, con una facilidad y velocidad pasmosas.

Con Blazor, los desarrolladores .NET podemos crear espectaculares aplicaciones web sin abandonar las herramientas ni el lenguaje que ya utilizamos a diario.

Si ya hemos trabajado con ASP.NET Core y MVC, ¿siguen valiendo estos conocimientos?

Totalmente. De hecho, si conocéis ASP.NET Core estaréis mejor posicionados para exprimir Blazor al máximo, porque hay conocimientos que podréis aprovechar directamente.

Por ejemplo, las Blazor Web Apps, que es el nuevo modelo de proyecto unificado utilizado por defecto para las aplicaciones web con Blazor, son en la práctica aplicaciones ASP.NET Core. Esto significa que heredan de la plataforma muchas funcionalidades de forma directa: inicialización, inyección de dependencias, logging, settings, middlewares, routing, etc. y, por tanto, vuestros conocimientos previos os serán de utilidad.

En caso de optar por el modelo de ejecución puro en el lado cliente, denominado Blazor WebAssembly, los conocimientos de ASP.NET Core os vendrán también de perlas para la implementación del backend, imprescindible en cualquier aplicación SPA. Además, en este caso, podréis disfrutar de las ventajas de utilizar .NET en ambos extremos: ¡compartir código C# entre frontend y backend de forma directa!

Inicialmente, la ideal de Blazor no era sustituir a MVC ni Razor Pages, simplemente cubría un hueco que anteriormente no estaba resuelto en el stack de tecnologías .NET: la implementación de aplicaciones SPA en el frontend. Por tanto, no se trataba de un reemplazo, sino de una opción adicional que simplificaba el acceso al mundo de las aplicaciones SPA.

Sin embargo, la última versión de Blazor aparecida con ASP.NET Core 8, ha traído consigo un nuevo modelo de proyecto unificado que incluye capacidades de renderización completa en servidor, por lo que, ya podríamos implementar en Blazor lo que hasta ahora hacíamos mediante vistas MVC o páginas Razor.

Lo importante, como siempre, es disponer de varias alternativas para poder elegir la más apropiada en cada escenario.

¿En qué consiste el curso de desarrollo con Blazor?

Este curso se imparte completamente online utilizando la potentísima plataforma de eLearning SELF (de los mismos que están detrás de CampusMVP), y siguiendo su contrastada metodología para asegurar tu éxito a lo largo el proceso de formación.

Curso de Blazor en CampusMVP

Sin horarios y a vuestro propio ritmo, pero no en solitario: contaréis con todo el soporte del equipo de CampusMVP y, dado que soy el tutor, me tendréis a vuestra disposición para la resolución de dudas y ayudaros durante aprendizaje.

La dedicación estimada ronda las 6 u 8 horas semanales, durante un total de 12 semanas. A lo largo de ellas realizaremos un profundo recorrido en la última versión Blazor, partiendo desde cero, a través de las más de 200 lecciones que componen el temario. Éste, además, lo podréis descargar en formato PDF (¡600 páginas!) al finalizar el curso, para que lo tengáis como referencia.

Para afianzar los conocimientos, incluimos también más de 50 vídeos, sin paja ni rellenos, directos al grano y llevados a cabo de forma magistral por el gran José Manuel Alarcón, donde podréis ver en vivo el funcionamiento de muchas de las características que vamos estudiando.

Pero el curso no sólo consiste en contenido teórico: a lo largo del mismo encontraréis numerosas prácticas que os ayudarán a conseguir una mejor asimilación de los conceptos, así como proyectos descargables, consejos, trucos e ideas que seguro os resultarán de utilidad cuando vayáis a aplicar vuestros nuevos conocimientos en el mundo real.

¿Y cómo saber vuestro nivel de aprovechamiento? Sencillo. Conforme vayáis avanzando os propondremos autoevaluaciones que os permitirán conocer vuestro grado de conocimiento sobre los contenidos. Al finalizar el curso podréis acreditar su realización mediante un diploma, así como incluirlo en vuestro perfil certificado de CampusMVP, un perfil online verificable por terceros donde podéis demostrar qué habéis aprendido con nosotros.

¿Cuáles son los contenidos del curso?

En este curso hacemos un completo recorrido de Blazor, comenzando desde cero.

Tras una breve introducción para ponernos en contexto, inmediatamente comenzamos describiendo los distintos modelos de hosting disponibles para el desarrollo web: Blazor SSR, Blazor Server y Blazor WebAssembly. Veremos cómo funcionan, sus elementos arquitecturales y las ventajas e inconvenientes de cada uno, para que podáis elegir cuál es el que más conviene en cada caso.

A lo largo del curso estudiaremos los distintos modelos de hosting en paralelo, por lo que al finalizar estaréis en disposición de crear aplicaciones utilizando cualquiera de ellos.

Seguidamente, entraremos en faena creando nuestros primeros proyectos Blazor, echando un vistazo a la forma de organizarlos y los tipos de componentes con los que estructuraremos nuestras aplicaciones.

Estudiaremos también en la sintaxis Razor, fundamental a la hora de escribir componentes, detallando sus particularidades y diferencias respecto al Razor que usamos en MVC o Razor Pages, directivas, construcciones y técnicas para organizar y simplificar el código.

Aprenderemos las distintas fórmulas para comunicar componentes, y a sacar provecho de los eventos del ciclo de vida de los mismos, así como a controlar aspectos como la liberación de recursos o la renderización de componentes.

Empezaremos creando componentes simples, pero iremos profundizando sucesivamente hasta llegar a componentes complejos que usan toda la potencia de Blazor para crear elementos altamente reutilizables gracias a la parametrización, uso de fragmentos o tipado genérico. Veremos cómo consumir y producir eventos del sistema o personalizados para facilitar la comunicación bidireccional entre componentes.

Haremos también una parada en la inyección de dependencias y aprenderemos a utilizarla para crear componentes más sencillos, limpios y reutilizables.

Dedicaremos un módulo al sistema de navegación y routing de Blazor, aprendiendo a construir sitios navegables y controlar la navegación del usuario.

También pondremos el foco en el potente sistema de binding, ese mecanismo que enlaza la UI con nuestras clases .NET de forma casi mágica. Seguidamente, nos centraremos en estudiar las herramientas que ofrece Blazor para ayudarnos a crear formularios de datos y validar la información suministrada.

La interoperación con Javascript también toma su protagonismo en el curso. Las fórmulas para comunicar nuestro código Blazor con este lenguaje abre la puerta al aprovechamiento del enorme ecosistema del mismo, consiguiendo que en muchas ocasiones no tengamos que partir de cero a la hora de crear interfaces espectaculares.

Para la creación de aplicaciones renderizadas por completo en el servidor, iremos viendo en distintos puntos las mejoras progresivas o progressive enhancements que nos ofrece Blazor SSR para conseguir una experiencia de usuario similar a la obtenida con una SPA.

Ya casi finalizando, nos detendremos en estudiar los mecanismos de autenticación y autorización que nos permitirán construir aplicaciones seguras y adaptadas a distintos perfiles de usuario. Veremos también cómo crear aplicaciones internacionalizadas, crear y distribuir componentes reutilizables o algunas técnicas para testear nuestros componentes.

De forma trasversal, al final de cada módulo te demostraremos sobre una aplicación real cómo "encajan" los conceptos que hemos ido viendo en él. Esa aplicación es BlazorStore, la plataforma de comercio electrónico que desarrollaréis al finalizar el curso, y para la que hemos reservado sus últimas lecciones.

¿Qué conocimientos previos se necesitan para seguir el curso?

Si estáis leyendo esto, probablemente ya los tengáis ;)

En primer lugar, dado que se trata de un curso de programación de aplicaciones web, es necesario conocer los fundamentos de este tipo de sistemas, al menos a un nivel básico. Debéis saber identificar cliente y servidor, entender las responsabilidades de cada uno de estos extremos y conocer mínimamente los mecanismos de comunicación entre ellos.

También es importante que conozcáis algo de HTML y CSS, y muy recomendable que tener algunas nociones de Javascript, aunque no es indispensable.

Por último, dado que una de las premisas de Blazor es desarrollar usando C# y .NET en todos los extremos, ¡qué menos que conocerlos! En el curso asumiremos que tenéis un nivel razonable de C# y que habéis trabajado con la biblioteca de clases base de .NET. Es decir, en el curso no explicaremos qué es una expresión lambda o qué es un objeto de tipo List<string>, se supone que debéis saberlo antes de comenzar.

En cambio, no es necesario conocer nada sobre tecnologías de acceso a datos, pues el curso no entraremos en ello. En algunos ejemplos usaremos Entity Framework Core, pero no es necesario que lo conozcáis para poder seguirlos sin problema.

Me convence, ¿cuándo empezamos?

Pues ya, en cuanto queráis :) Sólo tenéis que visitar la web de CampusMVP, inscribiros, y casi sobre la marcha os facilitarán las credenciales de acceso a la plataforma.

Recordad que, si trabajáis para una empresa española, este curso podríais hacerlo prácticamente sin coste, gracias a la Formación Bonificada.

¡Eso es todo! Ahora es vuestro turno...

Bueno, pues creo que con esto quedarán despejadas todas vuestras dudas sobre el curso, o al menos muchas de ellas. Si no es así, no dudéis en contactar con CampusMVP, donde os van a atender de maravilla, o conmigo a través de un comentario, correo electrónico o usando el formulario de contacto del blog.

¡Espero veros a muchos por allí!

Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 556

febrero 19, 2024 07:05

Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Otros

Publicado en Variable not found.

» Leer más, comentarios, etc...

Variable not found

Enlaces interesantes 555

febrero 12, 2024 07:05

Enlaces interesantes

Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

.NET MAUI / Xamarin

Publicado en Variable not found.

» Leer más, comentarios, etc...

Blog Bitix

Obsidian, una herramienta para almacenar conocimiento

febrero 10, 2024 06:00

Hace ya unos meses desde que estoy usando Obsidian, pasado este tiempo considero que es un salto a los anteriores editores y aplicaciones de notas que he estado usando. A nivel personal como diario y otros asuntos ofrece varias funcionalidades que facilitan el gestionar el conocimiento y que no he visto en los anteriores editores que he usado. Es más que un editor de texto es una herramienta para almacenar conocimiento.

Continuar leyendo en Blog Bitix

» Leer más, comentarios, etc...

Picando Código

Actualización en SuperTimeTracker.com

febrero 02, 2024 11:00

Feliz día de la marmota, y felices 10 años a mi proyecto SuperTimeTracker.com 🎂

supertimetracker.com

Aprovechando que tuve que renovar el dominio (pasando por esa etapa en que uno se cuestiona: ¿debería volver a renovar el dominio o darme por vencido y abandonarlo?), actualicé un poco mi “proyecto de fin de semana”:

Super Time Tracker es una aplicación web muy simple y minimalista para gestionar el tiempo de tareas. No necesitas crear una cuenta, grupo o clientes. No necesitas compartir tu correo electrónico, nombre o número de teléfono (en su momento era una aplicación para Firefox OS). Sólo traquea tu tiempo. Tu información no es compartida con terceros y te permite traquear tiempo en paz.
La información se guarda en el cache del navegador web y se puede usar la aplicación offline (incluso bajándote el código y ejecutándola en tu computadora).

El domingo 2 de febrero de 2014 registré el dominio para subir la web, y el lunes siguiente lo publiqué en mi blog.

Una actualización “silenciosa” que le hice hace un tiempo fue eliminar Google Analytics. Sinceramente no lo revisaba hace años, y un día me dispuse a eliminar ese maldito código JavaScript de Google Analytics que tenía todavía colgado en alguno de mis proyectos. La verdad es que la cantidad de visitas que llegan ya me resulta irrelevante, particularmente cuando tienden a 0 la mayoría del tiempo. Y usar Google Analytics en mis páginas ahora que sabemos cómo usan nuestros datos todas estas corporaciones, me parece poco ético.

Los otros dos cambios son gracias a Ismael Padilla. Él mismo encontró los dos primeros errores reportados en la aplicación y abrió Pull Requests en GitHub para corregirlos. Perdón Ismael por haber demorado unos años en revisarlos y aceptarlos 😬

El primer Pull Request corrige un error que tenía al guardar una tarea mientras el reloj estaba corriendo. El reloj se detenía para volver a cero, pero el botón de play/pausa quedaba en “pausa”, por lo que había que presionarlo dos veces para volver a empezar el timer.

El segundo corrige un problema con el manejo de fechas si abrimos la página en dos ventanas de navegador distintas.

Se pueden ver los cambios en supertimetracker.com y el código fuente en GitHub.

Qué loco que ya hayan pasado 10 años, a ver si vuelvo a tener esos momentos de inspiración que dan para proyectos de fin de semana y compro algunos dominios nuevos…

El post Actualización en SuperTimeTracker.com fue publicado originalmente en Picando Código.

» Leer más, comentarios, etc...

Arragonán

Buscando el Product Market Fit y Arquitectura Hexagonal

enero 23, 2024 12:00

Hace un par de meses estuve en La Vertical by Mercadona Tech hablando sobre DDD estratégico. Al final del evento, pude conocer a algunas personas con quienes estuve compartiendo impresiones, ideas, proyectos…

En un momento dado, una persona me preguntó sobre qué opinaba de usar el estilo de arquitectura de Ports & Adapters, más popularmente conocida como Arquitectura Hexagonal, cuando el contexto es la fase de búsqueda o consolidación del Product Market Fit. Me pilló la pregunta algo a contrapié y creo que le respondí de forma un poco tibia; podríamos resumirlo con un clásico: “No lo sé, creo que depende del equipo y del contexto.

Esto es algo sobre lo que he compartido mi punto de vista en petit comité en bastantes ocasiones, así que quería extender un poco esa respuesta aterrizándolo en este artículo.

Dibujo que representa el product market fin, un hexágono dividido de driver y driven con un interrogante encima

¿Product Market Fit?

Este es el momento en el que un producto no está validado a nivel de negocio, o al menos no totalmente. Son momentos donde aún no es rentable y hay que probar a lanzar soluciones para cubrir los problemas de nuestros potenciales clientes e ir iterando (o descartando) esas soluciones. Más info sobre esto en este artículo de la lista de correo de Ignacio Arriaga: ¿Qué es el product market fit y cómo acelerarlo?.

Así que en una situación en la que no hemos consolidado el Product Market Fit, la capacidad de iterar un producto de software a una velocidad razonablemente alta es crítica para hacerlo. Más en situaciones en las que tenemos un presupuesto limitado, como suele ser el de la mayoría de startups.

¿Arquitectura Hexagonal?

Si seguimos el estilo de Hexagonal Architecture o Ports & Adapters o Clean Architecture, colocamos en el medio nuestra lógica de negocio y nos abstraemos de los detalles de implementación de infraestructura.

Esta infraestructura son tanto los driver ports que son el mecanismo de entrega para interactuar con la lógica de negocio, como podrían ser server-side rendering, REST, gRPC, GraphQL, CLI, tareas programadas… Como los driven ports que son los encargados de mantener el estado vía persistencia de datos y la comunicación hacia otros sistemas.

Las características principales de este estilo de arquitectura son la cambiabilidad de la infraestructura y, como consecuencia de eso, la testeabilidad. Ya que al utilizar inyección de dependencias nos abstraemos de las diferentes piezas de infraestructura y podemos testear la lógica de negocio de forma unitaria.

Frente a lo que me parece percibir a veces, no hay una forma única de implementar software con este estilo de arquitectura. En mi caso, ha evolucionado un poco mi forma de trabajar con este enfoque, pero como base siguen siendo bastante válidos los contenidos que compartimos en algunas charlas de hace algunos años con Coding Stones.

Lo malo

Este estilo de arquitectura se ha popularizado mucho en los últimos tiempos y ha crecido de la mano con el uso conjunto de los patrones tácticos de DDD. Tanto que para muchas personas creo que no hay diferencia, no se percibe que son cosas distintas que unas veces se complementan y otras no tiene demasiado sentido aplicar, al menos no de forma purista.

Así que esto en ocasiones lleva a sobreingeniería en el diseño, en forma de exceso de abstracciones y aumento de complejidad extrínseca, haciendo un código más difícil de modificar y extender funcionalmente. Lo que provoca que en esos casos de aplicaciones con una lógica de dominio no demasiado compleja, se ralentice la velocidad de iteración en el producto.

También, otras veces, se espera que al aplicar este estilo de arquitectura desaparezcan todos los problemas asociados a la deuda técnica. Como si ya vineran integrados mágicamente en ello principios como DRY, YAGNI, KISS, Separation of concerns, ley de Demeter, las 4 reglas del diseño simple… y nos fuera a evitar tener code smells.

Lo bueno

Para mí, lo que aporta este tipo de arquitectura en este tipo de contextos es principalmente la testeabilidad. Cuando se quiere iterar rápido, tener una batería de tests en la que puedas confiar y que se ejecuta rápido es una gran ayuda para mantener el foco en lo que estás desarrollando.

En segundo grado, la cambiabilidad nos aporta que podemos posponer decisiones, por ejemplo, usando soluciones de infraestructura a priori simplistas que nos permitan validar que se aporta valor a pequeña escala, sabiendo que de ser necesario, podemos cambiarla en el futuro con menos esfuerzo al no afectar al diseño.

Depende del equipo y del contexto

Sobre el contexto, empiezo desde una situación en la que se ha llegado a la conclusión de que no podemos servirnos de herramientas no-code ni de un prototipo o prueba de concepto que podamos tirar a la basura dentro de pocos meses. Así que no nos quedan más narices que desarrollar algo que pueda evolucionar, iterarse y adaptarse a lo que nos vayamos encontrando en el futuro.

Normalmente en estos casos seremos un equipo pequeño, con capacidad financiera limitada tanto para contratar como para subcontratar y donde querremos tener buena capacidad para entregar software. Porque, de lo contrario, difícilmente podremos iterar nada.

Cualquier decisión técnica para mí debería ir encaminada a usar soluciones conocidas siempre que sea posible. En general, creo que la línea a seguir es la de Choose Boring Technology, con más razón en el caso de estar consolidando el Product Market Fit.

Algunas preguntas que podemos hacernos para pensar sobre esto: ¿Quiénes formamos parte del equipo? ¿Cuánto hemos trabajado usando el estilo de arquitectura de Ports & Adapters? ¿Nuestro software tiene un dominio con cierta complejidad o se parece más a CRUD que encajaría bien acoplado con algún framework? ¿Tenemos algún framework de desarrollo con el que todas las personas del equipo seamos productivas? ¿Sabemos o hemos comprobado si estaremos peleando contra ese framework si lo combinamos con ese estilo de arquitectura? …

Alternativas

En algunas ocasiones, mi aproximación ha sido quedarme un poco a medio camino, utilizando alguno de los artefactos o prácticas que habitualmente se asocian a la Arquitectura Hexagonal, pero manteniendo el acoplamiento al framework en cierto puntos. Esto es: capa de use cases para representar lo que hace el producto de software, inyección de dependencias para tener piezas cambiables y hacer que la lógica sea más fácil de testear y, si encaja con las necesidades iniciales del producto, también modelar eventos.

Use Cases

Esta capa representa las acciones que se pueden hacer sobre el producto de software. A partir de aquí, se encapsula lógica y se orquestan las llamadas a infraestructura. En esta capa no se sabe si va a ser llamada desde un API rest, un comando desde CLI, un cron…

En mi caso, normalmente son clases con constructor y un solo método público para ejecutarlas, así que en un momento dado hasta podrían ser funciones.

En caso de que usemos un ORM (o un ODM o similar), utilizo esas mismas entidades para representar el dominio. Al menos hasta el momento donde se percibe que el modelo de dominio y el modelo de datos entran en conflicto como para tener que hacer una separación.

Inyección de dependencias

En los constructores de los use cases, hago uso intensivo de inyección de dependencias, más para ganar en testeabilidad que en cambiabilidad de la infraestructura. Esto es que en lenguajes de tipado estático, en los constructores normalmente se espera la inyección de una dependencia de una clase y no de una interfaz. El esfuerzo que sí trato de hacer al inyectar esas clases a los use cases, es no acoplarme a nivel de naming de clases y métodos sobre la implementación.

En algunas ocasiones, esta inyección la he mantenido manualmente y otras a través de algún framework de IoC, dependiendo principalmente de si el framework de desarrollo lo trae de serie o si la base de código es aún manejable sin ello.

Eventos (opcional)

En casos donde desde el inicio se observa que existen muchos side-effects en un producto tiendo a introducir eventos de dominio, seguramente no para todos los use cases, pero al menos sí los más relevantes. Pistas para introducirlos pueden ser necesidades relacionadas con: auditoría, distintos tipos de notificaciones, desacoplar la comunicación con otros módulos o sistemas, instrumentar behavioral analytics en el backend, etc.

Conclusiones

El mero hecho de usar o no Ports & Adapters no es relevante para que el producto tenga éxito, pero la capacidad de iterar rápido el producto es crítica.

Dentro de que nunca vamos a tener certezas, en momentos donde estamos buscando Product-Market fit a nivel técnico normalmente deberíamos ir hacia lo más seguro y conocido por parte del equipo. Bastantes riesgos existen en esos contextos como para asumir más.

Ya sea un estilo de arquitectura completamente acoplado a un framework, de Ports & Adapters o se quede en algún punto intermedio para desarrollar un producto de software, lo que considero innegociable para iterar rápido es acompañarlo de otras 3 prácticas técnicas:

  • Hacer testing automático, al menos unitario y de integración de forma bastante intensiva para tener confianza en los cambios y poder iterar más rápido.
  • Tener automatizado el pipeline de entrega y que lo pueda hacer cualquiera en el equipo, ya sea pulsando un botón o con un push en el sistema de control de versiones.
  • Preparar un mínimo de telemetría técnica y de producto, para saber de forma temprana si han surgido problemas en producción a partir de un cambio y poder analizar cómo es el comportamiento de quiénes están usando el producto.

» Leer más, comentarios, etc...

Blog Bitix

Compro un soporte de monitor para ganar espacio en la mesa

enero 20, 2024 06:00

Finalmente he adquirido un soporte de monitor junto con unas bandejas para regletas y enchufes. Ha sido una gran mejora inmediata para ganar espacio y organización de mi mesa. Ahora tengo mucha más comodidad y una mesa en la que puedo dejar muchos más elementos si necesito para la tarea que realice. Un soporte de monitor es algo a comprar adicionalmente al monitor pero el espacio liberado en la mesa lo vale.

Continuar leyendo en Blog Bitix

» Leer más, comentarios, etc...

Picando Código

Libros que leí en 2023

enero 18, 2024 01:10

En 2023 leí unos cuantos libros muy buenos. En el post sobre libros de 2022 me había fijado el objetivo de leer al menos 20 libros en 2023. Lo superé habiendo leído 22 títulos, y estoy bastante contento con haber agregado libros de esta lista a mi lista de “libros favoritos”. Visitar librerías y descubrir libros nuevos sigue siendo una de las actividades que más disfruto. Vivo encontrando cosas nuevas para leer, por autores y autoras que sigo (tanto sus nuevas obras como recomendaciones), y la lista de libros que quiero leer aumenta a ritmo más acelerado del que puedo leerlos. Pero es un buen problema a tener.

A continuación una lista en el orden cronológico en el que los leí y un breve comentario sobre cada uno. ¡Con suerte alguien descubre algo nuevo que le interesa!

Libros 2023

🇮🇪 Motherfócloir – Darach Ó Séaghdha es un libro sobre el idioma Irlandés (el primer idioma oficial de la República de Irlanda, seguido por el Inglés). Fue un regalo de un amigo cuando visité Cork en Irlanda el año pasado. Habla sobre las experiencias del autor con respecto al lenguaje en distintas etapas de su vida. Con el genocidio cultural que han hecho los ingleses a lo largo de la historia en prácticamente todo el mundo, se complejiza la relación e identificación cultural de personas en lugares donde existen otros idiomas, pero se habla el inglés. Pasa bastante por estos lados con Irlanda, Gales y Escocia, donde existen idiomas nativos pero se ha impuesto el idioma inglés. En lo personal me resulta sumamente interesante y disfruté mucho la lectura. El idioma Irlandés y el Gaélico Escocés están bastante relacionados. Siendo estudiante de Gaélico, me resultó particularmente interesante aprender sobre las diferencias y similitudes. Además de enseñarnos varias cosas de la cultura irlandesa y su relación con el lenguaje (al punto que podemos aprender a decir unas cuantas cosas en Irlandés), el autor tiene una forma muy divertida de escribir.

♀ Just Get on the Pill – Krystale E. Littlejohn Un libro que no es necesariamente “entretenido”, pero de repente sí necesario. Una de las tantas injusticias del patriarcado, en una relación entre un hombre y una mujer la responsabilidad de la prevención del embarazo cae casi exclusivamente sobre la mujer. El libro es bastante académico, con una investigación intensiva de cómo esta responsabilidad está desbalanceada y la sociedad responsabiliza a la mujer cisgénero, pero no son las únicas afectadas por esta injusticia. A ver cuándo aparece “la píldora” para los hombres…

✒ Sign Here – Claudia Lux Uno de los libros de ficción más entretenidos que leí en el año, Sign Here (“firme aquí”) es la novela debut de Claudia Lux. El principal protagonista es Peyote Trip (“Viaje de Peyote”), un tipo que trabaja en el quinto piso del Infierno. Se encarga de conseguir personas que acepten vender su alma. Por un buen tiempo va trabajando en conseguir un ascenso, para lo cual necesita que un miembro más de la familia Harrison venda su alma. Es muy atrapante, me resultaba difícil de soltar, siempre queriendo leer un capítulo más para saber qué pasa a continuación. Es de esos libros que lograron transportarme a la situación, a veces se sentía como estar dentro de una película. Me gustaría leer más situaciones en las oficinas del infierno, que al final del día, no son tan distintas a las oficinas en nuestro mundo porque el capitalismo trajo el infierno a nuestras vidas diarias.

Este es de esos tantos libros que tuve en la mira por meses y no recuerdo exactamente de dónde lo saqué. Hay muchos de ese tipo en esta lista. Después de tanto tiempo en mi lista de libros por leer, finalmente lo adquirí y lo agregué a la pila. Es una pequeña victoria: haber encontrado el libro por azar, leerlo y haberlo disfrutado, y sacarlo de la lista de libros por leer. Divertido, gracioso y oscuro, recomendado.

Recientemente me encontré con la versión tapa blanda de este libro en una librería. Me llamó la atención y noté que en la tapa decía que próximamente va a haber una serie de televisión basada en el libro. ¡Puede estar buena!

🚬 Los peligros de fumar en la cama – Mariana Enríquez Este libro me lo prestaron en inglés con el título “The Dangers of Smoking in Bed “. Pero Mariana Enríquez es una escritora argentina cuyos libros se publican originalmente en español. Ha adquirido mucha popularidad en librerías por éstos lados, y generalmente se encuentran sus obras traducidas al inglés. Ésta en particular es una colección de historias cortas de terror psicológico. Los cuentos son bastante oscuros, macabros y fantásticos, mezclado con un poco de familiaridad Latinoamericana. Esa es la sensación que me dió al leerlo, encontrar esas características familiares dentro de lo diverso que he venido leyendo, además de ser historias muy buenas. Lo disfruté mucho y recomiendo que lean a Mariana Enríquez si les gusta la literatura de terror. Tiene otro libro de cuentos cortos que voy a tener que leer también.

🕴 Diaboliad – Mikhail Bulgakov Mirando libros al azar en una librería me encontré con varios libros de Mikhail Bulgakov, autor ruso de principios del siglo 20. Me llamó la atención el diseño de las tapas, y leyendo de qué se trataban decidí comprar Diaboliad. Korotkov, un trabajador de oficina es despedido por un error de su trabajo en el almacén central principal de materiales para fósforos y se embarca en una aventura Kafkaesca que desemboca en lo surreal. Me resultó muy interesante la premisa, y es la primera historia de esta colección. El autor tiene un estilo particular y distinto, fue una buena lectura y entretenida, seguramente lea algún libro más de Bulgakov en algún momento.

🏴󠁧󠁢󠁳󠁣󠁴󠁿 The Wee Free Men – Terry Pratchett Hace mucho leí los dos primeros libros de la serie Discworld de Terry Pratchett: The Colour of Magic y The Light Fantastic. Tengo una amiga que es muy fanática de esta saga y me venía recomendando “The Wee Free Men” prácticamente desde que nos conocimos. Culpo a mis problemitas mentales el no haber leído este libro antes. Cada vez que iba a una librería, miraba los libros de Pratchett a ver si lo tenían. Pero ninguna de las ediciones que encontraba era similar en arte y/o tamaño a la edición que ya tenía de los anteriores títulos de la saga Discworld. Y quería que todos los libros de Discworld tuvieran un estilo similar en mi biblioteca. Un día encontré una que era lo suficientemente parecido y lo compré. No podía tener libros dispares en la colección de Pratchett…

The Wee Free Men son los Nac Mac Feegle, “pequeños hombres libres” de piel azul que incorporan en su dialecto cosas de dos de los lenguajes oficiales de Escocia: Scots y Gaélico. Según Pratchett “hablan una mezcla de Gaélico, Scots antiguo, Glaswegiano y pavadas”. Estos seres acompañan a la protagonista Tiffany Aching en la búsqueda de su hermano perdido. Es un libro bastante entretenido, si ya han leído a Pratchett saben qué esperar. ¡Fantasía con humor! Hay cuatro libros más en la saga Mundodisco con estos personajes, tengo que leer más Pratchet.

🔥 Farenheit 451 – Ray Bradbury Cuando un profesor de física me “envenenó” con la literatura distópica, recuerdo que me comentó sobre la trilogía imperdible de libros representativos del género: 1984, Un Mundo Feliz (Aldous Huxley) y Farenheit 451. Después de muchos años, leí el último de estos tres que me faltaba. Farenheit 451 es una novela distópica clásica, en una sociedad donde los libros están prohibidos y existe una fuerza de bomberos que se dedican a quemar los libros que encuentren. Lo recomiendo si disfrutan de la ficción distópica (que van a encontrar varios más del género en esta lista). Es un libro que aperece en muchas listas de “mejores novelas de ciencia ficción”, da para relectura y análisis. Ojalá le pudiera agradecer a Pedro el profe de física por haberme envenenado con estos libros.

⛈ The Mercies – Kiran Millwood Hangrave Es 1617 en la remota isla Noruega de Vardø y todos los hombres de la isla perecen en un instante cuando una viciosa tormenta ataca el mar en pleno viaje de pesca. La isla es ahora un lugar de mujeres. Pero un tiempo más tarde aparece una figura autoritaria a poner orden en este lugar habitado por mujeres independientes. Es una novela histórica, basada en hechos reales que sucedieron durante el siglo 17. Los detalles de lugares, objetos y demás está muy bien y ayudan a transportarse a ese momento y lugar. Fue un libro muy entretenido que me gustaría volver a leer. ¡Recomendado!

🤖 Robot Uprisings – D. H. Wilson & J. J. Adams –  En febrero/marzo estuve de visita en Uruguay donde me reencontré con muchas de mis porquerías materiales que tenía guardadas en un depósito. Entre ellas encontré mis libros. Este era uno de esos libros que tenía sin leer en mi colección, y se transformó en mi compañero durante las vacaciones. Tiene cuentos de varios autores distintos sobre robots e inteligencia artificial (de la divertida, no la mierda que los cocainómanos de Silicon Valley nos quieren vender hasta en la sopa éstos días). Si bien recuerdo varios de los cuentos, el que más me gustó fue “Sleepover” de Alastair Reynolds. Empieza con una premisa bastante familiar pero la historia se va lejos y te vuela la cabeza. Voy a tener que leer algo más de este escritor. Incluye un cuento de Cory Doctorow, lo primero que leí del autor este año, pero no lo último. El libro es ciencia ficción pura, y éstas colecciones están muy buenas para conocer autores nuevos.

🎮 Ask Iwata – Hobonichi & Sam Bett – Estaba al tanto de este libro, pero no fue hasta que me lo encontré de casualidad en una librería que decidí adquirirlo. Satoru Iwata fue CEO de Nintendo por varios años y en etapas bastante significativas. Este libro es una colección de varias conversaciones y entrevistas (incluyendo Iwata Asks) respecto a desarrollo de videojuegos, la gestión de Nintendo y más. Me resultó muy interesante y ayuda a entender varias de las particularidades de Nintendo como compañía. Incluso cuando habla de cosas más “corporativas” u orientadas a temas de trabajo, tiene una perspecitva bastante particular y entretenida. Para tener una idea de la personalidad del libro, una frase famosa de Iwata San: “En mi tarjeta de presentación, soy presidente corporativo. En mi mente, soy un desarrollador de videojuegos. Pero en mi corazón, soy un gamer”.

🚔 Attack Surface – Cory Doctorow –  Primer libro de Doctorow que leí este año, y mi primer introducción a los audiolibros. Por haber participado del Kickstarter, recibí la versión audiolibro de Attack Surface. Así que decidí probar cuando salía a caminar, ir escuchando un audiolibro en vez de música. Empecé con Force Multiplier, una historia nueva sobre Marcus Yallow (de Little Brother y Homeland) disponible a través del Kickstarter. La experiencia me resultó interesante, y me daba algo con qué distraerme mientras caminaba. Así que empecé a escuchar Attack Surface, pero iba alternando entre leer y escuchar hasta que decidí terminar leyéndolo. Lo interesante es que me quedaron en la memoria las voces que escuché antes, así que los personajes tenían estas voces en mi cabeza cuando leía.

Attack Surface es la tercera entrada en la saga de Little Brother. A diferencia de los dos anteriores, no se trata de una novela para “jóvenes adultos” y la protagonista es Masha, la joven que trabajaba para el DHS (Department of Homeland Security) y eventualmente una firma privada de seguridad. Masha navega la línea entre lo que está bien y lo que está mal entre su trabajo en Infosec instalando software de vigilancia para gobiernos represores, y los activistas a los que apunta esa represión. También aprendemos un poco en qué anda Marcus Yallow en éstos tiempos. Es muy fiel al estilo de Doctorow.

🕵 Red Team Blues – Cory Doctorow – Ya que estaba leyendo a Doctorow, y lo iba a ver en persona, seguí con su -hasta el momento- más reciente libro. Red Team Blues es un poco distinto, si bien mantiene el estilo del autor en lo que respecta a nerdismo informático, es más una novela detectivesca. Es la primera novela en una serie protagonizada por Marty Hench, un contador forense, retirado que se dedica a destapar estafas y estafadores de Silicon Valley. Me resultó entretenido y fácil de leer, pero no creo que siga la saga de Marty Hench por ahora. Doctorow tiene 2 libros más escritos, el siguiente “The Bezzle”, sale en unos días.

😈 Nuestra parte de noche – Mariana Enriquez –  Me gustó tanto el formato cuento corto de Mariana Enríquez que tenía que ver qué tal se traducía al formato novela. Fue una grata sorpresa ver su nueva novela “Nuestra parte de noche” en versión traducida al inglés en prácticamente todas las librerías de Edimburgo, incluso copias autografiadas. Pero no adquirí este libro en inglés, lo compré cuando estuve de visita por Uruguay a principio de año. La persona que me prestó su libro de cuentos cortos que comenté antes lo consiguió en inglés, yo en español, y lo leímos en simultáneo.

Tiene el estilo característico de la autora, y aplica lo mismo que comenté en su libro de cuentos cortos. Juan y su hijo Gaspar atraviesan Argentina por carretera, desde Buenos Aires hacia las cataratas del Iguazú. Son los años de la junta militar, hay controles de soldados armados y tensión en el ambiente. La madre de Gaspar murió en circunstancias poco claras, Gaspar está destinado a ser medium en una sociedad secreta que contacta con la Oscuridad mediante atroces rituales, y Juan lo quiere proteger de ese destino. Una frase de la contratapa lo describe muy acertadamente: “El terror sobrenatural se entrecruza con terrores muy reales en esta novela perturbadora y deslumbrante”.

🏢 The Unit – Ninni Holmqvist – Otra novela de esta ola de literatura distópica (que generalmente se agrupa con “The Handmaid’s Tale” de Margaret Atwood) que tanto disfruto. La autora es Sueca y la novela fue traducida al inglés por Marlaine Delargy. El escenario es una sociedad en el futuro no muy distante donde las personas denominadas económicamente inútiles se envían a una comunidad de retiro llamada “the Unit”. Teóricamente libres de problemas financieros, cuentan con apartamentos lujosos, instalaciones de última generación, jardines, comida gourmet, arte y música. El precio: los residentes se conocen como “prescindibles”, deben donar sus órganos uno por uno a medida que sean requeridos, hasta que no quede nada por donar. La historia sigue a Dorrit Weger, una nueva “prescindible” en la Unidad, y cómo la naturaleza humana lleva a demostrar las fallas y crueldad de este sistema. Es muy bueno y es interesante conocer nuevas situaciones distópicas potenciales que no son difíciles de imaginar se impongan mañana en el tipo de distopía en el que vivimos.

✊ Terrible Worlds Revolutions – Adrian Tchaikovsky –  Adrian Tchaikovsky es un nombre que empecé a ver seguido recorriendo las secciones de ciencia ficción de librerías. Después de agarrar varios de sus libros para ver de qué iban, un día encontré “Terrible Worlds Revolutions” acompañado, y me llamó la atención enseguida. Unos meses más tarde recibí el libro como regalo de cumpleaños.

El primer cuento es un poco militarista, pero bastante entretenido. Acción y ciencia ficción, con corporaciones horrendas como en la vida real, y soldados que habitan mechas. El segundo está basado en el cambio climático, también con aspectos de ricos contra pobres y un poco de inteligencia artificial (de la entretenida, no la mierda que los cocainómanos de Silicon Valley nos quieren vender estos días). El tercero es en un escenario un poco más fantástico, con humanos compartiendo el mundo con “ogros”. Me pareció que este último es el que más apela al espíritu de rebelión, y me encantó. Cada cuento me gustó y me atrapó más que el anterior. Como comenté con el primero, me resultó entretenido, pero el segundo me atrapó un poco más y el tercero me pareció excelente. El hilo conductor es esa idea de “mundos terribles” y “revoluciones” que le dan el título. Seguramente lea más de este autor, y probablemente vuelva a leer estos cuentos, muy recomendado.

🇨🇳 Sinopticon – Xueting Christine Ni – Este libro es una colección de 13 historias de ciencia ficción de China, traducidas por primera vez al inglés. La traductora y editora hace un excelente trabajo en la selección. Las historias están muy buenas y representan un espectro diverso de autores y autoras (siendo el más viejo de 70 años al momento de la publicación y la más joven de 20), así como la temática de las historias. Cuenta con una introducción muy interesante sobre Kehuan 科幻 (el término Chino para ciencia ficción), las distintas decisiones tomadas para la traducción, la selección de cuentos y más. Al final de cada cuento agrega una sección de notas, con comentarios sobre su autor o autora y la historia.

Disfruté muchísimo de esta colección, la recomiendo mucho. Los cuentos recorren lugares comunes de la ciencia ficción, pero muchas veces nos sorprenden con giros inesperados. Está muy bueno y ya agregué algún libro de autores Chinos a mi lista de libros por leer.

🫖 A Psalm for the Wild Built – Becky Chambers – Debería haber escrito un post entero sobre la serie “Monk and Robot” de Becky Chambers. Este es otro de esos libros que en algún momento me llamaron la atención y lo agregué a mi lista para “leer eventualmente”. Este año lo adquirí y fue uno de los mejores libros que leí y pasó a mi lista de libros favoritos. Así como me gusta mucho la ciencia ficción distópica como algunos de los títulos que he listado, esta saga estaría en la categoría diametralmente opuesta de ciencia ficción. El escenario es un mundo utópico en el futuro, un género que se denomina “solarpunk”, movimiento literario más optimista con imágenes de un futuro sustentable interconectando naturaleza y comunidad.

La historia es protagonizada por Dex, monje de té que viaja por las áreas habitadas por humanos. Ofrece sus habilidades para preparar té adaptado a las personalidad de cada persona y ofreciendo un rato para escuchar sus problemas y necesidades. Un tiempo atrás, los humanos usaban robots para hacer trabajos manuales. Hasta que un día los robots se volvieron concientes de su existencia, abandonaron las herramientas y se fueron a vivir en la naturaleza (el sueño de mucha gente que trabaja en IT, incluyéndome). Un día Dex se encuentra con Mosscap, un robot enviado con la misión de retomar el contacto con los humanos y la no trivial tarea de averiguar “¿qué necesitan?”.

Es un cuento de ciencia ficción optimista, utópico, sano, inteligente y sumamente entretenido. El mundo constuido por la autora dan ganas de que exista, perderse en él y pensar y filosofar distintas cuestiones. Me encantó y estoy seguro que lo voy a volver a leer.

🌐 The Internet Con – Cory Doctorow – Otro de los libros que leí de Cory Doctorow, aunque este es no-ficción. Explica la historia de cómo las grandes corporaciones de tecnología nos han ido encerrando en sus jardines privados y mantienen a su base de usuarios rehén de sus sistemas. Expone cómo empresas como Microsoft, Twitter, Facebook y demás corporaciones enemigas de la humanidad han luchado contra la interoperabilidad y cómo podemos defendernos. Debería leerlo de nuevo, sobre todo los últimos capítulos, porque me quedé con la impresión de que faltó esa gran solución. De repente gran parte de las cosas ya las sabía, y por eso no me resultó tanto un descubrimiento. O debería seguir con la lectura recomendada para adentrarme más en el tema…

🏭 The Factory – Hiroko Oyamada – Esta novela la pondría en una categoría similar a Diaboliad comentado más arriba. La historia sugeriría entrar en un hilo distópico, pero se va transformando en algo muy “El Proceso” de Kafka, y desemboca en lo surreal. Bastante fácil de leer, entretenida e interesante aunque un poco loca. Creo que así como le entré yo sin saber mucho más, es la mejor forma de leerlo para que todo sea una sorpresa. Otra novela de la autora, “Weasels in the Attic” es bastante popular y la he visto en varias librerías, y me la comentó el señor de la tienda donde compré este libro. Así que de repente para 2024 leo esta otra novela más reciente.

🗣 VOX – Christina Dalcher – En algún momento del año (pasado) me encontré con VOX y Femlandia de Christina Dalcher. Leyendo las contratapas, los agregué a mi lista de libros por leer inmediatamente. Siempre que los volvía a ver pensaba “tengo que leer esto”, hasta que eventualmente me decidí por VOX por ser el primero en orden cronológico. Me gustó mucho, lo agrupo con la corriente literaria que comenté en The Unit más arriba. Se ha vuelto uno de mis géneros favoritos. Es una novela distópica donde las mujeres pierden control sobre sus pasaportes, trabajos, cuentas de banco e incluso el acceso a la lectura, seguido de un dispositivo que no les permite hablar más de 100 palabras por día (o el dispositivo les da un choque eléctrico que va aumentando su intensidad cuanto más se pasen del límite). Me gustaría pensar que es un concepto sumamente disparatado, pero la sociedad en la que vivimos no está tan alejada. Muy entretenido e interesante, muchas veces perturbador, sumamente recomendado. Al momento de escribir esto ya leí la siguiente novela de la autora: Q, y también lo voy a recomendar, seguido de Femlandia que está agregado a mi lista de libros para leer en 2024.

🤖 A Prayer for the Crown Shy – Becky Chambers – El segundo libro en la serie “Monk and Robot”. Después de leer el primero, sabía que no iba a tardar en conseguir el segundo. Creo que hasta me gustó más, pero no sé si debido a las circunstancias en las que me encontraba al momento de leerlo, o realmente es mejor que el primero. De todas formas voy a releer ambos títulos en algún momento, son de esos libros que hacen bien. ¡Ojalá termine siendo al menos una trilogía! Este título empieza donde terminó el anterior, incluso encontré que existe una edición en español que incluye ambos. No tengo más que agregar que lo comentado en el primer libro. ¡Muy recomendado!

🧚 The Fairy Tales of Herman Hesse – De adolescente leí bastante de Herman Hesse. Recuerdo haber leído El Lobo Estepario, Siddhartha y Demian. Me encontré de casualidad con su libro de “Cuento de Hadas” en una librería y decidí comprarlo. Lo estuve leyendo a lo largo del año, una historia a la vez cada tanto, ya que no tienen continuidad. Cada cuento y reflejan algunas posturas ideológicas del autor en contra de la guerra, nacionalismo y otras. Muy interesante, algo distinto para conocer más sobre la literatura de Hesse.

Y esos fueron los 22 libros que leí en papel en 2023, además de algunos audiolibros, pero esos no cuentan 😜

El post Libros que leí en 2023 fue publicado originalmente en Picando Código.

» Leer más, comentarios, etc...

Navegapolis

¿Por qué le llaman Agilidad cuando quieren decir lo de siempre?

enero 17, 2024 11:56

Hay titulares que se pasan de frenada, como el del libro del mismísimo Jeff Sutherland: “Scrum: el arte de hacer el doble de trabajo en la mitad de tiempo“.

Llamativo y tentador, porque ¿Quién no desea cuadruplicar la productividad?
¿Por qué vender una idea equivocada de la agilidad?
¿Para vender más libros?

Es verdad que los equipos ágiles alcanzan niveles altos de productividad, calidad y creatividad, pero esta no es la finalidad de la agilidad, sino la consecuencia. La finalidad es crear ambientes de trabajo en los que las personas trabajen motivadas y comprometidas.

La agilidad es para los que quieren equipos que disfruten construyendo productos increíbles o brindando servicios de primera. Personas que encuentran plenitud en su trabajo, no sólo un cheque a fin de mes.

Querer las consecuencias de la agilidad —hacer el doble en la mitad de tiempo— sin un interés real en el desarrollo y plenitud de las personas acaba rompiendo la magia: la motivación y el compromiso. Es como querer una pareja para obtener su dinero, sus cuidados o sus favores.

La entrada ¿Por qué le llaman Agilidad cuando quieren decir lo de siempre? se publicó primero en Navegápolis.

» Leer más, comentarios, etc...

Una sinfonía en C#

Cómo crear una imágen de Docker sin tener Docker instalado gracias a Azure

enero 16, 2024 12:00

Introducción

Todos nos hemos encontrado en la encrucijada de tener que crear una imagen de Docker y no tener Docker instalado en nuestro equipo. En este post vamos a ver cómo podemos crear una imagen de Docker sin tener Docker instalado en nuestro equipo utilizando una cuenta de Azure.

El problema

Primero necesitamos una cuenta de Azure y una instancia de Azure Container Registry a la que tengamos acceso. La idea es que teniendo el código o el binario, lo que queramos meter en la imagen (Sea lo que sea, multistae o no) y el Dockerfile podemos utilizar la capacidad de Azure Container Registry de crear una imagen a partir de un Dockerfile.

Importante, nuestro código o binario subirán a la nube durante el proceso

Entonces, teniendo ya el código o binario y el Dockerfile, vamos a crear la imagen.

Pasos para crear la imagen y subirla al ACR

Antes de nada tenemos que tener (además de la cuenta de Azure y el ACR) instalado el Azure CLI. Lo podemos descargar desde aquí

  • Hacer login en Azure
  • Seleccionar la suscripción donde tenemos el ACR
  • Crear la imagen

az login

az account set --subscription KKKKKK-KKKK-KKKK-KKKK-KKKKKKKKK

az acr build --registry miurl.azurecr.io -f Dockerfile --image test:latest .

como vemos el comando acr build es idéntico al docker build, pero en vez de utilizar el contexto local, lo hace en la nube.

Y como dije antes, tomará un tiempo porque subirá el código o binario a la nube y luego creará la imagen.

Una vez que termine, podemos ver la imagen en el ACR.

Enjoy!

» Leer más, comentarios, etc...

Blog Bitix

Hemeroteca #23

diciembre 22, 2023 05:00

Este complicado año 2023 termina con varios cambios en el blog y a nivel personal. El blog ha bajado en gran medida las visitas e ingresos por publicidad AdSense y en el que he dejado de publicar artículos con un calendario fijo semanal.

Continuar leyendo en Blog Bitix

» Leer más, comentarios, etc...

Juanjo Navarro

We're hiring!

noviembre 30, 2023 07:59

Genial esta parodia de una oferta de trabajo:

We work only with the very latest technologies, frameworks and languages. At least that’s what we claim and it doesn’t matter if there’s zero correlation to our actual product: […] It’s purely functional Web Assembly all the way to the core neural network running the heart of what’s essentially an imageboard with nicer design.

Our development toolchain is exclusively open source. This naturally doesn’t apply to our own product, because we love money. However, we do encourage all our employees to give back to the FOSS community – they just have to do it on their own free time. We’re not completely stupid.

Y sobre el proceso de selección:

A lengthy recruitment process which will take up significant amounts of your spare time, except for the interviews. We always interview on prem and during office hours.

IQ tests and bizarre questions designed to trap you in logical cul-de-sacs while simultaneously having nothing at all to do with programming or relevant domain-specific knowledge.

» Leer más, comentarios, etc...

Picando Código

Novedades de IRB en Ruby 3.3: Autocompletado basado en tipos, debug y más

noviembre 17, 2023 01:07

Estamos a pocos días del 25 de diciembre, lo que significa versión nueva de Ruby. Ya podemos ir probando Ruby 3.3 con ruby-3.3.0-preview3. Una de las tantas novedades de esta versión es IRB 1.9, con varias cosas nuevas.

Autocompletado basado en tipos

Por defecto, IRB usa expresiones regulares para el autocompletado con IRB::RegexpCompletor. El nuevo IRB::TypeCompletion, usa análisis de tipo con Prism (parser introducido en Ruby 3.3) y RSB (el sistema de tipos presentado en Ruby 3).

Para habilitar IRB::TypeCompletion, tenemos que ejecutar IRB con el parámetro --type-completor:

$ irb –type-completor

O agregar el siguiente código en nuestro archivo ~/.irbrc:

IRB.conf[:COMPLETOR] = :type # por defecto es :regexp

Con este autocompletado activado, tenemos la ventaja de contar con autocompletado de métodos encadenados, parámetros de un bloque y más si está disponible la información del tipo. Por ejemplo en un bloque:

IRB autocompletado de bloques

Al usar los elementos de un Array como parámetro del bloque enviado a map, IRB sabe que l es un String y nos muestra el autocompletado disponible, algo que no funciona con el motor basado en expresiones regulares. Lo mismo aplica a métodos encadenados:

IRB 1.9 autocompletado con Strings

Me pareció una característica bastante interesante. En este enlace podemos ver el Pull Request de esta funcionalidad y estudiar el código. Podemos leer más información en IRB: Typed Based Completion. El autocompletado se puede deshabilitar completamente ejecutando IRB_USE_AUTOCOMPLETE=false irb, o exportando esa variable de ambiente en alguno de nuestros archivos de perfil.

Integración con debug

Hace poco escribí sobre la gema debug. A partir de IRB 1.8, tenemos integración con dicha gema en IRB. Al agregar un breakpoint en nuestro código con binding.irb, podemos activar el debugger con el comando debug y empezar a usar los comandos de esa gema, además de tener habilitados los comandos de IRB:

IRB debug

 

Cambiar los colores del diálogo de autocompletado

Otra característica nueva es el soporte para cambiar el color del fondo y el estilo de la fuente del diálogo de autocompletado con la class Reline::Face.

IRB colores

Tenemos que escribir la configuración de colores en nuestro ~/.irbrc:

Reline::Face.config(:completion_dialog) do |conf|
  conf.define :default, foreground: :black, background: :bright_green
  conf.define :enhanced, foreground: :white, background: :magenta
  conf.define :scrollbar, foreground: :magenta, background: :bright_green
end

Más información en su documentación, incluyendo los códigos de colores que podemos usar.

Otras mejoras de IRB en Ruby 3.3

  • Soporte de paginador para los comandos ls, show_source y show_cmds.
  • Información más precisa y útil en los comandos ls y show_source.

Como si fuera poco, IRB ha pasado por un refactorizado (¿refactoreo?) extensivo y recibido muchos arreglos de bugs que facilitarán mejoras a futuro.

Son buenos tiempos para programar en Ruby. Ruby 3.3 va a ser más rápido y más eficiente, como cada versión de Ruby 3 desde 3.0!

El post Novedades de IRB en Ruby 3.3: Autocompletado basado en tipos, debug y más fue publicado originalmente en Picando Código.

» Leer más, comentarios, etc...

Picando Código

Disponible Tourist Trap – sorteo de claves de Steam

noviembre 15, 2023 06:03

Hoy se publicó en Steam Tourist Trap (disponible también en XBox), la aventura gráfica surrealista desarrollada en Santa Ballena, una ciudad Sudamericana afectada por la gentrificación turística. En Junio publiqué una entrevista a Manuel González y Juan Andrés Nin, desarrolladores del juego. Fueron tan amables de enviarme una clave Steam para que lo probara y unas más para regalar.

Tourist Trap

Lo he jugado en Steam con Proton en Linux, y anda bien de bien. Todavía no lo completé, pero hasta ahora me viene gustando mucho. Cumple con la premisa de la descripción cuando habla de “comedia oscura”, la intro tiene un humor característico que le va a gustar a cínicos como uno. No recuerdo la última vez que un juego me hizo largar la carcajada, pero éste lo logró con un desodorante…

Santa Ballena es una ciudad en un mundo distópico con una ambientación así medio como opresiva que caracteriza ese género. Manuel nos contaba en la entrevista que está inspirada en Maldonado y Punta del Este, y se siente muy familiar.

El juego progresa a través de la historia y puzzles, como es característico del género. Encontramos objectos y/o los obtenemos de distintas formas interactuando con gente y el ambiente, y combinando distintos objetos juntos. Algunas veces llegué a un punto que me trancaba. Pero dándole vueltas y pensando en las pistas, eventualmente encontraba cómo seguir. Cuando nos trancamos, la tecla Tab nos muestra “hotspots”, elementos con los que podemos interactuar.

El arte es otro aspecto muy bueno, las escenas como pintadas a mano y el diseño de los personajes caricaturescos y su animación están geniales. La combinación queda muy buena.

Un muy buen juego que recomiendo, ¡mucha suerte a Juan Andrés y Manuel con el lanzamiento!

Sorteo Claves de Steam para Tourist Trap (TERMINADO)

Si te interesa participar por una de las claves Steam de Tourist Trap, podés hacer cualquiera de estas dos cosas:

  • Dejar un comentario en este post expresando tu interés por participar.
  • Escribir sobre el sorteo en el fediverso (Mastodon, o equivalentes) con la URL de este post y mencionar a @picandocodigo para que pueda ver tu mensaje y agregarte a la lista (o contactame de alguna forma para agregarte al sorteo). Por ejemplo:
    Tourist Trap disponible en Steam y XBox. Participá por una clave gratis: https://picandocodigo.net/2023/tourist-trap-steam-sorteo-claves-steam via @picandocodigo

Si dejas comentario y además publicas en el fediverso vale como entrada doble. No hagan trampa, seamos buena gente. Mucha suerte, y publicaré los nombres ganadores este viernes 17 de noviembre.

🎉 Ganadores del sorteo: Arlequín y Azel_Dragoon 🎉
Les envío la clave de Steam por correo.

Dejo el tráiler más reciente de Tourist Trap:

YouTube Video

El post Disponible Tourist Trap – sorteo de claves de Steam fue publicado originalmente en Picando Código.

» Leer más, comentarios, etc...

Picando Código

Paquete de eBooks: Ruby on Rails de Pragmatic Programmer

noviembre 13, 2023 07:52

Humble Bundle tiene un nuevo paquete de ebooks sobre Ruby y Ruby On Rails de Pragmatic Programmer. Pragmatic Programmer publica muy buenos libros de Ruby, y este es un excelente paquete. Los rumores de la muerte de Ruby y Rails han sido muy exagerados. No sólo está vivo y coleando, sino que es un lenguaje en constante evolución (y se paga muy bien).

Es una excelente oportunidad para adentrarse en el hermoso lenguaje de programación que es Ruby. Si bien este paquete incluye la cuarta versión del “Pickaxe” (Programming Ruby 1.9 & 2.0), es la última publicada hasta el momento y todavía es vigente. Es considerado el libro de referencia para Ruby (y de una versión anterior aprendí mucho Ruby personalmente). Lo básico todavía sirve, y podemos leer lo nuevo de Ruby 3 cuando salga la quinta edición en diciembre.

También me interesa Learn To Program con Ruby. Lo voy a mirar para ver si lo puedo recomendar a gente que quiera aprender a programar para que empiecen de una con Ruby!

eBooks Ruby on Rails

Personalmente lo compré más que nada por Agile Web Development with Rails 7 (me tengo que poner al día con Rails después de no tocarlo en años), Ruby Performance Optimization suena interesante, Effective Testing with RSpec 3 seguro aprenda más sobre testing, Ruby Performance Optimization, y bueno, en general diría que todos me resultan interesantes menos el de Cucumber 😅

Son 13 libros al precio que elijas, con un mínimo para obtenerlos todos que al momento de comprarlo eran £ 14.63. Los ebooks están disponibles en formatos PDF, MOBI y ePub, por lo que funcionan en casi cualquier dispositivo: computadoras, e-readers, iPads, teléfonos móviles y más. La compra también apoya a la caridad Active Minds una organización sin fines de lucro que trabaja en promover la salud mental en adultos jóvenes de 14 a 24 años y en cambiar la cultura entorno a cómo hablamos de salud mental.

Compra el paquete de ebooks Ruby y Rails en este enlace.

El post Paquete de eBooks: Ruby on Rails de Pragmatic Programmer fue publicado originalmente en Picando Código.

» Leer más, comentarios, etc...

Blog Bitix

Desempaquetado de lector de libros electrónico Amazon Kindle Paperwhite (11ª generación)

noviembre 09, 2023 08:00

Una parte del tiempo libre que dispongo la dedico a la lectura, de novelas y libros técnicos principalmente. Tras tener un Kindle Touch del 2012 y venderlo me he vuelto a comprar un Kindle Paperwhite de 11ª generación. Tras casi 10 años de diferencia entre ambos dispositivos las mejoras técnicas entre ambos dispositivos son notables, teniendo el Paperwhite una pantalla mucho mejor e iluminación entre otros añadidos que hacen del Paperwhite un salto grande y merezca el cambio de dispositivo.

Continuar leyendo en Blog Bitix

» Leer más, comentarios, etc...

Blog Bitix

Desempaquetado de lector de libros electrónico Amazon Kindle Paperwhite

noviembre 09, 2023 08:00

Una parte del tiempo libre que dispongo la dedico a la lectura, de novelas y libros técnicos principalmente. Tras tener un Kindle Touch del 2012 y venderlo me he vuelto a comprar un Kindle Paperwhite de 11ª generación. Tras casi 10 años de diferencia entre ambos dispositivos las mejoras técnicas entre ambos dispositivos son notables, teniendo el Paperwhite una pantalla mucho mejor e iluminación entre otros añadidos que hacen del Paperwhite un salto grande y merezca el cambio de dispositivo.

Continuar leyendo en Blog Bitix

» Leer más, comentarios, etc...

Picando Código

Error: EDID block 0 (tag 0x00) checksum is invalid, remainder is N

noviembre 09, 2023 06:12

Hace poco compré una Raspberry Pi 4. Estoy muy contento con ella, a pesar de que al poco tiempo saliera la versión 5 con hardware mucho mejor 😅
La tengo en su case muy prolija, con el sistema instalado en un disco duro SSD, conectada a mi televisor. Uno de sus usos es para mirar servicios de streaming, películas y series.

Hace poco me empezó a pasar que dejaba de transmitir la imagen al televisor. Recomiendo de primera habilitar la conexión SSH en Raspbian (o el sistema que tengan instalado), para poder investigar cualquier problema desde otra computadora como es el caso de este post.

Como comentaba, si bien la Raspberry estaba prendida, no había imagen. Así que me conecté por SSH y empecé a buscar qué podía estar pasando. El servidor gráfico y el escritorio estaban todos funcionando aparentemente bien. Ejecuté el comando dmesg para ver los mensajes del kernel. Podemos mandarlo por pipe a less para hacer más práctica la lectura e investigación:

dmesg | less

Hay mucha información, pero esto me llamó la atención. Siempre es un buen indicativo de error ver “BAD” en el log:

[ 3.172912] EDID block 0 (tag 0x00) checksum is invalid, remainder is 110
[ 3.172944] [00] BAD 00 ff ff ff ff ff ff 00 4c 2d 7a 0a 00 00 00 00
[ 3.172957] [00] BAD 2e 16 01 03 80 59 32 78 0a ee 91 a3 54 4c 99 26
[ 3.172968] [00] BAD 0c 50 54 bd ef 80 71 4f 81 c0 81 00 81 80 95 00
[ 3.172979] [00] BAD a9 c0 b3 00 01 01 02 3a 80 18 71 38 2d 40 58 2c
[ 3.172990] [00] BAD 45 00 24 72 42 00 00 1e 66 21 56 aa 51 00 1e 30
[ 3.173000] [00] BAD 46 8f 33 00 24 72 42 00 00 1e 00 00 00 fd 00 18
[ 3.173011] [00] BAD 4b 0f 51 17 00 0a 20 20 20 20 20 20 00 00 00 fc
[ 3.173021] [00] BAD 00 53 41 4d 53 55 4e 47 0a 20 20 20 20 20 01 6b
[ 3.223212] EDID block 0 (tag 0x00) checksum is invalid, remainder is 110

Buscando en internet me encontré con este mensaje en los foros de OpenSuse.

EDID se refiere a “Extended display identification data” (en wikipedia). Se trata de la información que manda el monitor a la computadora sobre sí mismo. Y en teoría el error significa que la comunicación entre el monitor y la computadora no está funcionando bien, el paquete de información EDID no se recibió correctamente. Según dice el foro el problema se debe generalmente a cables de baja calidad. No sé si este es exactamente el problema que hacía que no hubiera imagen (ahí hablan más bien de que hay imagen pero con una resolución menor a la soportada).

Pero al conectar y desconectar el cable HDMI funcionó de nuevo. Volvió a pasar otra vez y terminé cambiando el puerto HDMI en el que conectaba la Raspberry Pi al televisor. Tanto el cable como el puerto podrían ser el problema. El cable debe tener sus años ya. Pero si tuviera que adivinar, me la jugaría a que es el televisor. Conseguí mi televisor de segunda mano, un amigo me lo vendió a un precio simbólico al comprarse un televisor nuevo. Ya tenía el uso que le dió mi amigo, ahora tiene 6 años de uso más. Hay partes de la pantalla que están como más oscuras que el resto… No te digo, te muestro:

Mi tele rota 2023

Esa sección a la izquierda donde se ve como más oscuro a la mitad de la pantalla, se nota bastante. Sí, sería tiempo de cambiar de tele… Sólo de pensar lo difícil que va a ser conseguir una tele boba que no tenga que conectar a internet.

Pero bueno, mientras no compro un televisor nuevo, sigo usando éste con mi Raspberry Pi. He hecho alguna cosa más con esta divertida computadora, ya comentaré más al respecto 😁

Foto del raspberry usado en la imagen destacada por Mockup Graphics en Unsplash.

El post Error: EDID block 0 (tag 0x00) checksum is invalid, remainder is N fue publicado originalmente en Picando Código.

» Leer más, comentarios, etc...

Metodologías ágiles. De lo racional a la inspiración.

Scrum master a tiempo completo: 42 Tareas

octubre 26, 2023 09:11

Uno de los artículos que más referencio en mi formación en Scrum cuando hablo de las labores del Scrum Master es:&nbsp;42-tasks-for-a-scrum-masters-job. Por alguna razón, todo el mundo parece entender que el Product Owner es un trabajo a tiempo completo, o ser miembro de un equipo también, pero que probablemente el rol del Scrum Master puede ser realizado a media jornada o incluso menos. El scrum

» Leer más, comentarios, etc...

Header Files

Cómo llamar a una función una única vez

octubre 13, 2023 08:00

Introducción

Algunas veces es necesario tener funciones que han de llamarse una única vez en todo el ciclo de vida del proceso. El caso que más he visto es el de funciones de inicialización, tales como la configuración de un framework de terceros, la definición de variables de entorno o la creación de zonas de memoria compartidas.

Como pasa muchas veces, C++ nos ofrece no una, sino muchas formas de resolver el problema: estudiemos algunas de ellas (spoiler, dejaré mi favorita para el final). Para facilitar las explicaciones, asumiremos que el código a ejecutar está encapsulado en una función llamada init_once() que debe ser llamada antes de que execute_many() se ejecute.

Variable bandera

Seguramente la solución más sencilla, aunque no necesariamente la más eficiente, es crear una variable a modo de bandera de uso (inicializada a false), y cambiarla la primera vez que se llame a la función.

namespace
{
    bool g_called{false};
}

void execute_many()
{
    if (!g_called) {
        init_once();
        g_called = true;
    }
    // ...
}

Variante con variable estática

Personalmente prefiero limitar el alcance de las variables todo lo posible, por lo que cambiaremos esta bandera a una variable estática local. Recordad que una variable estática se crea una única vez y perdura durante toda la vida del proceso.

void execute_many()
{
    static bool s_called{false};
    if (s_called) {
        init_once();
        s_called = true;
    }
    // ...
}

Si bien presentan una solución simple, queda la sutil posibilidad de que cambiemos el valor de la bandera por error (por ejemplo, si tenemos varias funciones de inicialización). El tema de la eficiencia claramente dependerá del contexto, aunque la gran mayoría de las veces no será un problema. Por último, estas soluciones podrían originar una condición de carrera y desembocar en una doble inicialización.

std::call_once

C++11 introdujo una forma estándar de resolver este problema, y que además es thread-safe. Como ya se dijo, las dos soluciones anteriores pecarían de crear condiciones de carrera, necesitando el uso de mutex adicionales; el uso de std::call_once es equivalente pero mucho más limpio. Básicamente sigue el mismo modelo que la solución anterior: se asocia un flag especial (thread-safe) a la función que queremos llamar una única vez:

#include <mutex>

void execute_many()
{
    static std::once_flag s_once;
    std::call_once(s_once, init_once);
    // ...
}

Uso de singletons

Otra posible solución es emplear un singleton. Un singleton es un patrón de diseño que permite restringir la creación de objetos de una clase a una única instancia. Así, podemos utilizarlo para llamar a init_once() durante la construcción del mismo (y como la clase sólo se construye una vez, sólo se llamará a la función una única vez). Una ventaja de este método frente a los anteriores es que nos evitamos la comprobación de una bandera de estado para cada ejecución. Si la función execute_many() se llama de forma masiva, pues es una mejora que ganamos. En contrapartida, la función execute_many pasa a ser miembro del singleton.

Acá una implementación sencilla pero suficiente de un singleton con inicialización única:

class Singleton
{
public:
    Singleton& get_instance() {
        static Singleton s_singleton;
        return s_singleton;
    }

    void execute_many() { /* ... */ }

private:
    Singleton() {
        init_once();
    }
};

void foo()
{
    Singleton::get_instance().execute_many();
}

Usando el operador de evaluación secuencial en la inicialización de una variable estática

La última solución que expondré es, para mí, la más limpia en términos de código generado, aunque requiere un poco más de conocimiento del lenguaje para poder entenderla. Expliquemos primero las partes que lo componen:

Operador de evaluación secuencial

El operador de evaluación secuencial es una expresión del tipo (e0, e1, …, en), donde las sub-expresiones ei son evaluadas en orden y cuyo tipo y valor final corresponden a los de en. Así, la siguiente expresión auto x = (42.0f, "hola"s) resultaría en x de tipo std::string y con valor "hola". Si una de las sub-expresiones fuese una llamada a función, ésta se invocaría, independientemente del tipo de retorno de la misma, incluido void. Por otra parte, si una de las sub-expresiones lanza una excepción, las siguientes sub-expresiones no serían evaluadas.

int a = 0;
std::cout << (a++, ++a, a) << std::endl;

try {
    (a++, throw std::exception{}, a--); // a-- is never called
} catch(...) {
    std::cout << "Exception" << std::endl;
}

std::cout << a << std::endl;

El resultado es:

2
Exception
3

Nótese que como son expresiones separadas, evaluadas secuencialmente, el uso del operador de post-incremento no se diferencia (en cuanto al resultado final) del de pre-incremento.

Inicialización de variable estáticas

Por otro lado, las variables estáticas sólo se construyen una vez, y el estándar de C++ garantiza que la inicialización de una variable estática es thread-safe; es decir, si diversos hilos pasan concurrentemente por la inicialización de la variable, sólo uno de ellos, el primero, la efectuará, quedando los demás bloqueados hasta que finalice la inicialización.

Ensamblando las partes

Con todo esto podemos construir una versión minimalista de nuestra solución, que garantizará que la función init_once() será llamada una única vez, de forma thread-safe y sin comprobaciones innecesarias de banderas de estado.

void execute_many()
{
    static const bool s_initialized = (init_once(), true);
    // ...
}

Extendiendo la solución

El principio de responsabilidad única conlleva, por lo general, a descomponer nuestro código en clases y funciones con una finalidad más acotada. En el caso que nos ocupa hoy esto puede suponer aumentar el riesgo de que la función init_once() sea llamada desde diversos lugares, debiendo aplicar los mecanismos de protección expuestos más de una vez. Esto nos lleva al eterno dilema del programador: evitar duplicar código innecesariamente.

En términos generales, la solución pasa primero por limitar el acceso a la función en sí misma. Una primera forma de hacerlo es crear una clase cuya única razón de ser sea la de invocar a esta función:

class InitOnceCaller
{
public:
    static void call_init_once()
    {
        static const bool s_initialized = (init_once(), true);
    }

private:
    static void init_once() { /* ... */ }
};

La contrapartida acá es que debemos pagar por una llamada a función adicional en caso de que el compilador no la haga inline.

En caso de que la función deba ser llamada únicamente desde un punto en concreto, podríamos mover init_once() a una lambda local.

void execute_many()
{
    static const auto s_init_once = []() { /* ... */ };
    static const bool s_initialized = (s_init_once(), true);
}

Conclusión

Se han presentado varias formas de abordar el problema de inicialización única, yendo desde la más obvia y sencilla, hasta la más completa (aunque sutilmente críptica para los menos entendidos en el lenguaje), pasando por opciones intermedias en cuanto a legibilidad y rendimiento.

» Leer más, comentarios, etc...

Juanjo Navarro

Mini Curso: Pair Programming with a Large Language Model

octubre 02, 2023 09:32

Logo DeepLearning.AI

DeepLearning.AI sigue sacando cada poco tiempo sus cursos cortos.

Se trata de pequeños cursos de una duración de alrededor de 1 hora. Aunque son muy cortos, facilitan mucho el aprendizaje inicial de una tecnología ya que proporcionan junto al video un cuaderno python donde podemos practicar, con todos los requisitos preinstalados y con un token de acceso al API de turno. Digamos que es la forma más rápida de tener un entorno montado para practicar.

Puesto que son tan cortos, es difícil no sacar algo en positivo. No obstante creo que este nuevo curso que acaban de publicar, Pair Programming with a Large Language Model, es quizá de los peor planteados.

Como parte positiva, se puede practicar con el API de Bard, lo cual si vives en Europa es especialmente práctico (en estos momentos dicho API no está accesible desde Europa). Aprendes a importar el API y a realizar las llamadas básicas para interrogar al LLM.

En la parte negativa la verdad es que está el resto. El curso no tiene mucho sentido ya que su objetivo es utilizar el API de Bard para realizar “consultas de programación” y para utilizar el LLM de Google como un “compañero de programación”: Ayudarte a programar, a debuggear, etc. Francamente, para eso no hace falta utilizar el API y se puede utilizar el chat de Bard directamente. Además, como “compañero” Bard resulta ser bastante flojo, con respuestas poco acertadas o directamente erróneas, por lo que te quedas con la sensación de que el LLM de Google está por detrás de la competencia.

Flojito.

» Leer más, comentarios, etc...

Meta-Info

¿Que es?

Planeta Código es un agregador de weblogs sobre programación y desarrollo en castellano. Si eres lector te permite seguirlos de modo cómodo en esta misma página o mediante el fichero de subscripción.

rss subscripción

Puedes utilizar las siguientes imagenes para enlazar PlanetaCodigo:
planetacodigo

planetacodigo

Si tienes un weblog de programación y quieres ser añadido aquí, envíame un email solicitándolo.

Idea: Juanjo Navarro

Diseño: Albin