Picando Código

Costumbres del código: [Lenguaje del teclado] – Parte 3

octubre 22, 2024 10:00

Hace unos 16 años, escribí un par de posts sobre el lenguaje que usaba en el teclado de mi computadora. Así fue como descubrí eventualmente la distribución de teclado que vengo usando desde hace tiempo. Cómoda para escribir en español, en inglés y programar en teclados con distribución Inglés de Estados Unidos.

Costumbres del código: lenguaje del teclado - parte 3

En Costumbres del código: [Lenguaje del teclado] , contaba cómo empecé usando un atajo de teclado para cambiar el idioma del teclado de inglés a español. En Costumbres del código: [Lenguaje del teclado] – Parte 2 había aprendido a usar la distribución de teclado Inglés alternativo internacional gracias a un comentario de Bernabé García (¿en qué andará dklight éstos días?). ¡Pero la cosa no terminó ahí! Más adelante descubrí algo incluso mejor: Inglés variante Internacional con teclas AltGr muertas (AltGr dead keys).

Esta es la variante que vengo usando desde no mucho después que publiqué aquellas dos entradas en junio de 2008. No recuerdo exactamente todas las diferencias, creo que las vocales con tilde en español se hacen igual: AltGr + la vocal. La ñ tambien es AltGr n. Pero lo que sí recuerdo es las comillas ' y ". En la variante sin AltGr muertas, se puede presionar las comillas una vez, seguida de una letra, para escribir caracteres con tilde. Para escribir la comilla en sí, hay que usar AltGr. En la variación AltGr muertas, se imprimen al presionarlas una sóla vez. Por último, los signos de apertura para exclamaciones y preguntas están en el signo en particular, presionándolos con AltGr.

Estoy seguro que había alguna razón más que no recuerdo en este momento por la cual uso la variación AltGr muertas sobre la otra. En cada instalación nueva de Linux, a la hora de definir la distribución de teclado, tengo el recuerdo (por lo menos en los instaladores gráficos) de un campo de texto para probarla. Y creo que fue así que descubrí esta otra opción con teclas AltGr muertas que vengo usando desde tanto tiempo. Puedo escribir cómodo en inglés y español, y las teclas de uso común en programación siguen estando a la mano: []. {}. ./'";:

Otra parte interesante de esta variación para mí, es que desde hace unos años estoy aprendiendo Escocés Gaélico. Este idioma también usa acentos. Pero el acento es el opuesto de nuestro tilde, signo que nos acostumbramos a usar en español desde que aprendemos a escribir. Por ejemplo el nombre del idioma en Gaélico es Gàidhlig. Y con esta distribución de teclado, aprendí a hacer vocales con el acento opuesto presionando AltGr, el tilde inverso (tecla a la izquierda del uno en teclado americano) seguido de la vocal. Así que también me queda cómodo para escribir en Gaélico. Estaría interesante ver un teclado en idioma Gaélico, el alfabeto sólo tiene 18 letras: A, B, C, D, E, F, G, H, I, L, M, N, O, P, R, S, T, U (y con estas pocas letras logran más sonidos que el idoma español).

Cada tanto recibía algún comentario que me recordaba esas dos entradas en el blog, y en mi cabeza quedaba el tema pendiente de escribir la versión que venía usando ahora. Como que estaba la culpa de no haber compartido cómo siguió la cosa. Pero con la satisfacción de la misión cumplida, cierro este post. Por ahora, y después de muchos años, esta va a ser la última entrada en el blog en la serie “Costumbres del código: [Lenguaje del teclado]”.

Distribución del teclado idioma Inglés, variación Internacional con teclas AltGr muertas

El post Costumbres del código: [Lenguaje del teclado] – Parte 3 fue publicado originalmente en Picando Código.

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

Variable not found

HybridCache, la nueva caché híbrida de .NET 9

octubre 22, 2024 07:53

Imagen decorativa sugiriendo sistemas de almacenamiento en la nube

Una de las novedades más destacables de .NET 9 es, sin duda, el nuevo sistema de caché híbrida (Hybrid cache), una puesta al día del sistema de caché distribuida que nos acompaña desde las primeras versiones de .NET Core, y al que iban haciendo falta ya algunas mejoras.

Este nuevo sistema está construido encima de la infraestructura de caching existente (Microsoft.Extensions.Caching), añadiendo mejoras que hacen que su uso sea más sencillo y contemplando de serie funcionalidades que antes nos veíamos obligados a implementar manualmente.

Vamos a echarle un vistazo a sus principales características :)

Disclaimer: lo que vamos a ver a continuación está basado en .NET 9 RC2, por lo que todavía es posible que haya cambios en la versión final.

¿Qué aporta Hybrid Cache sobre IDistributedCache?

Empecemos por la que, para mi gusto, es la principal aportación de Hybrid Cache: la protección contra estampidas.

Una estampida es el efecto que puede ocurrir en sistemas que usan caché para soportar una carga muy alta de peticiones al mismo tiempo. En ellos, si la caché se invalida por algún motivo, todas las peticiones concurrentes que llegan mientras ésta no haya sido poblada de nuevo intentarán recargarla simultáneamente, dando lugar a un ataque masivo al servidor de origen que en el peor de los casos puede llevarlo al suelo.

Con la protección integrada contra estampidas, Hybrid Cache se encarga de gestionar las peticiones concurrentes, permitiendo que sólo una de ellas llegue al servidor de origen y el resto esperen a que la caché sea repoblada. Esto es una funcionalidad que antes debíamos implementar manualmente, y no siempre era trivial hacerlo bien.

Otra característica realmente interesante de Hybrid Cache es la implementación de serie de una caché multinivel, solucionando un escenario que es bastante frecuente en sistemas distribuidos: aunque usemos un mecanismo externo como Redis, Memcached u otros, es muy habitual que también tengamos una caché en memoria en el propio servidor, para evitar tener que ir a la caché externa en cada petición.

Hybrid Cache nos permite configurar fácilmente una caché de nivel 1 (L1) en memoria del servidor (usando la clase MemoryCache de siempre), y una caché de nivel 2 (L2) en un sistema externo (usando IDistributedCache), y gestionar la sincronización entre ambas de forma transparente. Es decir, desde nuestro código simplemente escribiremos o leeremos a través de Hybrid Cache, y éste se encargará de gestionar la comunicación con la caché en memoria y la externa.

Por otra parte, como recordaréis, IDisbributedCache es una interfaz muy simple que sólo nos permite almacenar y recuperar bytes, por lo que si queríamos almacenar contenidos más sofisticados como objetos o estructuras, teníamos que encargarnos de serializarlos y deserializarlos manualmente, dando lugar a mucho código repetitivo, propenso a errores, y muchas veces poco eficiente.

Hybrid Cache ha mejorado las APIs para interactuar con la caché, con el objetivo de simplificar su uso en los escenarios más frecuentes. Los métodos para almacenar y recuperar datos de la caché son más fáciles de usar, y permiten el uso directo de objetos complejos sin necesidad de serializarlos o deserializarlos manualmente.

Por defecto, Hybrid Cache serializará sin problema las secuencias de bytes (digamos que es el formato nativo), las cadenas de texto serán convertidas a bytes UTF-8, y el resto de tipos de datos se usará System.Text.Json para obtener su representación JSON, aunque si fuera necesario, podemos configurar serializadores personalizados para tipos de datos específicos. En todo caso, el payload puede ser comprimido para ahorrar espacio y minimizar los datos en circulación.

También es interesante destacar la introducción de la invalidación basada en tags, un mecanismo que permite agrupar elementos de la caché bajo una misma etiqueta, y luego invalidar todos los elementos que tengan esa etiqueta de forma sencilla. Hasta ahora, la única forma de conseguir algo parecido era implementar manualmente algún mecanismo de agrupación externo a la caché y eliminar las entradas una a una.

La reutilización de objetos permite mejorar el rendimiento en escenarios donde los objetos almacenados en la caché distribuida son grandes o se accede a ellos con mucha frecuencia. Cuando estos objetos sean inmutables y su estado no sea alterado desde el código, es posible que Hybrid Cache pueda reutilizar el objeto entre distintas peticiones concurrentes en lugar de deserializarlo de nuevo cada vez.

Uso de Hybrid Cache

La clase abstracta HybridCache, definida en el espacio de nombres Microsoft.Extensions.Caching.Distributed es la que nos dará acceso a las funcionalidades de la caché híbrida. Internamente existe una implementación concreta de esta clase llamada DefaultHybridCache, que es la que usaremos en la mayoría de los casos, aunque será transparente para nosotros porque normalmente trabajaremos con la clase abstracta.

De momento, estos nuevos tipos no vienen incluidos en los metapaquetes básicos de .NET 9, sino que se distribuye a través del paquete NuGet independiente Microsoft.Extensions.Caching.Hybrid, que es necesario instalar en los proyectos donde queramos usarlos. A día de hoy, todavía son paquetes en preview, pero en pocas semanas serán ya definitivos.

Una vez instalado, lo habitual será registrar el servicio en el contenedor de dependencias de la aplicación, para lo que usaremos el método AddHybridCache de la clase IServiceCollection. Luego, podemos reclamar instancias de HybridCache donde deseemos usar sus servicios.

Por ejemplo, la siguiente aplicación ASP.NET Core registra HybridCache y luego lo usa desde un endpoint para almacenar y recuperar la hora actual, pero actualizándose solo cada 5 segundos:

var builder = WebApplication.CreateBuilder(args);

// Agregamos los servicios de caché híbrida
builder.Services.AddHybridCache();

var app = builder.Build();

app.MapGet("/", async (HybridCache cache) =>
{
    DateTime cachedItem = await cache.GetOrCreateAsync(
        key: "currentTime",
        factory: _ => ValueTask.FromResult(DateTime.Now),
        options: new HybridCacheEntryOptions()
                {
                    LocalCacheExpiration = TimeSpan.FromSeconds(5),
                }
        );
    return cachedItem;
});

app.Run();

Pero fijaos que en el ejemplo anterior sólo estamos usando la caché de primer nivel, porque no hemos configurado la caché distribuida o de segundo nivel. Para ello, necesitamos registrar un servicio IDistributedCache en el contenedor de dependencias; HybridCache detectará automáticamente la presencia de este servicio y usará la caché de segundo nivel.

Por ejemplo, si queremos usar Redis como caché distribuida, podemos instalar el paquete NuGet Microsoft.Extensions.Caching.StackExchangeRedis y registrar el servicio de IDistributedCache en el contenedor de dependencias de forma similar a la siguiente:

var builder = WebApplication.CreateBuilder(args);

// Agregamos los servicios de caché híbrida
builder.Services.AddHybridCache();

// Agregamos los servicios de caché distribuida con Redis
builder.Services.AddStackExchangeRedisCache(options =>
{
    options.Configuration = builder.Configuration.GetConnectionString("RedisConnectionString");
    options.InstanceName = "HybridCacheDemo";
});

var app = builder.Build();

app.MapGet("/", async (HybridCache cache) =>
{
    DateTime cachedItem = await cache.GetOrCreateAsync(
        key: "CurrentTime",
        factory: _ => ValueTask.FromResult(DateTime.Now),
        options: new HybridCacheEntryOptions()
                {
                    // Establecemos la expiración de caché local y distribuida:
                    LocalCacheExpiration = TimeSpan.FromSeconds(5),
                    Expiration = TimeSpan.FromSeconds(10)
                }
    );
    return cachedItem;
});

Obviamente, HybridCache es mucho más que lo que hemos visto aquí, pero creo que estos ejemplos son suficientes para hacernos una idea de cómo se configura y se usa. Si queréis profundizar más, os recomiendo que le echéis un vistazo a la documentación oficial de .NET 9.

¡Espero que os haya resultado interesante!

Publicado en Variable not found.

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

Variable not found

Enlaces interesantes 582

octubre 21, 2024 06:05

Enlaces interesantes

Como todos los principios de semana, aquí va la lista de enlaces recopilados durante los últimos siete días. Hay bastantes cosas que me han llamado la atención en esta ocasión; entre otros, he descubierto que Visual Studio incluye un visualizador de JWT integrado, el atributo [OverloadResolutionPriority] de .NET 9/C#13, y también me he preguntado cuántos son muchos índices en una tabla SQL 😕

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

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...

Picando Código

Analogue3D: Nintendo 64 reimaginado

octubre 16, 2024 07:30

Analogue3D Consola

Exactamente un año después de que lo adelantaran, hoy Analogue presentó su nueva consola Analogue3D.

Una reinvención del N64. En resolución 4K. 10x la resolución del N64 original. El primer y capaz el mejor sistema multijugador de todos los tiempos. Analogue3D es 100% compatible con cada juego original de N64 jamás creado. Libre de región. Bluetooth LE. Wifi doblebanda. Cuatro puertos para controles en el estilo original. Enteramente nuevo, hardware Analogue de próxima generación presentando 3DOS. Diseñado enteramente en FPGA. Sin emulación.

Si bien estaba muy entusiasmado con el anuncio original, me empecé a hacer la idea de que iba a ser carísimo. No sé por qué imaginaba un precio por encima de los 500 dólares. Los productos de Analogue son de gama alta, enfocados a la alta calidad, medio como un lujo. Pero me sorprendió ver que la consola se va a poder encargar por USD 249.99, y las preventas abren el 21 de octubre.

Hacen hincapié en el tema de la compatibilidad:

100% compatiblidad. Por primera vez. Analogue3D representa un hito en la preservación de videojuegos: no sólo es la primera reinvención de un N64 – pero la primera recreación 100% compatible de un N64. Analogue pasó casi 4 años diseñándolo en FPGA. No más problemas de compatibilidad en emulación de software como lag de entrada (input lag), inexactitudes de audio/gráficas, problemas de sincronización/velocidad de frames y más. Por primera vez, puedes volver a vivir la experiencia del N64 exactamente como debe ser, sin compromisos.

Como mencionaba en el post hace un año, particularmente interesante para alguien como yo que se cambió de país y región. Además de eliminar el problema de cómo jugar juegos americanos en consola europea o viceversa, abre la posibilidad de probar algún juego que sólo haya sido publicado en una región distintas y nos lo hayamos perdido.

Quienes crecimos con el Nintendo 64, usamos nuestras teles de tubo de rayo catódico en su momento. El mío llegó a estar conectado a mi primera televisión plana, que compré “de adulto” antes de ser archivado con el resto de mi colección. Analogue no sólo nos va a permitir jugar nuestros juegos en televisores modernos a 4K, sino que promete la misma experiencia de un CRT:

La inconfundible. Firma y alma del CRT. En tu televisor de alta definición. En 4K.

A diferencia de sus predecesores 2D, el N64 no se trataba sólo de píxeles. El enfoque distintivo del hardware original para representar polígonos y texturas depende del CRT de manera mucho más crítica que sistemas 2D más simples. Incluso los desarrolladores de videojuegos tenían que aprovechar la interacción entre el hardware y un CRT para lograr harmonía.

Mientras que muy pocos aumentadores de escala modernos han transformado la era 2D de videojuegos con claridad perfecto al pixel, el N64 demanda algo mucho más radical: la inconfundible esencia de un CRT.

Analogue3D trae calidad de referencia real de CRT a tu televisor de alta definición en 4K. Vive la experiencia del N64 con autenticidad sin par y cero lag. Es el N64, renacido.

Los modos de visualización originales de Analogue3D son recreaciones meticulosamente reproducidas, virtualmente indistinguibles de pantallas CRT. Capturando el calor, la profundidad y textura en cada cuadro. El suave brillo de fósforo y los vibrantes colores se unen con líneas de exploración inmersivas y máscaras de sombra. Esto no es sólo aumento de escala – es una transformación sin precedentes.

Esto me resulta interesante, se ve que no escatimaron gastos y realmente trabajaron para sacar la mejor recreación del Nintendo 64 posible. Veremos qué tal.

Analogue 3D colores

Un aspecto donde todavía no estoy convencido es el control. Lo he comentado un poco en el blog antes, pero la palanquita del control del Nintendo 64 es muy particular, y lo único -en mi experiencia- que se ha acercado a reproducirla son los SteelSticks. Analogue trabajó con 8BitDo para el nuevo control:

Trabajamos muy de cerca con 8BitDo para diseñar una recreación inalámbrica bluetooth del control de N64 original con un factor de forma moderno. Elaborado con una atención al detalle intransigente, los botones C, d-pad, y A/B retienen el tamaño original, sub-diseños y sensación. Presentan un joystick con efecto HALL de calidad superior, con la entrada de estilo original del N64. Dile adiós a la infame palanquita suelta que plagaba los controles originales. Y ahora puedes actualizar tu control 8BitDo 64 directamente con Analogue3D simplemente conectándolo a la consola. Un tributo a jugar N64 como nunca antes.

Tengo varios productos 8BitDo, y los controles son geniales (los prefiero por ejemplo al Pro Controller de Nintendo Switch), pero no le tengo tanta confianza para reproducir el estilo de la palanquita analógica del Nintendo 64. Hace un tiempo compré el Mod Kit 8BitDo para Nintendo 64, y poco después compré la palanquita que ofrecían. Si bien se nota que en durabilidad le ganan a las originales, son como otros reemplazos que probé. Se sienten más parecidas al Game Cube que al Nintendo 64.

De repente es cuestión de acostumbrarse, pero se nota mucha diferencia en la sensación comparado con las originales a la hora de jugar juegos de Nintendo 64. Básicamente -para mí- hacen muy difícil jugar juegos donde necesitamos precisión como F-Zero X, o incluso hasta Mario Kart 64 de repente, por falta de precisión.

Tendré que esperar, a lo mejor al haber trabajado con Analogue, lograron reproducir más fielmtente la experiencia. Y los kits que vendían para reemplazar la palanquita hasta ahora fueron más una prueba, o un paso evolutivo hacia algo mejor en este nuevo control. Igual todavía tengo mi control Atomic Purple de mi Nintendo 64 original con su SteelStick instalado. En el sitio web de 8BitDo ya tienen la información del 8BitDo 64 y las preventas abren el 21 de octubre también a USD 39.99.

La consola va a venir equipada con 3DOS, una evolución de AnalogueOS. Rediseñado para 4K, lleno de características elaboradas únicamente para N64. El sistema es compatible con los accesorios de hardware de Nintendo 64 como el Memory Pack, pero incluye lector SD y una tarjeta de 16GB. Seguramente entre las características esté salvar el estado del juego por más que el cartucho no lo soporte. Al soportar Bluetooth para los controles 8BitDo 64, imagino que otros controles 8BitDo, o los controles de Nintendo 64 de Nintendo Online, también se van a poder conectar. El Expansion Pack ya viene incorporado en el sistema.

La verdad que me entusiasmó ver esta noticia. El precio es mucho más bajo de lo que imaginaba, las características de display con filtros CRT, compatibilidad 100%, parece ser la mejor forma de revivir esas horas de Nintendo 64 en un televisor moderno.

El post Analogue3D: Nintendo 64 reimaginado fue publicado originalmente en Picando Código.

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

Juanjo Navarro

TIL: Juego de caracteres en un .bat

octubre 16, 2024 10:19

Voy a ver si escribo por aquí mis TIL. Así le doy un poco de uso al blog y estos aprendizajes diarios quedan recogidos para referencia futura y utilidad pública.

Empezando por cómo especificar el juego de caracteres de un fichero .bat.

Hoy he generado un .bat para copiar una serie de ficheros, cada fichero con una línea xcopy:

xcopy "\\ruta\nombre del fichero con acentos áé.pdf" "c:\tmp\ruta\nombre del fichero con acentos áé.pdf"

La cuestión es que esos acentos en el nombre del fichero hacían que no encontrase el fichero de origen cuando iba a buscarlo. He probado a grabar el .bat en distintos juegos de caracteres pero nada funcionaba.

Solución: Incluir una primera línea en el fichero .bat indicando el juego de caracteres del propio .bat (que era UTF-8):

chcp 65001
xcopy "\\ruta\nombre del fichero con acentos áé.pdf" "c:\tmp\ruta\nombre del fichero con acentos áé.pdf"

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

Picando Código

Reseña: Halls of Torment – Steam

octubre 15, 2024 10:00

Halls of Torment es un juego de “supervivencia de hordas”. Nuestra misión es sobrevivir Salas de Tormento que cuentan una ambientación fantástica y diabólica, y envían hordas de enemigos a atacarnos. Controlamos a distintos héroes medievales y en nuestras aventuras nos vamos a encontrar tesoros, magia, y nuevos poderes.

Halls of Torment

A primera impresión me hizo acordar a Diablo y el Gauntlet original de Atari para maquinitas (arcade). La experiencia más reciente que había tenido relativamente similar fue Diablo III. Pero es un estilo diferente, y nuevo para mí. Si bien no conocía el género, es relativamente simple de entender y agarrarle la mano, pero se vuelve desafiante bastante rápido y es un poco adictivo.

Empezamos eligiendo un héroe, entramos a la primera Sala de Tormento, y empiezan a aparecer las olas de monstruos. Movemos al héroe con las teclas WASD y apuntamos hacia donde ataca con el mouse. Podemos elegir atacar manualmente con el clic del mouse o activar ataque automático.

De a poco vamos habilitando más héroes y salas. Cada personaje tiene habilidades distintas: puntos de vida, defensa, fuerza, velocidad y más. Y al usar armas diferentes, varían totalmente las formas de ataque, lo que hace que la experiencia sea bien variada.

A medida que juntamos experiencia al eliminar hordas de enemigos, vamos subiendo de nivel (juntando los cristales que van dejando al morir). Podemos obtener equipamiento como botas, armadura y otras prendas, que mejoran las habilidades de nuestro héroe. También podemos comprar mejoras permanentes con el oro que vamos adquiriendo.

El primer héroe es un espadachín barbárico, con el que jugué mis primeras horas. Después me animé a probar el Arquero, el Clérigo que pasó a ser mi favorito, hasta que descubrí al Exterminador. El Exterminador alimenta mi espíritu piromaníaco, ¡su arma principal es un lanzallamas! Hay también Hechizera, Vikingo, la Cazadora de Bestias (¡con un perro!), son al menos 11 en total.

Halls of Torment - Exterminator

Cada Sala de Tormento tiene su propio repertorio de enemigos, demonios, magos, arqueros, fantasmas y demás criaturas espeluznantes. También nos enfrentamos a varios jefes –Señores del Tormento– que presentan un desafío más alto con patrones de ataque particulares que tenemos que ir aprendiendo para poder eliminarlos. El diseño de los personajes y las criaturas es muy bueno. Presentan muy bien este mundo oscuro de fantasía con influencias del Diablo original.

Los gráficos son estilizados como juegos de PC de los 90’s, con arte pre-renderizado. Las imágenes que acompañan este post no le hacen justicia, recomiendo ver el video al final para darse una idea de cómo funciona. Hay veces que hay más enemigos y hechizos o ataques en pantalla de los que mi cerebro puede procesar. Pero el juego nunca pierde la fluidez a pesar de la cantidad de elementos. Es muy satisfactorio (y catártico) eliminar a miles de enemigos en una misma partida.

Algo bueno que encontré es que podemos cambiar la imagen del puntero del mouse y su tamaño. Un viejo como yo agradece esta opción, en momentos me cuesta encontrarlo. Todos los detalles gráficos están muy buen cuidados, estilizado como un juego de PC de la vieja escuela, pero con todo lo que ofrece la tecnología moderna.

Halls Of Torment

Cada sesión dura 30 minutos, lo que lo hace ideal para jugar de a ratos. Esto nos tienta con la idea de “una sesión mas y ya está”, que puede terminar en un par de horas seguidas de exterminar demonios. La diversidad de personajes y distintas habilidades por jugada hacen que la rejugabilidad sea muy alta. Al ser una experiencia prácticamente nueva cada vez, sigue siendo divertido volver a jugarlo e ir probando cosas para obtener nuevos resultados e ítems. Todavía me quedan por probar uno o dos de los personajes, por ahora me sigo quedando con el Exterminador como mi preferido (¡quemen en el infierno demonios malditos!).

Cada sala tiene es bien distinta en estructura aparte de los enemigos y jefes. Es entretenido cómo el estilo o arquitectura de cada sala afecta la estrategia. El primer nivel es bastante abierto, con algunas columnas o pequeñas estructuras en el camino, lo que facilita agarrarle la mano. Después van variando, haciendo que necesitemos implementar distintas estrategias ya sea para que no nos eliminen fácilmente porque nos acorralamos contra una pared, o para atacar a las hordas de forma más efectiva.

Por ejemplo a veces podemos guiar a las hordas como para atraparlas entre estructuras como si fuera un embudo y eliminarlas más efectivamente. Una de las salas es a lo largo, entonces hay que ir moviéndose de manera distinta para atacar desde un punto mejor. En varios momentos momentos, sobretodo cuando nuestro personaje tiene un nivel bajo, las hordas de enemigos se ponen intensas y sufrimos un poco de agobio. Esa intensidad lo hace súper entretenido. Incluso cuando tenemos un nivel bien alto, a veces estamos a un par de errores de sufrir una derrota. Así que no nos podemos confiar demasiado, nos mantiene atentos.

Halls Of Torment

Como si todo esto fuera poco, tenemos los típicos achievements de Steam que nos llevan a probar y hacer cosas nuevas para completarlos. Hay 500 logros por descubrir, hay para rato. Algunos se presentan también como misiones, como “generar tanta cantidad de daño con tal personaje”. Combinado con la diversidad que ofrece en cada partida, promete muchas horas de entretenimiento.

Los requerimientos de hardware para Halls of Torment en Linux son bastante accesibles:

  Mínimos Recomendados
Sistema Operativo Ubuntu 18.04 LTS o equivalente Ubuntu 22.04 LTS o equivalente
Procesador 4 Cores / 2.5 GHz+ 4 Cores / 3.5 GHz+
Memoria 4 GB RAM 8 GB RAM
Tarjeta de video Intel Iris Xe / Nvidia GTX 970 / AMD RX 570 (Mesa 22.0) Nvidia GTX 1070 / AMD RX 570 (Mesa 22.0)
Espacio en disco 4 GB 4 GB

Entre los idiomas disponibles, podemos poner los textos en español.

¡El juego está hecho con Godot! El motor de desarrollo de videojuegos multiplataforma software libre. Cuando inicia podemos ver el mensaje de “Made in Godot”, e incluso es uno de los títulos destacados del showcase de juegos hechos en Godot. Por si había alguna duda de que Godot estuviera al nivel de juegos profesionales, Halls of Torment es uno más de los títulos que lo demuestra. Fue desarrollado por Chasing Carrots, un estudio indie alemán de 5 personas.

Un juego muy recomendado, ideal para este mes tenebroso, y para hacer catársis asesinando esqueletos y demonios malignos. Cuando parece que se largaron la mayor cantidad de hordas posible a atacarnos y nuestro héroe resiste hasta el final, destruyendo a todos y cada uno de los enemigos, es una muy buena sensación. Tiene una puntuación altísima en reseñas de la comunidad en Steam, con reviews “abrumadoramente positivos”. Si lo jugaron, o lo llegan a probar después de leer esto, cuenten qué tal en los comentarios.

Trailer de lanzamiento de Halls of Torment:

YouTube Video

El post Reseña: Halls of Torment – Steam fue publicado originalmente en Picando Código.

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

info.xailer.com

xaWeb

octubre 15, 2024 07:20

Tengo el gusto de anunciaros un nuevo proyecto de OZ Software para desarrollar páginas web con nuestro querido lenguaje Harbour utilizando la tecnología CGI. El slogan: ‘desarrollo web rápido y fácil‘ describe claramente los objetivos principales de la herramienta.

He preparado un importante documento de introducción a xaWeb (40 páginas) xaWeb, que os animo a leerlo con detenimiento y en su totalidad. Son muchos conceptos nuevos, pero de verdad que no es complicado y merece la pena. No obstante, os adelanto las características esenciales de xaWeb:

  • Desarrollo de ejecutables tipo CGI para Windows y Linux (64 bits)
  • Independiente de Xailer: Se puede utilizar cualquier editor y no usa ninguna librería de Xailer
  • Soporte de paquetes de contexto como Materialize, que permite tener un buen diseño visual sin esfuerzo
  • Funcionamiento como servicio web
  • Gestión de sesiones
  • Sistema de depuración de código
  • Sincronización automática de datos entre CGI y HTML
  • Mínimos conocimientos necesarios de HTML, CSS y JavaScript para usarlo
  • Soporte de toda la potencia HTML, CSS y JavaScript si se tienen los conocimientos necesarios
  • xaWeb es un producto comercial de OZ Software
  • Se abre un periodo Beta al cual se puede apuntar cualquier usuario que lo desee

Con Xailer 9 publicamos una importante mejora en Xailer que permite crear ejecutables tipo CGI o consola para Linux 64 bits. Este era una paso previo necesario para intentar abordar el desarrollo de xaWeb, pues somos conscientes que el 99,99% de los servidores de Internet son Linux. Con motivo de la la inclusión de esta importante funcionalidad en Xailer, publicamos en nuestro WIKI dos artículos en los cuales explicábamos como instalar WSL (Windows Linux subsystem) y como instalar el servidor web de Apache. Para poder crear ejecutables para Linux desde el IDE de Xailer es absolutamente necesario que se instale WSL al menos (el primer paso). Aunque el segundo paso es más que recomendable.

Hace unos meses, dimos un paso más para la creación de páginas Web para Linux, con la publicación de un nuevo ‘plugin‘ de despliegue de archivos. Este ‘plugin’ permite que cualquier archivo que publiquemos en la carpeta ‘www‘ automáticamente se despliegue en WSL y en cualquier servidor web vía FTP. De la misma forma, si creamos un archivo CGI para Linux, el plugin también realiza el despliegue del mismo tanto en WSL como en un servidor FTP que usted elija.

Con Xailer 9 también es posible crear CGIs para Windows. De hecho, puede tener dos proyectos que apunten al mismo código fuentes, cada una para su plataforma en particular. La ventaja de los CGIs para Windows es que se pueden depurar y ejecutar desde el IDE. No obstante, creemos que finalmente nuestros CGIs correrán en máquinas Linux y por lo tanto, es importante que desde el primer día, sea capaz de crear CGIs para esa plataforma.

En breve estará disponible xaWeb; pero me temo que no va a ser un recompilar la aplicación y listo. Lo que si os podemos asegurar es que os encontraréis rápidamente en casa y que el camino para hacer software web se despeja completamente y el resultado final es espectacular.

Somos conscientes de que hay importantes aspectos que ahuyentan a muchos potenciales usuarios de xaWeb, como son:

  • Uso de servidores Linux
  • Instalación WSL para trabajar en local con Linux
  • Aprendizaje de HTML, JavaScript y CSS

Los pilares de xaWeb ya están terminados, pero es más que probable que haya que realizar modificaciones a nivel estructural que puedan afectar incluso a los ejemplos que ya están realizados. Hemos esperado a tener un CRUD completo funcional con archivos DBF para hacer este anuncio. En el siguiente enlace podéis ver algunos ejemplos de lo hecho hasta ahora corriendo bajo servidor Linux 64 bits. Con todos los ejemplos se incluye el código fuente en xaWeb para que le echéis un ojo y os animéis a usarlo cuando esté disponible.

xaWeb: All samples

Comentarios abiertos para conocer vuestras opiniones y sugerencias. Gracias por vuestro tiempo.

Un cordial saludo

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

Variable not found

Soporte para colecciones en parámetros `param` de .NET 9

octubre 15, 2024 06:05

.NET 9 apareciendo en el horizonte

Cada vez que llega una nueva versión del framework, todos estamos ansiosos por conocer las novedades, especialmente las más espectaculares. Sin embargo, a veces hay pequeñas mejoras que, sin ser revolucionarias, nos pueden resultar útiles en algunos escenarios.

El modificador params permite especificar que un método o función acepta un número variable de argumentos, como en el siguiente ejemplo, donde vemos una función Sum() que puede ser invocada con cualquier número de valores:

// Declaración de la función:
int Sum(params int[] values) 
{
    return values.Sum();
}

// Ejemplos de uso:
Console.WriteLine(Sum(1)); // Enviamos un único valor -> "1"
Console.WriteLine(Sum(1, 2, 3, 4, 5)); // Enviamos cinco valores -> "15"
Console.WriteLine(Sum()); // No enviamos elementos, se recibirá un array vacío -> "0"
Console.WriteLine(Sum([1, 2, 3])); // Aquí pasamos un array directamente -> "6"

Hasta ahora, el parámetro param sólo podía ser un array, lo que limitaba un poco su uso. Por ejemplo, no podríamos llamar a la función Sum() pasándole directamente un List<int> o un IEnumerable<int> sin convertirlos antes a array porque fallarían en tiempo de compilación, al no tratarse de un int[], que es el tipo del parámetro esperado.

¿Qué ha cambiado?

En .NET 9 se ha añadido soporte para otros tipos de colecciones, por lo que podemos hacer algo más flexible nuestro código. Por ejemplo, ahora podríamos declarar parámetros param con tipos como List<T>, HashSet<T>, Collection<T> o, en general, cualquier clase o estructura que implemente IEnumerable<T>:

// Declaración de la función:
int Sum(params IEnumerable<int> values)
{
    return values.Sum();
}

// Usos permitidos adicionalmente en .NET 9:
Console.WriteLine(Sum(new List<int> { 1, 2, 3 })); // -> "6"
Console.WriteLine(Sum(new HashSet<int> { 1, 2 })); // -> "3"
Console.WriteLine(Sum(new Collection<int> { 1, 2, 3, 4 })); // -> "10"
Console.WriteLine(Sum(GetNaturalNumbers(10))); // Podemos pasar cualquier IEnumerable<int> -> "55"

IEnumerable<int> GetNaturalNumbers(int count)
{
    for (int i = 1; i <= count; i++) yield return i;
}

Los parámetros param también soportan los tipos Span<T> y ReadOnlySpan<T>, por lo que también podríamos escribir código más eficiente cuando este usando estos tipos de datos de más bajo nivel:

Span<int> numbers = stackalloc int[] { 1, 2, 3 };
Console.WriteLine(Sum(numbers));
Console.WriteLine(Sum(1, 2, 3));

int Sum(params Span<int> values) 
{
    // Sumar de forma más eficiente, por ejemplo usando SIMD...
    ...
}

En definitiva, se trata de una mejora en el lenguaje que, sin ser espectacular, permite flexibilizar un poco nuestro código y optimizar algunos escenarios, así que bienvenida sea :)

Publicado en Variable not found.

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

Variable not found

Enlaces interesantes 581

octubre 14, 2024 11:43

Enlaces interesantes

Aquí tenemos la recopilación de enlaces de la semana. Entre ellos, me han llamado especialmente la atención los datos que muestra Trevor I. Lasn en su artículo sobre el factor edad en el mundo tecnológico, probablemente porque estoy en el 15% del que habla, los desarrolladores que vuelan ya por encima de los 45 tacos 😆

Y aparte, como siempre, un poco de ASP.NET Core, datos, IA, programación web y otros temas que espero que os resulten interesantes 🙂

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

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...

Picando Código

Después de varios años, arreglé un problema en mi instalación de KDE neon

octubre 14, 2024 10:00

Mi laptop Dell Precision 3530 ya tiene unos añitos arriba. Desde hace un buen tiempo vengo usando KDE neon en esta computadora. Es una distribución basada en Debian/Ubuntu que incluye el software más reciente de la comunidad KDE, prácticamente ni bien se publica. El manejo de paquetes y configuraciones me es familiar por mi experiencia con Debian y Ubuntu. Así que es como una continuación de lo que venía usando, pero aprovechando lo último del entorno de escritorio Plasma y todo lo que ofrece el framework KDE.

Buscando en mis correos de la época, veo que la laptop vino con Ubuntu 16.04 instalado (otra computadora comprada que no pagó una licencia a Microsoft 🙌). Estoy seguro que en ese momento cambié de distribución, pero no me acuerdo qué usé. Lo importante es que no poco después instalé KDE neon y me quedé con eso. Todo esto viene a que en alguna de las instalaciones “rompí” la partición de booteo. Me acuerdo tener problemas con UEFI, ¿o EFI? No sé, nunca me tomé el tiempo de aprender lo suficiente del tema como para saber de lo que estoy hablando.

Cuestión que cada vez que booteaba mi computadora, me tiraba a una consola de rescate de Grub. Con mucho ensayo y error terminé encontrando en internet cómo lograr bootear a mi sistema. Pero nunca me tomé el tiempo de arreglar el error de raíz: Había roto la partición de booteo. Por eso, para lograr ingresar al sistema operativo, tenía que ejecutar los siguientes comandos en esa consola de grub rescue cada vez:

set prefix=(hd0,gpt2)/boot/grub/
insmod normal
normal

Si llegaba a haber un dispositivo de almacenamiento USB conectado a la laptop, el 0 en hd0 podía variar a 1 u otro número. Esta lista de comandos está anotada en alguno de mis cuadernos o notas por ahí, pero a esta altura creo que voy a morir con ese conocimiento memorizado de la cantidad de veces que lo ejecuté. No resultaba una molestia tan grande, las computadoras con Linux pueden pasar meses o años sin reiniciar o apagarse, y a la vez era una capa extra de seguridad en caso de que alguien con acceso físico a mi laptop quisiera bootear el sistema 😅

Hace poco se publicó KDE Plasma 6.2 y el sistema me ofreció actualizarme a la última versión de la distribución. Actualicé e instalé todo, y tuve que reiniciar. En la familiar consola de grub, lancé los hechizos, pero no hubo caso. El sistema no booteaba…

Llegó el temido momento que en que tuve que enfrentar el problema y “aprender”. Pero no creo haber aprendido tanto… La manera en que lo resolví fue siguiendo las instrucciones de la instalación de KDE neon mismo. Por cierto, después de todos estos años siempre vuelvo a este post para asegurarme que estoy ejecutando bien el comando dd.

Ejecuté la aplicación boot repair desde la imagen Live de KDE neon que estaba usando para la instalación. No corrigió el problema, pero me advirtió que debía deshabilitar el modo BIOS-compatiblity/CSM/Legacy mode en mi firmware UEFI y bootear el live-USB en un modo de booteo compatible con UEFI. Hice eso en la configuración de mi BIOS (pero no sé si realmente era parte del problema).

Lo importante es que a pesar de haber roto la partición, en mi disco duro todavía quedaban unos 200mb en fat32 que en algún momento pertenecieron a dicha partición. Al editar manualmente las particiones para la instalación, el instalador me advirtió que tenía que aumentar el tamaño a 300mb. Por suerte la siguiente partición era root, por lo que pude eliminarla, cambiar los tamaños, y seguir con la instalación.

Particiones laptop Precision

Así que creé esta partición montada como /boot/efi y procedí con el resto. Todavía después de tantos años me asombro con el tema de mantener home en una partición aparte, y compartir mis archivos y configuraciones a través de distintas instalaciones de distribuciones.

Mi recuerdo de todo esto es que los problemas con EFI/UEFI eran algo relacionado a Secure Boot que complicaba la instalación de sistemas operativos alternativos cuando una computadora viene con Windows. Pero como dije, nunca aprendí mucho del tema. Estos días estoy mal acostumbrado a que la computadora simplemente funcione™ gracias a que Linux me simplifica la vida (en general).

Finalmente cuando prendo mi computadora, después de todos estos años, bootea directo a la pantalla de inicio de sesión y no tengo que tirarle unos encantamientos para que inicie. Es el cierre de una etapa, no sé si te voy a extrañar pantalla de rescate de grub, pero es algo con lo que conviví mucho tiempo de lo que temporalmente me puedo despedir.

El nuevo KDE neon funciona bien de bien y a pesar de tener todas las mismas configuraciones que venía usando en mi partición home, el sistema tiene ese olor a coche nuevo. Dejo la tradicional captura de pantalla, ¡guarden capturas de pantalla de sus computadoras! Son un buen viaje en el tiempo para el futuro:

KDE Neon - Plasma 6.2

El post Después de varios años, arreglé un problema en mi instalación de KDE neon fue publicado originalmente en Picando Código.

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

Variable not found

Creando GUIDs con orden natural en .NET 9

octubre 10, 2024 06:34

Imagen de una fábrica creando GUIDs

Probablemente, todos hemos usado en algún momento el método Guid.NewGuid() de .NET para generar identificadores únicos globales. Y muchos hemos sufrido con el problema que supone su (pseudo) aleatoriedad, principalmente cuando necesitamos ordenarlos... sobre todo si su destino final es acabar siendo el campo clave de una base de datos relacional.

Pero pocos éramos conscientes de que el método Guid.NewGuid() de .NET retorna un GUID versión 4, y que existen otras versiones de UUID (¡hasta 8!) que pueden resultar más beneficiosas en determinados escenarios.

En particular, los UUIDs versión 7 son generados (al menos teóricamente) siguiendo un orden natural, lo que permite almacenarlos de forma secuencial y recuperarlos en el mismo orden, gracias a que en su creación se usa un timestamp para proporcionar secuencialidad, combinado con valores aleatorios para aportar la unicidad propia de estos identificadores.

La cuestión es que .NET 9 ha añadido un nuevo método estático a la clase Guid que permite crear GUIDs versión 7: Guid.CreateVersion7(). Para que podáis ver la diferencia con el tradicional NewGuid(), vamos a generar algunos GUIDs con éste último:

Console.WriteLine("Creating v4 GUIDs:");
for (int i = 0; i < 10; i++)
{
    Console.WriteLine(Guid.NewGuid());
}
Creating v4 GUIDs:
96499bb0-6a32-43ed-9a10-fc197870a810
074c3c21-a6ef-4d5b-a66d-21167a6e8be0
9dad3441-0534-4351-823a-d60662728a18
a141fe8e-d6f9-40ae-9854-4748b8c0107f
a05565cc-fe02-433d-86f1-4c8c5a84c5e4
f2286470-445a-40d5-b7ab-b23fcfed6a1c
8b4a771a-7162-42b9-a475-ec1c473a6582
3162d279-144b-429f-b4c8-6be7735171e1
6942610d-c7b7-4366-943c-37d3e2ad369c
d29603a3-e3d8-45c4-b9a5-d2f8fe24c964

Como podréis observar, los identificadores son completamente aleatorios, sin orden aparente. Ahora, vamos a crear algunos GUIDs versión 7:

Console.WriteLine("Creating v7 GUIDs:");
for (int i = 0; i < 10; i++)
{
    Console.WriteLine(Guid.CreateVersion7());
}
Creating v7 GUIDs:
019219a9-516a-7c79-8106-0b8441f9ab43
019219a9-516b-7d02-9781-c77f25095756
019219a9-516b-7851-87fd-5bc6eb0ee404
019219a9-516b-7c0d-b335-0b4846e7e09e
019219a9-516b-7eee-82b2-012155dcac8f
019219a9-516b-7737-a1ff-7ffe53570d9d
019219a9-516b-738d-8699-c69ca9e7e944
019219a9-516b-7e69-84f9-c95c8c8981f3
019219a9-516b-76e9-ae3d-3fdde59ddad8
019219a9-516c-7394-bbac-a3828d3c5611

Fijaos en un detalle importante: aunque a primera vista parece que los valores están ordenados, si nos detenemos un poco veremos que hay algunos que no lo están. Esto es debido a que, según la especificación de la IETF, sólo se reservan para el timestamp los primeros 48 bits, rellenándose el resto con valores aleatorios. Y dado que se usa como referencia el Unix Epoch (milisegundos desde el 1 de enero de 1970), es posible que dos GUIDs generados en el mismo milisegundo no estén ordenados.

Esto podemos comprobarlo introduciendo una pequeña espera entre cada generación de GUIDs. Ahora obtendremos un resultado ordenado, porque aseguramos que cada uno de ellos se ha generado en un milisegundo distinto:

Console.WriteLine("Creating v7 GUIDs with delay:");
for (int i = 0; i < 10; i++)
{
    Thread.Sleep(1);
    Console.WriteLine(Guid.CreateVersion7());
}
Creating v7 GUIDs with delay:
0192381d-83ad-7548-b873-4dd00f737d99
0192381d-83bd-7a69-835e-af2f12ebdc83
0192381d-83cd-7b88-a4c3-b5972dde1aa4
0192381d-83dc-7fac-8afa-1ab485bd80cd
0192381d-83ec-7f0a-b236-b04fa35a40d5
0192381d-83fb-796a-8546-b6134d307f96
0192381d-840b-789d-9aa8-dcdf35598d6f
0192381d-841a-7a5f-b845-90eac2aad978
0192381d-8429-76a9-852d-717eb2965253
0192381d-8439-7d6f-a581-c452c19be749

Por tanto, debemos saber que CreateVersion7() no garantiza que los GUIDs generados estén ordenados, sobre todo:

  • Si estamos generando identificadores a un ritmo elevado (más de uno en cada milisegundo).
  • En escenarios con concurrencia, donde varios hilos podrían estar generando GUIDs en el mismo momento.
  • En sistemas distribuidos o escalados horizontalmente, donde varios servidores podrían estar generando GUIDs simultáneamente.

Pero bueno, si nuestro escenario es más básico, la inclusión de CreateVersion7() en .NET 9 al menos nos facilitará su uso.

Como punto extra, también es interesante saber que a la estructura Guid se le ha añadido la propiedad Version, que permite obtener la versión de un GUID:

var guid4 = Guid.NewGuid();
Console.WriteLine(guid4 + ", version: " + guid4.Version);

var guid7 = Guid.CreateVersion7();
Console.WriteLine(guid7 + ", version " + guid7.Version);
04fd0245-219e-4e3c-b15f-89da92d2bdba, version: 4
0192383b-8ef8-7a12-ab35-7d07905b6fcf, version 7

¡Espero que os sea de utilidad!

Publicado en Variable not found.

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

Variable not found

Enlaces interesantes 580

octubre 07, 2024 06:05

Enlaces interesantes

Una semana más, aquí tenéis los enlaces recopilados durante la semana pasada, con mucho protagonismo de los últimos lanzamientos de OpenAI que, si usáis sus APIs o planeáis hacerlo, seguro que os interesarán: la API realtime y el prompt caching

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

.NET MAUI / Cross-platform

Otros

Publicado en Variable not found.

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

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

Scrum master a tiempo completo: 42 Tareas

octubre 04, 2024 08:29

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...

Picando Código

Star Wars: A New Hope en concierto

septiembre 22, 2024 09:39

Star Wars: A New Hope en concierto en Usher Hall, Edimburgo

El pasado viernes 20 de setiembre de 2024, se realizó en el Usher Hall de la ciudad de Edimburgo el evento “Star Wars: A New Hope in concert”. En este evento la Orquesta Nacional de Escocia, conducida por Ben Palmer, ejecuta la música de John Williams en simultáneo con la película. ¡Fue una experiencia inolvidable!

Desde el momento que apareció el logo de 20th Century Fox y escuché la tan familiar percusión tocada en vivo, me recorrió una emoción enorme y se me erizaron todos los pelos de la nuca. Fue lo más parecido que puedo tener a la experiencia de mirar Star Wars por primera vez. Como he dicho antes, Star Wars: A New Hope debe ser la película que miré más veces en mi vida. Pero disfrutarla en un lugar como Usher Hall acompañada de estos músicos espectaculares tocando cada nota de la película, me voló la cabeza.

La música de John Williams es uno de los protagonistas principales de Star Wars. Y la Orquesta Nacional de Escocia la hace perfecta, no falta nada. El evento se hace relativamente seguido, recuerdo haber visto los afiches otros años y habérmelo perdido porque ya se habían vendido todos los asientos decentes. Pero ya estoy en la lista de distribución de noticias, así que soy de los que compran entradas temprano cuando aparece algo. También hacen eventos con otras películas y uno de videojuegos (al que tuve el gusto de asistir este año también), y música clásica, así que hay orquesta para rato. Ojalá tengan planeado hacer The Empire Strikes Back y The Return of the Jedi eventualmente ¡estoy ahí!

Durante la escena de Jabba y Han Solo en Tatooine, mi mente empezó a divagar. Como tantos nerds que miramos los documentales y leímos sobre los cambios que hizo Lucas en las ediciones especiales de 1997 sabemos: originalmente Jabba era un actor humano en una escena que no llegó al corte final. En las versiones nuevas se agregó a Jabba con gráficos en computadora, así como el tosco (desprolijo, horrible) efecto de Han pisándole la cola. Este efecto se ve bastante mal todavía. Así que pensaba si con los gigallones de dólares que tiene Disney, no sería hora de re-editar la trilogía original en versión “desespecializada”. O en el peor de los casos, una versión re-especializada donde corrije las cosas malas de la versión especializada original…

Existen versiones des-especializadas no oficiales creadas por la comunidad, si uno sabe dónde encontrarlas. Pero me parece que hay potencial para un boxset nuevo en Blu-Ray HD 4K Mega 64 sin las “mejoras” de 1997 (yo lo compro 🙋).

No tengo palabras para describir lo alucinante que fue el espectáculo, disfruté cada momento de la película como nunca antes la había disfrutado. Con la escena de la ceremonia final donde Leia le da las medallas a Han y Luke (¡spoiler!) la música va creciendo en fuerza hasta el punto más alto de impacto en la transición hacia los créditos. En este momento el público explotó en merecido aplauso y festejo. La mayoría de los asistentes nos quedamos hasta que terminaron los créditos, disfrutando las últimas notas de la noche y aplaudiendo a la orquesta por tal impresionante actuación.

El Usher Hall como ven en la foto es uno de esos teatros espectaculares diseñados con terrible acústica. Este año fue la primera vez que lo visité en otro evento de la Orquesta Nacional de Escocia, uno con música de videojuegos, y fue igualmente disfrutable (aunque ahí aprendí que es mejor sentarse en los asientos de los niveles altos para ver mejor los músicos). Si tienen la oportunidad de ver un evento de este tipo, lo recomiendo mucho. Por mi parte, quedo esperando más idas al Usher Hall a ver la Sinfónica. Ya veo que hay un evento de “La música de John Williams” en 2025…

El post Star Wars: A New Hope en concierto fue publicado originalmente en Picando Código.

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

Picando Código

Simular botón del medio en mouse 8bitdo N30 en Linux

septiembre 17, 2024 11:00

Desde hace un tiempo soy el feliz poseedor de un mouse N30 de 8BitDo, o “el mouse NES” como le digo yo. El mouse es un homenaje al Nintendo Entertainment System, y usa el mismo tipo de botones y paleta de colores. Sinceramente es más “lindo” que “cómodo”, pero al final del día es un mouse, y no uso tanto el ratón a la hora de programar (para cosas como juegos o diseño, más vale usar otro más ergonómico).

Cuenta con los dos botones tradicionales y la superficie entre medio sirve para hacer scroll, a pesar de no tener ninguna indicación visual. Es raro, pero hace scroll, y también podemos usar el d-pad a la izquierda pero el movimiento es un poco más “robótico”. Algo que extrañaba es el botón del medio del mouse, que uso mucho para cerrar pestañas, arrastrar la pantalla en GIMP, o abrir enlaces en pestaña nueva, entre otras interacciones. Por defecto, presionar los dos botones a la vez no simulaba el botón del medio en mi sistema, así que tuve que investigar el tema.

Mouse 8bitdo NES

Mouse 8bitdo NES – Picando Código recomienda lavarse las manos antes de tocar el mouse o controles después de haber comido golosinas…

Encontré que con la herramienta xinput podemos tanto detectar el mouse como cambiar las características habilitadas. Al correr xinput list en mi consola, obtengo la lista de dispositivos:

$ xinput list
xinput list
⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ DELL0820:00 044E:121F Mouse               id=11   [slave  pointer  (2)]
⎜   ↳ DELL0820:00 044E:121F Touchpad            id=12   [slave  pointer  (2)]
⎜   ↳ Keychron K8 Keychron K8                   id=19   [slave  pointer  (2)]
⎜   ↳ MOSART Semi. 2.4G Keyboard Mouse Consumer Control id=22   [slave  pointer  (2)]
⎜   ↳ MOSART Semi. 2.4G Keyboard Mouse          id=25   [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
   ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
   ↳ Power Button                              id=6    [slave  keyboard (3)]
   ↳ Video Bus                                 id=7    [slave  keyboard (3)]
   ↳ Video Bus                                 id=8    [slave  keyboard (3)]
   ↳ Power Button                              id=9    [slave  keyboard (3)]
   ↳ Sleep Button                              id=10   [slave  keyboard (3)]
   ↳ DELL0820:00 044E:121F UNKNOWN             id=13   [slave  keyboard (3)]
   ↳ Intel HID events                          id=14   [slave  keyboard (3)]
   ↳ Intel HID 5 button array                  id=15   [slave  keyboard (3)]
   ↳ Dell WMI hotkeys                          id=16   [slave  keyboard (3)]
   ↳ AT Translated Set 2 keyboard              id=17   [slave  keyboard (3)]
   ↳ Keychron K8 Keychron K8                   id=18   [slave  keyboard (3)]
   ↳ Keychron K8 Keychron K8                   id=20   [slave  keyboard (3)]
   ↳ MOSART Semi. 2.4G Keyboard Mouse System Control   id=21   [slave  keyboard (3)]
   ↳ MOSART Semi. 2.4G Keyboard Mouse Consumer Control id=23   [slave  keyboard (3)]
   ↳ MOSART Semi. 2.4G Keyboard Mouse          id=24   [slave  keyboard (3)]

Tiene pinta que es MOSART Semi. 2.4G Keyboard Mouse id=25. Pasándole el nombre a xinput, podemos ver qué propiedades tiene:

$ xinput list-props ‘pointer:MOSART Semi. 2.4G Keyboard Mouse’
Device ‘MOSART Semi. 2.4G Keyboard Mouse’:
       Device Enabled (215):   1
       Coordinate Transformation Matrix (217): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000
, 0.000000, 1.000000
       libinput Natural Scrolling Enabled (352):       0
       libinput Natural Scrolling Enabled Default (353):       0
       libinput Scroll Methods Available (354):        0, 0, 1
       libinput Scroll Method Enabled (355):   0, 0, 0
       libinput Scroll Method Enabled Default (356):   0, 0, 0
       libinput Button Scrolling Button (357): 2
       libinput Button Scrolling Button Default (358): 2
       libinput Button Scrolling Button Lock Enabled (359):    0
       libinput Button Scrolling Button Lock Enabled Default (360):    0
       libinput Middle Emulation Enabled (361):        1
       libinput Middle Emulation Enabled Default (362):        0
       libinput Accel Speed (363):     1.000000
       libinput Accel Speed Default (364):     0.000000
       libinput Accel Profiles Available (365):        1, 1
       libinput Accel Profile Enabled (366):   1, 0
       libinput Accel Profile Enabled Default (367):   1, 0
       libinput Left Handed Enabled (368):     0
       libinput Left Handed Enabled Default (369):     0
       libinput Send Events Modes Available (337):     1, 0
       libinput Send Events Mode Enabled (338):        0, 0
       libinput Send Events Mode Enabled Default (339):        0, 0
       Device Node (340):      “/dev/input/event20”
       Device Product ID (341):        1578, 16641
       libinput Drag Lock Buttons (370):       <no items>
       libinput Horizontal Scroll Enabled (371):       1
       libinput Scrolling Pixel Distance (372):        15
       libinput Scrolling Pixel Distance Default (373):        15
       libinput High Resolution Wheel Scroll Enabled (374):    1

La propiedad de interés es Middle Emulation Enabled, que tiene el valor 0. Para emular el botón del medio, cambio el valor a 1 con:

$ xinput set-prop ‘pointer:MOSART Semi. 2.4G Keyboard Mouse’ ‘libinput Middle Emulation Enabled’ 1

Ahora el tema es hacer que esto se ejecute automáticamente cada vez que inicio el sistema. En esta computadora estoy usando KDE Neon con KDE, así que me metí en las configuraciones del sistema, System > Autostart, y agregué una entrada manual. En “Program” o “Programa” ingresé xinput y en “Arguments” set-prop 'pointer:MOSART Semi. 2.4G Keyboard Mouse' 'libinput Middle Emulation Enabled' 1. Esto agrega un archivo .desktop a ~/.config/autostart y si el mouse está conectado al iniciar el sistema, todo va bien. Si conecto el mouse más tarde, puedo ejecutar el comando a mano desde ese mismo menú.

Y así quedó funcionando la emulación de botón del medio con los dos botones del mouse.

El post Simular botón del medio en mouse 8bitdo N30 en Linux fue publicado originalmente en Picando Código.

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

Una sinfonía en C#

Docker tricks, crear una imagen para poder depurar un error.

septiembre 10, 2024 12:00

“Introducción”

En este caso queremos crear una imagen pero nos da algún tipo de error, y es complicado de resolver. Bueno, lo que podemos hacer es apuntar los comandos que queremos ejecutar, crear una imagen con su base y hasta el punto que funciona y hacer que inicie con un comando que nos permita crear al contenedor e ingresar.

Crear imagen a partir de una con problemas

FROM node:20.12.0 AS builder
ARG environment=dev

WORKDIR /app
COPY ./package.json /app/
COPY ./yarn.lock /app/

RUN yarn
COPY . /app/
RUN yarn build:$environment

FROM nginx:1.21.5-alpine

EXPOSE 80/tcp
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]

y vemos que nos da un error al hacer RUN yarn

¿Qué podemos hacer?

Facil, creamos una imagen con la base que tenemos y hasta el punto que funciona, y luego la ejecutamos con un comando que nos permita ingresar al contenedor. Pero como comando de inicio, usamos tail -f /dev/null para que se quede esperando y no se cierre.

FROM node:20.12.0 AS builder
ARG environment=dev

WORKDIR /app
COPY ./package.json /app/
COPY ./yarn.lock /app/

CMD ["tail", "-f", "/dev/null"]

una vez hecho esto, podemos hacer un docker build -t myimage . y luego un docker run -it myimage /bin/bash para ingresar al contenedor y ver que es lo que pasa.

Desde dentro del container ejecutamos el comando que da problemas y vemos el error que nos da.

yarn

.....

Request failed \"401 Unauthorized\""

Y vemos que nos da un error al intentar restaurar los paquetes.

Nada más, una forma sencilla de ir depurando error por error dentro de un contenedor.

Agregamos una línea para copiar el archivo de configuración de npm y listo.

FROM node:20.12.0 AS builder
ARG environment=dev

WORKDIR /app
COPY ./package.json /app/
COPY ./yarn.lock /app/
COPY .npmrc /app/ # <-- Agregamos esta línea

RUN yarn
COPY . /app/
RUN yarn build:$environment

FROM nginx:1.21.5-alpine

EXPOSE 80/tcp
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /app/dist /usr/share/nginx/html
CMD ["nginx", "-g", "daemon off;"]

Nos leemos.

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

proyectos Ágiles

Master en Agile – MMA 2024-2025

septiembre 04, 2024 05:12

En octubre de 2024 se iniciará el Barcelona la 14ª edición del Postgrado en Métodos Ágiles (PMA) y otra del Máster en Transformación Agile (MMA) en La Salle (Universitat Ramon Llull), el primero a nivel mundial sobre Agile.

Con el Máster en Métodos Ágiles de La Salle-URL aprenderás a liderar el cambio hacia la Business Agility y a lanzar con éxito iniciativas en entornos complejos y altamente competitivos, reduciendo el Time To Market a fin de maximizar el valor aportado al negocio.

Desarrollarás una manera de pensar transversal e integradora para crear equipos de alto rendimiento mediante Scrum, Kanban, Lean Startup, OKR, diseño organizativo y liderazgo sistémico para elaborar estrategias de escalado Agile en la organización y transformar su cultura, de modo que también aumente la motivación de sus miembros.

Con profesores de primer nivel y visitas a empresas podrás iniciar un cambio hacia la agilidad y resiliencia empresarial en tiempos de incertidumbre.

Esta es una oportunidad única para aprender de profesionales-profesores de primer nivel, con muchos años de experiencia específica en Agile, aplicando principios y métodos ágiles en contextos diversos, especializándose en aspectos concretos,  investigando sobre nuevas técnicas, ponentes en conferencias nacionales e incluso internacionales, que incluso han inventado métodos y escrito libros.

Además, aprenderás a aplicar herramientas de inteligencia artificial para afrontar retos como abordar situaciones complejas, analizar grandes volúmenes de datos, crear agendas para workshops operativos y transformadores, o preparar product backlogs.

El MMA incluye las siguientes certificaciones oficiales:

  • «Certified Scrum Master» (CSM) de la Scrum Alliance, la entidad de certificación Agile de mayor prestigio a nivel internacional.
SAI_BadgeSizes_DigitalBadging_CSM
  • Certified Agile Skills – Scaling 1 de la Scrum Alliance, , la entidad de certificación Agile de mayor prestigio a nivel internacional.
  • Certified Leader de Agile Humans.

Adicionalmente, se incluye la visita a empresas singulares en aspectos concretos:

 ✍ Para inscripciones, consultar la página oficial del Máster.

A continuación, más detalle acerca del Postgrado en Agile (PMA) y del Máster en Agile (MMA)

PMA – Postgrado en métodos Ágiles

El PMA incluye las siguientes certificaciones oficiales:

  • «Certified Scrum Master» (CSM) de la Scrum Alliance.
  • Opción de acceder al Certified Project, Portfolio, And Operations Management for Business Agility de Businessmap.
AsignaturasTemasProfesores
Fundamentos & InceptionEquipos y Proyectos en entornos complejos.


Principios y métodos más conocidos (Scrum, Lean, Kanban y XP). Facilitadores e impedimentos.

Lanzamiento de Agile en un equipo.


Inception y conceptualización ágil de proyecto, priorización ágil, historias de usuario,  elaboración de Product Backlog, técnicas de priorización.

Xavier Albaladejo


Silvia Sistaré

Agustín Yagüe

Scrum y KanbanEstimación y planificación ágil, framework de Scrum, retrospectivas, Kanban, métricas ágiles, herramientas ágiles físicas, radiadores de información.Raul Herranz

 

Teodora Bozheva

Personas y equiposGestión de personas, gestión de conflictos, motivación e incentivos, facilitación compartida, contratación ágil.

 

Visual thinking.

Steven Wallace

 

Silvia Sistaré

Virginia Armas

Gestión de producto ágilDesign Thinking, Lean UX & Prototyping.

 Estrategia de Producto – Consciencia situacional (Wardley Maps), modelo de negocio (Lean Canvas), modelo de tracción, métricas AARRR.
Planificación y gestión estratégica – OKR y Hoshin Kanri.

Customer development – Lanzando y escalando startups ágiles, las tres fases de un producto.

Lean Startup – Desarrollo de producto basado en prototipos y experimentos. Bancos de ideas, desarrollo basado en hipótesis.

Juncal Guinea


Lucía Barroso
Ingeniería ágil User eXperience y prototipado en Agile.

 

ALM ágil, eXtreme Programing, Software Craftsmanship, testing ágil.

BDD y TDD. Desarrollo guiado por pruebas (de aceptación y unitarias).

Métricas Accelerate y SW Delivery assessment.

Cómo trabajar con código heredado y reducir la deuda técnica.

DevOps
Juncal Guinea

 

Cristina Verdi
Trabajo Final de PostgradoDurante el Postgrado se realiza un caso práctico de introducción de los contenidos en un equipo ágil en una empresa real. Para ellos los alumnos se organizan en equipos multidisciplinares utilizando Scrum, con feedback regular de un tutor con experiencia en transformación de equipos. 

El Postgrado tendrá una duración de 4 meses y se realizará viernes tarde y sábado por la mañana.

Ver también:

MMA – Master en Métodos Ágiles

Incluye todas las asignaturas del Postgrado (PMA) y, adicionalmente, las siguientes asignaturas especializadas en Business Agility, agilidad organizacional y transformación (aparte de las tres certificaciones indicadas al inicio y las visitas a empresas):

AsignaturasTemasProfesores
Enterprise Learning & personal efficiencyAgile Kaizen, Comunidades de Práctica, Open Spaces, Talent development, gamification.

 

Productividad y aprendizaje personal en Agile (eficiencia).
Steven Wallace


Esther Somoza
Lean Thinking & Agile ManagementLean. Escalado con Kanban.

 

Business Agility con ViMa – agilidad para equipos de negocio

Agile-Lean Management

Teodora Bozheva

  Xavier Quesada


Xavier Albaladejo

Coaching y CulturaCoaching de equipos, creación de equipos de alto rendimiento, liderazgo.

 

Tipos de cultura empresarial, transformación cultural.

Joserra Díaz

 

Jasmina Nikolic
Jaume Gurt

Transformación ContinuaEstrategia de despliegue de Agile en organizaciones, gestión del cambio, estructuras ágiles, cómo vender Agile a la Dirección. Contratos ágiles.

Enterprise continuous improvement.

Xavier Albaladejo

 

Ángel Medinilla
Scaling Agile Escalado (LESS, Spotify, Nexus, SAFe, Unfix), desescalado y auto-organización empresarial (reinventing organizations, sociocracy 3.0, liberating structures, …), equipos distribuidos.

 

Impact Mapping, Product Portfolio Management, Roadmapping, Budgeting for Agile

Adrian Perreau
Fernando Palomo

 

Mattijas Larsson

Trabajo Final de MásterDurante el Máster se realiza un caso práctico de introducción y aplicación de Agile en una empresa real, incluyendo la parte de transformación organizativa, de métodos y de cultura. Para ellos los alumnos se organizarán en equipos multidisciplinares utilizando Scrum, con feedback regular de un tutor con experiencia en transformación organizativa.Xènia Castelltort (oratoria / public speaking para poder explicar tus ideas de manera convincente)

El Máster tendrá una duración de 8 meses y se realizará viernes tarde y sábado por la mañana (incluye los estudios indicados en el Postgrado).

El cambio en la organización comienza por el propio cambio, para también poder dar ejemplo. Por ello en el MMA se realizan diferentes ejercicios de auto-conocimiento:

  • Cómo el alumno trabaja en equipo.
  • Estilo de liderazgo del alumno (según el paradigma Agile).

Como en las últimas ediciones, contaremos con la participación de empresas que nos explicarán sus experiencias de transformación y donde trabajan con modelos de gestión desescalados (basados en Sociocracia, NER y otras alternativas).

Información adicional

  • Perfil de los estudiantes: 30-45 años (no son recién licenciados, son personas con experiencia profesional).
  • Alrededor del 50% son mujeres.
  • 15% de los estudiantes ya no son del ámbito tecnológico, son pioneros-innovadores en otras industrias.
  • Alumnos de diferentes disciplinas – Product Owners, Scrum Masters, Agile Coaches, líderes de equipos, Project Managers, managers funcionales, ingenieros SW. Van a adquirir conocimientos de Agile “on-top” de todo eso (y a aprender unos de otros).
  • Lo que les caracteriza: todos son agentes de cambio en su contexto (equipo, área, empresa).
  • Sus 20 profesores (de reconocimiento internacional) son el MAYOR VALOR DIFERENCIAL del PMA y del MMA.

Testimoniales

Me ha permitido tener conocimientos sobre varios temas súper importantes dentro de la Transformación Digital. Me dio herramientas para crecer a Agile Coach y, además, para tener mejores conversaciones y discusiones con las empresas en donde he trabajado

Carolina Graffe

Estoy desplegando el TFM en mi empresa, Además, no estoy sola. Uno de mis compañeros del equipo ha sido contratado como consultor por mi empresa para darnos soporte. Así que no sólo estoy aplicando lo que yo aprendí, sino que el MMA me ha permitido ampliar mi círculo de contactos relevantes, que me permite seguir aprendiendo.

Susana Santillán

Estoy trabajando como agente del cambio y mis aportaciones son muy valoradas por mi jefe y compañeros. Por el feedback recibido, mis aportaciones están muy por encima de lo esperado para mi rol.

Robert Avellaneda

Tengo mucho más contexto y más herramientas para el día a día. Incluso a nivel personal también me está ayudando mucho

María Hachero

Además de los conocimientos concretos que se reciben, uno de los principales cambios que han experimentado los alumnos es mayor perspectiva en los problemas, cómo abordar la complejidad en las empresas, en su trabajo y en las relaciones entre personas y en equipos. Han ganado discurso y aplomo para defender de manera más objetiva propuestas de cambio y mejora.

Encuesta a alumnos de las ediciones anteriores:

(*) Las personas que han valorado el impacto como «neutro o poco» usualmente son perfiles muy especializados en contextos muy estáticos, con lo cual les es difícil cambiar de «profesión» e introducir cambios en sus organizaciones (aunque algunos de ellos incluso dan conferencias sobre cómo van avanzando en esos contextos tan singulares).

 ✍ Para más detalles e inscripciones, consultar la página oficial del Máster.

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

Blog Bitix

Desempaquetado del ratón inalámbrico Logitech Signature M750

julio 23, 2024 09:00

Tras probar un ratón inalámbrico de los baratos pasado un tiempo me quedé con muy malas impresiones por la perdida de conectividad principalmente que era muy molesta. Pasé a un ratón con cable más fiable y tras 5 años el botón derecho me ha empezado a fallar y reconocer el clic aleatoriamente. Tras estar usando un Apple Magic Mouse que generalmente me ha funcionado bien en cuanto a conectividad he vuelto a darle una nueva oportunidad a un ratón inalámbrico pero ya de más calidad, finalmente he elegido el Logitech Signature M750. En el artículo hago un análisis del ratón y mis primeras impresiones.

Continuar leyendo en Blog Bitix

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

Header Files

La trampa al usar semántica de movimiento con std::string

julio 16, 2024 10:00

La trampa al usar semántica de movimiento con std::string

La semántica de movimiento de std::string puede ser complicada y, a menos que tengamos información previa sobre los tamaños esperados de las cadenas, puede tener el efecto contrario y hacer que el código sea más lento. La razón detrás de esto es la optimización de cadenas pequeñas (SSO, por sus siglas en inglés). que consiste, en resumidas cuentas, en tratar al objeto como si fuera una unión, de forma que si la cadena es más corta que un tamaño dado, se almacena en el mismo bloque de memoria del objeto en lugar de asignar memoria dinámica. Cuando la cadena supera ese tamaño, la cadena se almacena en un bloque diferente.

¿Qué es la Optimización de Cadenas Pequeñas (SSO)?

La SSO es una técnica utilizada en la implementación de std::string para optimizar el uso de memoria y el rendimiento. En lugar de asignar memoria dinámica para todas las cadenas, la SSO almacena cadenas pequeñas directamente en el objeto std::string (como si de una unión se tratase). Se puede ver la SSO en acción en este ejemplo.

Esta técnica evita la sobrecarga de la asignación de memoria dinámica, que puede ser costosa en términos de tiempo y recursos. Sin embargo, esta optimización introduce algunas consideraciones importantes al mover objetos std::string.

Nota: La SSO no es parte del estándar de C++ sino más bien una optimización de algunos compiladores. Igualmente, el tamaño máximo para considerar una cadena como pequeña no tiene que ser el mismo en todas las implementaciones ni plataformas.

El constructor de movimiento de std::string

Al mover cualquier objeto en C++, estamos dando la posibilida de realizar una copia optimizada. La eficiencia aumenta cuando tenemos recursos externos que podemos intercambiar, como un puntero a un bloque de memoria o un handle de fichero. Sin embargo, para el resto de datos, aún tenemos que copiar datos. Si la cadena es pequeña y la SSO está en acción, no hay ningún puntero que intercambiar y todavía estamos copiando los datos base de std::string.

De hecho, al mover, tenemos que garantizar que el objeto original se mantenga en un estado válido, lo cual normalmente se hace estableciendo algunos valores por defecto. En la práctica, esto significa que estamos copiando una vez y asignando una vez, duplicando la cantidad de operaciones en comparación con una copia normal. Por lo tanto, si nuestras cadenas se espera que siempre (o la mayoría del tiempo) sean más cortas que el límite de SSO, entonces un movimiento perjudicaría el rendimiento.

Comparación de Copia vs Movimiento

Para ilustrar mejor este punto, se puede comparar el rendimiento de la copia y el movimiento para cadenas pequeñas, grandes y una mezcla de ambas. El siguiente ejemplo permite visualizar las diferencias entre ellas. En este benchmark, se estableció un tamaño de 32 caracteres para tener aproximadamente un 50% de cadenas pequeñas y un 50% de cadenas grandes. Los resultados muestran cómo el movimiento de cadenas pequeñas puede ser menos eficiente que una simple copia debido a la SSO.

Benchmark std::string

Conclusión

En resumen, la semántica de movimiento de std::string no siempre es la mejor opción, especialmente cuando se trata de cadenas cortas que se benefician de la SSO. Es crucial considerar el tamaño esperado de las cadenas al decidir entre copiar o mover std::string. Esta decisión puede tener un impacto significativo en el rendimiento de nuestra aplicación.

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

info.xailer.com

Plugin de despliegue de archivos

junio 11, 2024 11:35

Os presento un nuevo plugin que puede ser muy útil para todos aquellos que os dedicáis a generar ejecutables tipo CGI que luego subís a un servidor web o cualquier otro tipo de archivo que querías desplegar un vuestros servidores de forma rápida.

Su funcionamiento es muy sencillo: el plugin detecta cuando se realiza una compilación y enlazado correcto de un archivo CGI y lo sube a Internet utilizando los servicios de CURL. En Xailer 9 existe una carpeta especial para los proyectos tipo Web de nombre ‘www’. Cuando el plugin detecta que se ha realizado un salvado de algún archivo en esa carpeta, hace automáticamente el despliegue.

Es más que probable que no queramos que esté realizando el despliegue constantemente, por lo que se ha incluido una opción de menú para activarlo o desactivarlo.

Este plugin es capar de realizar un despliegue múltiple si detecta que estamos utilizando WSL para la generación de los archivos CGI para el entorno Linux (nueva función de Xailer 9). En dicho caso no sólo despliega en nuestro servidor en Internet, sino que también despliega en WSL

Este sería un ejemplo de despliegue:

Su configuración es bastante sencilla. Tan sólo hay que indicar las direcciones URL donde queremos que despliegue y nuestras credenciales.

Estas son la propiedades que hay que configurar y viendo su nombre espero que se auto-expliquen, así mismas:

  • URL donde se despliegan los archivos tipo CGI
  • URL donde se despliegan el resto de archivos
  • Path donde se copian el resto de archivos en entornos WSL
  • Extensión de archivos CGI que se reconocen
  • Directorio donde se ubicarán los archivos JavaScript
  • Directorio donde se ubicarán los archivos CSS
  • Directorio donde se ubicarán el resto de archivos
  • Nombre de usuario de la conexión FTP
  • Contraseña de la conexión FTP

El plugin es susceptible de importantes mejoras. Como por ejemplo, poder establecer distintas URL y credenciales dependiendo del proyecto. Hemos decidido no incluir esa funcionalidad porque cada usuario tendrá su propia preferencia. No obstante, si alguien se anima a hacerlo, encantado de echarle una mano para cualquier duda que pueda tener.

Os adelanto que sólo funciona con Xailer 9 ya que se apoya en alguna función que no existe más que en Xailer 9.

Podéis descargar el plugin de este enlace.

Un saludo y hasta pronto

Ignacio Ortiz de Zúñiga
[Equipo de Xailer]

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

Juanjo Navarro

Nueva edición del Technology Radar (la 30)

mayo 21, 2024 06:31

Si no conoces el Technology Radar de la empresa Thoughtworks, deberías echarle un vistazo.

Se trata de un informe semestral donde se analizan una serie de puntos (“blips” los llaman) sobre el mundo del desarrollo de proyectos tecnológicos.

Estos blips se dividen en cuatro tipos:

  • Técnicas
  • Herramientas
  • Plataformas
  • Lenguajes & Frameworks

Para cada blip te aconsejan:

  • Adoptar
  • Probar
  • Evaluar – mantenerse al tanto y jugar un poco con él para conocerlo.
  • Resistir – mejor no usarlo, es dudoso su futuro o utilidad.

Esta última edición (la 30) está llena de IA y devops, cómo no. Yo me suelo fijar en temas prácticos (en Herramientas o en Lenguajes y Frameworks, sobre todo).

Aquí os dejo lo que más me ha llamado la atención (y he probado más o menos) de la última edición:

  • Pop – Herramienta para compartir la pantalla para hacer Pair Programming.
  • Aider – Una IA que hace de “coworker” de programación y me ha parecido muy bien pensado.
  • Continue – Un “Github Copilot” opensource en el que puedes elegir qué LLM utilizar (con el consiguiente coste por el uso del API si es de pago, claro). Puedes también utilizar un LLM local corriendo en tu infraestructura.
  • Dify – Un creador “gráfico” de aplicaciones “LLM” bastante impresionante. Permite diseñar un “flujo” de trabajo, donde vas haciendo consultas a distintos modelos IA, unir la información, hacer otras llamadas dependiendo de la respuesta anterior, etc. Además tiene integrado un sistema RAG con lo que le puedes subir documentos que la IA utilizará como referencia.
  • Crabviz – Utilidad para VSCode que genera un gráfico de llamadas entre clases.
  • Electric – Librería y framework que permite crear aplicaciones móviles o webapps con una base de datos “local” (que se ejecuta en el propio móvil o la página) y que automáticamente se sincroniza con un PostgreSQL en el back.
  • LiteLLM – Algo así como un “proxy” LLM. Permite configurar distintos LLM y acceder a ellos con un API común.

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

Una sinfonía en C#

Configurar Docker + HTTPS + nginx

mayo 21, 2024 12:00

“Introducción”

Cuando queremos probar algo en local (una aplicación web), dentro de un contenedor, no podemos utilizar https como desde Visual Studio o IIS. Si necesitamos sí o sí https, debemos configurar algunas cosas, como por ejemplo, un certificado autofirmado, nginx, etc. En este post vamos a detaler cómo hacerlo.

Pasos

Vamos a necesitar hacer un par de cosas, voy a detallar los pasos a seguir en una PC con Windows y una aplicación .NET Core, es que lo que yo uso.

Básicamente pondremos nuestra aplicación en un contenedor, configuraremos nginx para que haga de proxy y que además tenga https. Luego un docker compose que levante todo.

Crear certificado autofirmado

Para crear certificados autofirmados, podemos utilizar openssl. En Windows, podemos instalarlo desde aquí.

y ejecutar este comando:

localhost.conf

[req]
default_bits       = 2048
default_keyfile    = localhost.key
distinguished_name = req_distinguished_name
req_extensions     = req_ext
x509_extensions    = v3_ca

[req_distinguished_name]
countryName                 = Country Name (2 letter code)
countryName_default         = US
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = Texas
localityName                = Locality Name (eg, city)
localityName_default        = Dallas
organizationName            = Organization Name (eg, company)
organizationName_default    = localhost
organizationalUnitName      = organizationalunit
organizationalUnitName_default = Development
commonName                  = Common Name (e.g. server FQDN or YOUR name)
commonName_default          = localhost
commonName_max              = 64

[req_ext]
subjectAltName = @alt_names

[v3_ca]
subjectAltName = @alt_names

[alt_names]
DNS.1   = localhost
DNS.2   = 127.0.0.1
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout localhost.key -out localhost.crt -config localhost.conf -passin pass:12345678

Esto creará dos archivos, localhost.crt y localhost.key, estos archivos los usuaremos en nginx.

Ahora necesitamos registrar el certificado como confiable ya que es auto-firmado. (es decir, registrar en Windows como confiable)

En el Administrador de Certificados (certmgr.msc), puedes encontrar esta ubicación siguiendo estos pasos:

Abrimos el Administrador de Certificados.

  • Para esto escribimos certmgr.msc en el diálogo Ejecutar (Win + R).
  • En el Administrador de Certificados, expande el árbol de Certificados “Usuario Actual” en el panel izquierdo.
  • Debajo de esto, expande la carpeta Autoridades de Certificación Raíz Confiables.

Hacemos clic en la carpeta Certificados bajo Autoridades de Certificación Raíz Confiables.

Esta es la ubicación equivalente a Cert:\CurrentUser\Root en PowerShell.

Luego

En el Administrador de Certificados (certlm.msc, Certificate Manager for local machine), puedes encontrar esta ubicación siguiendo estos pasos:

  • Abre el Administrador de Certificados para la Máquina Local. Puedes hacer esto escribiendo certlm.msc en el diálogo Ejecutar (Win + R).
  • En el Administrador de Certificados, expande el árbol Certificados (Computadora Local) en el panel izquierdo.
  • Debajo de esto, expande la carpeta Personal.
  • Haz clic en la carpeta Certificados bajo Personal.

Ahora nginx usará los archivos de certificado y clave para servir https. Y deberías estar bien.

Configurar nginx

Para esto simplemente vamos a crear un archivo de configuración para nginx, que será el siguiente:

nginx.conf

worker_processes 1;

events { worker_connections 1024; }

http {

    sendfile on;

    upstream web-api {
        server api:80;
    }

    server {
        listen 80;
        server_name localhost;

        location / {
            return 301 https://$host$request_uri;
        }
    }

    server {
        listen 443 ssl;
        server_name localhost;

        ssl_certificate /etc/ssl/certs/localhost.crt;
        ssl_certificate_key /etc/ssl/private/localhost.key;

        location / {
            proxy_pass         http://web-api;
            proxy_redirect     off;
            proxy_http_version 1.1;
            proxy_cache_bypass $http_upgrade;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection keep-alive;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Proto $scheme;
            proxy_set_header   X-Forwarded-Host $server_name;
        }
    }
}

Le decimos a nginx que utilice el certificado y la clave que creamos antes, y que escuche en el puerto 443. y con el proxy_pass le decimos que redirija las peticiones al servicio que escucha en el puerto 80. (más adelante ese será el nombre del servicio en el docker compose)

Ahora creamos el Dockerfile para nginx:

FROM nginx:alpine

COPY ./nginx.conf /etc/nginx/nginx.conf
COPY localhost.crt /etc/ssl/certs/localhost.crt
COPY localhost.key /etc/ssl/private/localhost.key

CMD ["nginx", "-g", "daemon off;"]

Básicamente copiamos el archivo de configuración y los archivos de certificado y clave al contenedor.

Configurar nuestra app

En este caso una simple aplicación .NET Core, que escucha en el puerto 80.

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

COPY *.csproj ./
RUN dotnet restore

COPY . ./
RUN dotnet publish -c Release -o out

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app

ENV ASPNETCORE_HTTP_PORTS 80

EXPOSE 80
EXPOSE 443

COPY --from=build /app/out ./

CMD ["dotnet", "app.dll"]

Docker compose

version: "3.7"

services:

reverseproxy:
    build:
      context: ./nginx
      dockerfile: Dockerfile.nginx
    ports:
      - "8080:80"
      - "1443:443"
    restart: always

api:
    depends_on:
      - reverseproxy
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8088:80"
    restart: always

Simplemente apuntamos los dos servicios a sus Dockerfiles, y abrimos el puerto 1443 para https.

Si vemos algún error en el navegador relacionado con https lo más probable es que no hayamos registrado el certificado como confiable.

Dejo por acá un repositorio con el código

Nos leemos.

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

Arragonán

El lado estratégico de Domain-Driven Design. CommitConf 2024

mayo 08, 2024 12:00

Hace unas semanas estuve en Commit Conf en Madrid, evento al que no iba desde hace mucho. Estuve compartiendo la charla El lado estratégico de Domain-Driven Design, iterando ligeramente la que hice hace unos meses en La Vertical, a su vez basada en una charla más larga (y espesa) que he impartido in-company en varias ocasiones.

Foto de la sala de conferencias del track 1 del evento

En los últimos años ha crecido el interés y la adopción de Domain-Driven Design en la comunidad de desarrollo de software. Ahora es bastante habitual oír hablar del lado táctico de DDD, la mayoría de las veces acompañado del uso de ports & adapters (aka Hexagonal Architecture). Pero, al menos en castellano, no he visto hablar apenas de DDD estratégico y lo que nos puede aportar a nivel de Sociotechnical Architecture.

Así que de ahí vino buena parte de mi motivación de proponer repetirla en un evento mucho más masivo como es la Commit Conf.

La presentación está dividida en 4 bloques:

  • Introducción a DDD y específicamente a la parte estratégica
  • Resumen de las actividades estratégicas basado en el Domain-Driven Design Starter Modelling Process de DDD Crew
  • Un ejemplo práctico de DDD estratégico basado en un caso real, mostrando su división y conexión entre dominios visibilizándolo con un Context Map un tanto enriquecido con su clasificación desde diferentes puntos de vista
  • Otras consideraciones a tener a nivel de la organización de equipos

Aquí os dejo el vídeo de la charla

Y el genially que usé para la presentación

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

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

CAS2017: Conferencias Agile-Spain

abril 11, 2024 08:24

La CAS2017 ha sucedido hace un par de días, y empiezo a leer las primeras impresiones, felicitaciones, quejas, enhorabuenas y protestas... Mi visión sobre la CAS2017 &nbsp;¿Qué ha sucedido este año? Desde mi punto de vista personal, no puedo dar muchos detalles del contenido. ¡He visto muy pocas charlas! :) La CAS tiene cada vez para mi más de punto de encuentro que de conferencia dónde

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

Arragonán

Reduciendo riesgos con tests de carga

abril 04, 2024 12:00

Hace varias semanas estuve involucrado en realizar algunos tests de carga en Genially, algo que no había tenido necesidad de hacer desde que trabajé en Inditex lanzando un nuevo servicio interno.

Esto venía dado por unos cambios en los que estuvimos trabajando un par de equipos para mejorar la experiencia de uso de una parte del producto, lo cual implicó un cambio bastante importante a nivel de arquitectura.

Con estos cambios teníamos 2 riesgos:

  • Que aunque la experiencia de uso de la funcionalidad mejorase esto pudiera impactar negativamente en un funnel de conversión.
  • Que la nueva solución que habíamos implementado pudiera causar problemas dependiendo de la carga y tuviéramos incidencias.

El primer riesgo lo minimizamos realizando un rollout incremental, que es como lanzamos la mayoría de cambios relevantes en Genially. Esto, en este caso, significó lanzar los cambios internamente bajo una feature flag para obtener feedback cualitativo y luego abrirlo a un porcentaje del tráfico para observar las métricas de producto.

El segundo riesgo, como mencionaba al principio, lo minimizamos realizando algunos tests de carga.

¿Pero qué es un test de carga?

Es un tipo de prueba en la que se genera tráfico de forma artificial para evaluar la respuesta o capacidad de un sistema ante una carga determinada de trabajo o de personas usuarias, por lo que puede servir para comprobar tanto el rendimiento como el escalado de un sistema.

Para esto, antes de ejecutar la prueba, necesitamos tener definido previamente qué y cómo lo vamos a observar para poder consultarlo tras su ejecución (tiempos de respuesta, consumo de recursos, etc). Así que el entorno sobre el que vayamos a probar tiene que ser observable; en este caso, lo que más nos va a interesar son las métricas y, en caso de que empiece a degradarse el servicio, también las trazas pueden ayudar a identificar el origen del problema con mayor facilidad.

En ocasiones, este tipo de pruebas se tienden a hacer con personas reales de manera algo informal, en plan “entrad aquí X personas a hacer Y metiéndole caña y vamos a ver cómo van las métricas Z”. Eso puede ser perfectamente válido para tener una idea general de cómo responde el sistema con una carga un tanto aleatoria, pero tiene el problema de que no es repetible ni controlado, por lo que de ese modo no podemos dar seguimiento a los resultados obtenidos de forma consistente.

Para tener consistencia en este tipo de pruebas, hay herramientas que nos permiten automatizarlas, de ese modo obtenemos escenarios controlados y repetibles a los que sí podemos dar seguimiento. Con estas herramientas, podremos definir distintos escenarios en los que queremos probar el sistema y observar si se mejora o empeora comparando los resultados de antes y después de un cambio.

En cuanto a herramientas concretas, en el pasado usé Apache HTTP Server Benchmarking Tool y JMeter, pero en la última ocasión lo hice con k6 por recomendación de mi compañero Manu Franco. La verdad es que me pareció una herramienta fácil de empezar a usar, y viendo su documentación también muy potente, así que de momento se ha convertido en mi preferencia.

Tipos de tests de carga

Dentro de los tests de carga, se pueden clasificar en subtipologías dependiendo del objetivo de la prueba y del patrón de generación de tráfico utilizado. Me gusta mucho la gráfica y la explicación de la propia documentación de k6.

Esquema representando los distintos tipos de tests

  • Smoke tests: son pruebas sobre el sistema de corta duración (segundos o pocos minutos) con una carga baja, con el objetivo de comprobar que todo funciona razonablemente bien sin consumir muchos recursos. De primeras, no los hubiera incluido como test de carga, pero dada la aproximación de esta herramienta de generar tráfico concurrente, les compro el incluirlo. En este caso, se podrían lanzar de forma bastante recurrente para detectar errores de configuración a nivel de aplicación o anomalías en las métricas de forma temprana.
  • Average-load test: son pruebas sobre el sistema de duración media (minutos-hora) con una carga similar a la habitual, con el objetivo de asegurar que los cambios introducidos no impactan negativamente en el contexto habitual del sistema. Esto podría hacerse de forma periódica para encontrar potenciales problemas que se hayan podido introducir.
  • Stress test: son pruebas sobre el sistema de duración media (minutos-hora) con una carga por encima de la habitual, con el objetivo de comprobar el comportamiento del sistema con un tráfico bastante superior al habitual. Esto nos puede ser útil, por ejemplo, para prepararnos para campañas como navidad o rebajas en el mundo del comercio electrónico.
  • Spike test: de duración corta (unos pocos minutos) con una carga que sobrepase mucho la habitual del sistema. Su objetivo es ver cómo se comporta con un pico de tráfico masivo durante un tiempo más limitado. Escenarios para los que esto puede ser útil pueden ser prepararse para las primeras horas del Black Friday, si se va a lanzar un anuncio en prime time en televisión, etc.
  • Breakpoint test: de duración indeterminada y una carga incremental hasta llegar a que el sistema se rompa o llegue al límite que hayamos definido. En este caso, el objetivo es llevar el sistema al extremo máximo para conocer en qué momento nuestro sistema no da más de sí o hasta dónde permitimos escalarlo si la infraestructura del sistema puede ir hacia “infinito”. Los escenarios podrían ser comprobar optimizaciones de partes del sistema o trabajar en un plan de contingencia si en algún momento el sistema se acerca a su límite.
  • Soak tests: de larga duración (varias horas) y una carga similar a la habitual. Su objetivo es detectar problemas surgidos a partir de un uso extendido del sistema, como el aumento del consumo de infraestructura o la degradación de los tiempos de respuesta. Esto nos puede interesar especialmente cuando no somos los dueños de la infraestructura en la que corre nuestro sistema y queramos comprobar que quienes lo vayan a operar no se encuentren sorpresas posteriormente.

¿Cómo lanzar los tests de carga?

En un mundo ideal lo probaríamos en algún entorno aislado que se asemeje mucho a producción a nivel de infraestructura, pero no siempre podremos contar con esa posibilidad. Y la frencuencia de ejecución dependerá de cada contexto.

Por ejemplo, cuando trabajaba en Inditex, disponíamos de un entorno específico para este tipo de pruebas. Y dado que no era posible realizar llamadas entre entornos distintos debido a que estaba limitado a nivel de red, sabíamos que podíamos probar nuestros servicios de forma aislada sin necesidad de coordinarnos con equipos no involucrados en estas pruebas.

Por otro lado, para llevar a cabo pruebas preliminares del cambio de arquitectura al que me refería en Genially, las estuvimos realizando en un entorno efímero. A nivel de infraestructura, estos entornos efímeros son bastante limitados en comparación con el de producción, pero nos permitía realizar algunas validaciones en un entorno aislado también sin necesidad de coordinación. Utilizamos este entorno para ejecutar una serie de smoke tests y un mini average-load test para obtener las métricas base. Luego introdujimos los cambios relevantes y comprobamos si surgía alguna anomalía para ver si había que iterar algo, una vez visto que no había nada raro podíamos ir a producción con mayor confianza y darle seguimiento al uso real de las primeras horas.

En los casos que describo lanzábamos las pruebas de forma manual y luego analizábamos los resultados. Pero también existen contextos donde estas pruebas se lanzan automáticamente incluso en pipelines de continuous delivery. Así que se puede echar para atrás una release si un test falla dado el límite marcado como aceptable en una métrica. Por ejemplo si dada una carga se supera el máximo de latencia de peticiones, no se consigue ingestar un mínimo de peticiones por segundo, etc.

Concluyendo

Hay lugares donde este tipo de pruebas son muy relevantes por su contexto y forman parte del camino de entrega del software. En mi caso no han formado nunca parte de mi flujo habitual de trabajo, pero han habido ocasiones en las que me han resultado muy útiles para lanzar nuevos servicios, nuevas funcionalidades o para introducir cambios relevantes en la arquitectura con una mayor confianza.

Aunque nunca hay que olvidar que, como cualquier prueba automática, estas pruebas pueden ayudar a minimizar el riesgo pero no garantizan la ausencia total de problemas de degradación o errores. Ya que el tráfico artificial nunca será igual al generado a partir del comportamiento real de las personas que utilizan nuestro software, así que es importante invertir primero en observabilidad y en comprender cómo se comportan nuestros sistemas de software en producción.

» 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