Weblogs Código

Picando Código

El Retorno del videocasete del Regreso del Jedi 📼

agosto 16, 2022 01:00

Cuando era (más) joven, mi padre me trajo de regalo de un viaje la Edición Especial de la Trilogía de Star Wars. Perdí la cuenta de la cantidad de veces que miré estas películas en este formato. Star Wars: A New Hope debe ser la película que miré más veces en mi vida. No al punto de recordar cada escena y diálogo (me parece que eso es por daños en mi memoria después de tanto tiempo de abusar de mi cerebro), pero sí al punto de poder citar varios diálogos a medida que van pasando. También había mirado el documental o los programas especiales sobre los cambios de las ediciones especiales. Así que en varias escenas identificaba “esto cambió de la edición original” (ediciones que también había mirado en VHS en su momento).

El Retorno del videocasete del Regreso del Jedi

Un día nos juntamos con varios amigos a hacer la tradicional Maratón de Star Wars. Si no me acuerdo mal, esto fue por la época del estreno de Episodio II en los cines. La excusa para juntarse era refrescar la memoria antes de ir a ver la película nueva de Star Wars. Nos reunimos con un reproductor de video, golosinas, la trilogía que tenía en VHS y alquilábamos del video club Episodio I. Miramos las películas en orden “episódico”, no cronológico, así que empezamos por Ep I – La Amenaza Fantasma. Durante estas juntadas teníamos algún que otro recreo entre (o durante) las películas para jugar videojuegos, comer porquerías y demás. Parte de la gracia era pasar la noche sin dormir mirando películas. De estas juntadas salieron un par de chistes internos y referencias a las películas que siguieron surgiendo en el grupo durante años.

Sumando las horas de películas mas extras, llegábamos a la mañana siguiente terminando El Retorno del Jedi. Una de las veces que hicimos la maratón, alguien dejó por accidente la caja de uno de los videocasetes encima de la ventilación del videograbador. En el momento no nos dimos cuenta y nos pusimos a mirar la película. Cerca del final, la película paró abruptamente, y el equipo hizo un ruido raro. Cuando fuimos a mirar, el calor del videograbador (después de varias horas en funcionamiento) mas la ventilación tapada hizo que se derritiera la cinta del videocasete, cortándose. En el momento me sentí súper frustrado y enojado. Había perdido una de las películas que tanto me gustaba mirar.

Es de esas cosas que al pasar el tiempo uno se olvida y no tiene tanta importancia. Al principio cada tanto me acordaba y me molestaba un poco. En esa época me parecía inalcanzable comprar el videocasete en particular o toda la trilogía nueva, eran otros tiempos… Por eso me angustiaba un poco el hecho de haber perdido la tercera película. No me acuerdo cuántas veces volví a mirar A New Hope y Empire Strikes Back con esos videocasetes después de ese incidente. Más adelante ya empecé a mirar las películas cuando las daban en el cable y después se vino la época del DVD. La saga se fue extendiendo con las precuelas y más.

Pasaron años, y la caja con la colección de las tres películas edición especial de Star Wars quedó en la casa de mi madre en Maldonado. Yo me mudó a Montevideo y más adelante a Escocia. Pero las últimas veces que fui de visita a la casa de mi madre, la caja se encontraba adornando un rinconcito “nerd” del cuarto. El cuarto en el que solíamos dormir con mis hermanas cuando éramos niños y cada tanto volví a usar para dormir estando de visita. Creo que mi madre lo adornó así de gusto para que me sintiera más a gusto.

Hace pocos días alguien dejó abandonado un televisor al lado de un contenedor de basura en mi calle acá en Edimburgo. Por éstos lados se acostumbra dejar cosas afuera ya sea para tirar o para que alguien que le pueda dar uso se lo quede. No es la primera vez que veo un televisor al lado de un contenedor de basura en mi barrio. Es de esas cosas que no me resultaban comunes viviendo en Uruguay, capaz que por eso siempre me da algo de vergüenza levantar algo de la calle.

Pero esta vez me animé, en parte gracias al aliento de mi primo y el Oye (😁). En la tarde me acerqué a mirarla y pude ver que estaba en buen estado. Esperé a que se hiciera de noche, y salí a buscarla. La traje a casa, la desinfecté toda, y noté que le faltaba el enchufe al cable de electricidad. Por suerte es bastante fácil de cambiar, así que saqué el enchufe de una lámpara que no uso muy seguido, se lo puse al cable de la tele, y ¡funcionó! (Tengo anotado en mi lista de cosas para hacer “comprar enchufe en la ferretería” para devolver el de la lámpara).

El cable de la TV

La idea de obtener un televisor CRT era jugar al Game Cube como se debe. Muchos snobs del retro gaming dirán que hay que usar un televisor CRT sí o sí para consolas antiguas. Y si bien no me considero para nada un snob (y tengo bastante resentimiento con esta nueva moda hipster de retro coleccionar cosas, ¡que sólo inflan los precios en el mercado!), la imagen está mucho mejor en un televisor CRT que en las teles planas modernas. Hay varias explicaciones al respecto, pero no me quiero ir por esa rama en particular…

La Tele y el GameCube

Algo que me dejó bastante contento es que, como se puede apreciar en las fotos, ¡la tele tiene videocasetera! No sabía si funcionaba porque -oh sorpresa- no tenía videocasetes para probarla. Así que caminé hacia una tienda de porquerías viejas en Edimburgo. Le pregunté al señor de la tienda si tenía videocasetes y me dijo que “Sí, muchos!” y si buscaba algo en particular. Le comenté que necesitaba probar una videocasetera, pero cualquier cosa de ciencia ficción de los 80’s y 90’s me venía bien.

Se levantó y empezó a sacar videocasetes de varias partes de la tienda. La primera película que me mostró fue Alien Resurrection. Pensé “si fuera Alien, o Aliens, o hasta Aliens 3, de repente sí, pero justo ésta… sigamos mirando”. Tenía también Jurassic Park, que es una de mis películas favoritas, pero ya tengo una copia en VHS (en Uruguay…). La tercera película fue Star Wars: Return of the Jedi, Special Edition. La misma edición de la colección que me regaló mi padre hace unos años y que el videocasete de Return of the Jedi se quemó la cinta porque alguien dejó la caja encima de la ventilación de la videocasetera que estuvo en funcionamiento por horas. Así que la compré.

Cuando llegué a casa desinfecté el videocasete y la caja (no sé si esa manía me quedó de la pandemia o quedé paranoico por el olor que había dentro de la tienda…), inserté el casete y rebobiné la cinta. La última persona en usarla no la había rebobinado, que en el caso de un casete del videoclub sería mala educación, pero en este caso pensé “la última persona que tuvo esta cinta la disfrutó”. No pude evitar sonreír cuando apreté Play y vi que funcionaba.

Actualmente tenemos muchos medios para mirar La Guerra de las Galaxias: DVD, Blu-Rays, Versiones desespecializadas (que deshacen decisiones cuestionables de las ediciones especiales), streaming a través del sistema de la corporación del Ratón Miki, etc. Pero para quienes crecimos con estos dispositivos más analógicos, está bueno volver a usarlos después de tantos años. Tienen su gracia además que nos conectan con tantos recuerdos.

Esa colección original en VHS no tiene ningún valor monetario particular, nunca fui de comprar cosas como inversión por su futuro valor potencial. Una búsqueda rápida en eBay de hecho me demuestra que se consigue a precios extremadamente bajos. Pero esos 3 videocasetes en su caja tienen el valor de estos recuerdos. De levantarme un fin de semana temprano, ir al living de la casa de mi madre y ponerme a mirar Star Wars. O juntarme con amigos a pasar una noche sin dormir mirando Star Wars, comiendo pizza, haciendo chistes internos con las películas, y más.

Espero que alguno de mis amigos lea este post y me cuente qué se acuerda de esas noches, o si se acuerda del día que miramos tanto Star Wars y quemamos la cinta del Retorno del Jedi. Con esta compra de un videocasete usado en una tienda muy desordenada y que no recomiento a nadie, siento que se cerró un círculo. No tiene mucho significado en el gran esquema de las cosas, pero en mi mente algo quedó más tranquilo, la colección volvió a estar completa 🙂

El post El Retorno del videocasete del Regreso del Jedi 📼 fue publicado originalmente en Picando Código.

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

Blog Bitix

Ejemplo de patrón Builder para las clases Record de Java

agosto 12, 2022 04:30

Java se ha caracterizado por ser un lenguaje verboso y necesitar declarar todo de forma explícita, esto tiene la ventaja de que el código es muy explícito sin apenas convenciones que es necesario conocer para saber cómo se comporta el código. Por el contrario esta verbosidad requiere declarar gran cantidad de código que se hace repetitivo en muchas clases. Los Records de Java 16 permite declarar clases de datos en muy pocas líneas de código, esto lo consiguen introduciendo algunas convenciones que son de uso común en el lenguaje. Un aspecto que no resuelven los Records es el crear clases Builder que son una necesidad asociada para esas clases de datos.

Java

Java desde la versión 8 ha incorporado muchas novedades y con el ciclo de desarrollo de una nueva versión cada seis meses las novedades han sido numerosas y cada poco tiempo. Una de las novedades disponibles en la versión de Java 16 ha sido una especialización de clase, las clases Record.

Aún con todas las novedades que se han incorporando sigue habiendo algunas necesidades que al no estar cubiertas por el propio lenguaje o una clase del JDK, una de ellas relacionada con las clases Record es utilizar el patrón de diseño Builder.

Contenido del artículo

Las clases Record de Java

Las clases Record incorporadas en Java son muy útiles ya que simplifican enormemente el código de esas clases que prácticamente son contenedores de datos. Las clases Record evitan tener que declarar explícitamente los métodos getter para cada una de las propiedades así como los métodos hashCode y equals, métodos que hay implementar correctamente, también evitan declarar el método toString muy útiles para el correcto funcionamiento cuando las clases se añaden en colecciones.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Point {
   private final int x;
   private final int y;

   Point(int x, int y) {
       this.x = x;
       this.y = y;
   }

   int x() { return x; }
   int y() { return y; }

   public boolean equals(Object o) {
       if (!(o instanceof Point)) return false;
       Point other = (Point) o;
       return other.x == x && other.y == y;
   }

   public int hashCode() {
       return Objects.hash(x, y);
   }

   public String toString() {
       return String.format("Point[x=%d, y=%d]", x, y);
   }
}
records-2.java

La definición de una clase Record lo único que requieren prácticamente es declarar las propiedades y sus tipos, con esta definición la clase implícitamente implementa los métodos getter, hashCode, equals y toString, esta clase Record es equivalente a la anterior pero en muchas menos líneas de código.

1
2
public record Point(int x, int y) {}

records-1.java

Alternativas a Records en versiones anteriores de Java

Usar una de las últimas versiones de Java no es posible en el caso de una aplicación con mucho código existente que usa una versión anterior, a veces no tanto por pasar una nueva versión en el código ya que Java se caracteriza por mantener la compatibilidad hacia atrás sino por alguna dependencia antigua que no es compatible con una versión de Java más reciente o por el entorno de ejecución de la aplicación que ejecutarla sobre una versión más moderna de Java requiere actualizar versiones de librerías que requieren cambios en el código.

Dos librerías como alternativa a los Records utilizables en versiones anteriores de Java 16 son Immutables y Lombok. Ambas proporcionan soporte para evitar mucho del código de las clases Java que se suelen utilizar como contenedores de datos, además proporcionan soporte para crear Builders a partir de ellas.

Aunque Immutables y Lombok son librerías que proporcionan una funcionalidad similar su implementación entre ellas es muy diferente, la implementación de Immutables se realiza generando código con un procesador de anotaciones y Lombok manipula el bytecode de las clases. La aproximación de Immutables es más limpia y potencialmente menos problemática que Lombok pero Lombok es una librería muy popular y sigue utilizándose.

Librería para utilizar el patrón Builder sobre clases Record

No habiendo ninguna restricción para utilizar una versión de Java a partir de la 16 no es necesaria una alternativa a los Records ni requiere dependencias adicionales. Aunque los Records dan solución a una necesidad de crear clases de datos que suelen tener todas las aplicaciones no cubren todas las necesidades como es el caso de crear instancias con una clase Builder.

Hay una librería RecordBuilder para disponer de la funcionalidad del patrón Builder para las clases Record. Con leer el archivo README.md del repositorio Git es más que suficiente para conocerlo todo sobre como usarlo.

Ejemplo de patrón Builder con clase Record

El uso de la librería RecordBuilder para generar clases que implementan el patrón Builder es muy sencillo una vez están definidas las clases Record, basta con anotarlas con la anotación RecordBuilder.

1
2
3
4
5
6
7
8
package io.github.picodotdev.bloblogbitix.javarecordbuilder;

import java.util.Collection;

import io.soabase.recordbuilder.core.RecordBuilder;

@RecordBuilder
public record Book(String title, Collection<String> authors, String isbn, int year, int pages) {}
Book.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
package io.github.picodotdev.bloblogbitix.javarecordbuilder;

import java.util.List;

public class Main {

    public static void main(String[] args) {
        List<String> authors = List.of("Pedro Igor Silva", "Stian Thorgersen");
        Book book = BookBuilder.builder()
                .title("Keycloak - Identity and Access Management for Modern Applications ")
                .authors(authors)
                .isbn("978-1800562493")
                .year(2021)
                .pages(362)
                .build();

        System.out.println(book);
    }
}
Main.java
1
2
Book[title=Keycloak - Identity and Access Management for Modern Applications , authors=[Pedro Igor Silva, Stian Thorgersen], isbn=978-1800562493, year=2021, pages=362]

System.out

Como ocurre con cualquier otra librería hay que incluirla como dependencia del proyecto en este caso con la herramienta de construcción Gradle.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
plugins {
    id 'application'
}

repositories {
    mavenCentral()
}

dependencies {
    annotationProcessor 'io.soabase.record-builder:record-builder-processor:34'
    compileOnly 'io.soabase.record-builder:record-builder-core:34'
}

application {
    mainClass = 'io.github.picodotdev.bloblogbitix.javarecordbuilder.Main'
}
build.gradle
Terminal

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

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

Navegapolis

Agile coaching: los 12 puntos que centran la atención de los entrenadores

agosto 07, 2022 04:20

“Hacer agilildad” no es lo mismo que “ser ágil”. Una cosa es desarrollar de forma iterativa e incremental y otra, que personas motivadas y comprometidas aporten de forma continua y sostenible el mayor valor posible a los productos o servicios que desarrollan.

Incorporar prácticas ágiles no garantiza la agilidad.
Si el equipo, el cliente y la dirección de la empresa no tienen una mentalidad ágil (agile mindset), lo que consiguen es “hacer agilidad”, lo que en términos académicos se denomina: ingeniería concurrente.

El departamento de Ingeniería del Sofware de la Universidad Leibniz de Hannover, ha realizado un estudio (1) entrevistando a nueve entrenadores ágiles (agile coaches) de Alemania y España. El estudio identifica los 12 factores —que según ellos— se deben gestionar adecuadamente para desarrollar una mentalidad ágil.

El factor más importante es al mismo tiempo el más difícil de modelar: tener mentalidad ágil, tanto a nivel personal, como de cultura organizacional; porque las prácticas de trabajo se pueden implantar, pero no se puede hacer lo mismo ni con la mentalidad de las personas, ni con la cultura de la empresa.

Un entrenador ágil no es sólo un formador. Incorporar métodos ágiles es la mitad de su trabajo. La principal tarea de los entrenadores ágiles es el desarrollo de los equipos. Los entrenadores deben tener habilidades y responsabilidades específicas para facilitar las prácticas y supervisar que se realizan de forma correcta.

A menudo, además de imbuir los valores adecuados, el entrenador tiene que entender el contexto en el que se van a emplear métodos ágiles y adaptarlos de forma adecuada.
Para este cometido, necesitan habilidades de liderazgo, que incluyen habilidades de comunicación y comprensión de las dinámicas de grupo. Deben ser capaces de resolver conflictos y saber “crear equipo”.
También necesitan habilidades de gestión de proyectos: gestión del cambio, gestión del riesgo y gestión del conocimiento.

El estudio agrupa los factores claves para el desarrollo de la agilidad en tres dimensiones: el equipo, el propio entrenador ágil y la organización.

EQUIPO

El entrenamiento debe analizar los aspectos relacionados con el equipo: los caracteres y las actitudes de cada miembro, así como los que afectan al conjunto y provienen de un nivel superior.

Agile coaching: equipo

Prerrequisitios y actitudes personales

Una mentalidad ágil requiere la voluntad de aprender continuamente, de reflexionar sobre el comportamiento propio y las ideas aprendidas.
Exige saber extraer conclusiones para mejorar el modo de trabajo. Conclusiones que muchas veces implican cambios personales, por lo que se necesita tener una mentalidad abierta.

Si las personas no están abiertas a la incorporación de nuevas prácticas, no tendrán interés en cambiar.
No basta con la apertura a nuevas formas de trabajar, cada persona debe estar abierta a las demás, incluidas sus actitudes y opiniones.

La agilidad facilita trabajar en situaciones con información insuficiente. Esto requiere, muchas veces reconsiderar la propia opinión y estar dispuesto a ajustarla si es necesario.

La falta de voluntad al cambio es un factor en el que el entrenador difícilmente puede influir.

Lo que el equipo tiene que aportar para la colaboración con el entrenador

La colaboración entre el coach y el equipo debe contar con la voluntad de ambas partes.
El equipo debe participar activamente en la incorporación de la agilidad, tanto a nivel de prácticas como de mentalidad. En definitiva tiene que querer “entrenar”.
Esta voluntad bidireccional implica que, por un lado el equipo debe seguir las indicaciones de entrenador, y por otro que debe pedir al entrenador pistas e ideas y darle feedback de lo que necesita para la mejora de equipo.

Problemas del equipo

Problemas personales, en el equipo o con entidades externas como la dirección de la empresa u otros equipos.
Las dificultades personales de miembros del equipo, suelen ser consecuencia de actitudes propias de la personalidad, o de la resistencia al cambio. La personalidad individual puede causar problemas. Ocurre, por ejemplo con el miedo al fracaso, porque no es compatible con un entorno de trabajo ágil, donde “fracasar rápido” es, a grandes rasgos, una de sus características.
Los problemas que causan determinadas improntas personales afectan sólo a la propia persona; pueden causar conflictos internos en el equipo.

Entre los posibles problemas del equipo también se debe contemplar si faltan flujos de información. Por ejemplo entre el equipo y la dirección. Si el equipo no percibe el apoyo de la dirección o si no conoce cuál es su visión y por qué apuesta por la agilidad, pueden surgir problemas, porque la falta de información reduce el compromiso del equipo.

Las necesidades del equipo

Esta categoría recoge los factores que necesita el equipo para que sea posible la transformación, incluida la adopción de una mentalidad ágil.
Uno es la participación en el proceso. El equipo debe participar en cada paso, para identificarse con los nuevos modos de trabajo.
Incluir facetas ya existentes y conocidas, suaviza la transición.
El equipo debe conocer y entender la visión de la dirección. Sin esta comprensión, es difícil que las personas se identifiquen con la nueva forma de trabajar y posiblemente rechazarán los cambios.
Es importante que la decisión para la transformación ágil no sea una decisión importada por el entrenador. Debe ser una decisión interna de la empresa; motivada, bien por el propio equipo (enfoque ascendente) o bien por la dirección de la empresa (descendente).

Otro factor clave es que la cultura organizativa permita a las personas desarrollar ideas, experimentar e incluso fracasar con nuevos enfoques. Esto requiere que la organización confíe en el equipo. El ambiente de confianza lo deben percibir las personas para ahuyentar el miedo al fracaso.

La confianza también incluye que el entrenador y la organización acepten las actitudes personales. Por ejemplo, si un desarrollador se da cuenta de que su actitud y su idea de trabajo no ese ajustan al nuevo enfoque de desarrollo, entrenador y dirección deben aceptar esta decisión y buscar soluciones, junto con el desarrollador.

También es importante que el entrenador se adapte a las características específicas del equipo. Debe ser flexible y ágil para reaccionar ante nuevas situaciones y cambios.

El equipo debe conocer y comprender por qué se decide implantar la agilidad. En definitiva, entender la razón de ser de las prácticas que está aprendiendo —en especial si parece que sólo consumen tiempo con nuevas reuniones—.

Lo que el equipo debe aprender

Lo que el equipo necesita no sólo aprender, sino interiorizar.

Tiene que aprender a cuestionar y “desaprender” lo conocido. A reflexionar sobre los conocimientos previos y ajustarlos si lo considera necesario. La autorreflexión es importante y se debe interiorizar en el proceso de la transformación ágil.
Aprender a aceptar los problemas y resolverlos.

ENTRENADOR ÁGIL

El entrenamiento también debe tener en cuenta aspectos relacionados con el propio coach. En el modo en el que puede apoyar al equipo y lo que debe hacer para crear una atmósfera que facilite el aprendizaje.

Agile coaching: entrenador

Observar y comprender

El entrenador debe observar al equipo y adquirir un conocimiento implícito del mismo: de las percepciones de las que las personas no hablan.

Se debe interesar en conocer la carrera profesional, experiencia y actitudes de sus miembros, incluidas las posibles dudas o reservas de algunos contra la nueva forma de trabajar. Este conocimiento le permite desarrollar soluciones adecuadas, en colaboración con el equipo.
Para lograr un desarrollo flexible de la agilidad, debe comprender la forma de trabajo existente, los procesos, la motivación y necesidades del equipo.
Por la importancia de los aspectos sociales entre los integrantes, también debe observar el comportamiento interpersonal y detectar posibles problemas en las relaciones, que puedan ir incluso más allá del ámbito laboral, porque pueden entorpecer la colaboración.
El grado de autoorganización y autorresponsabilidad del equipo es importante. El entrenador debe observar el ámbito de libertad definido por la organización.

Actividades del entrenador

En general, son más conceptos que métodos concretos y deben ajustarse al equipo, en función de sus características específicas y sus aspectos sociales.
La mayoría de estos conceptos surgen de las necesidades y problemas que afronta el equipo, de manera que una de las actividades del entrenador es colaborar con él para encontrar soluciones a problemas específicos, de los que incluso el equipo puede no ser consciente. Esta es una situación difícil para el entrenador porque, por un lado no debe crear problemas artificiales y por otro, debe llamar la atención sobre los impedimentos que están entorpeciendo el trabajo y están pasando desapercibidos.

No voy a decirle a un equipo que tiene un problema si eso es lo que siento […] Si noto que hay una discrepancia, puedo intentar aclararlo primero para mí con preguntas, y luego hago que la gente sea consciente de que tal vez sea un tema en el que podamos trabajar.

Otra actividad clave del entrenador es ayudar a vivenciar los valores y la mentalidad ágil.

Siempre intento en las situaciones en las que los afectados podrían comportarse mejor, salir adelante con un buen ejemplo que pueda ser experimentado

Los entrenadores no suelen emplear simulaciones ágiles, porque son más apropiadas para colaboraciones breves en las que se requiere experimentar la agilidad en poco tiempo —por ejemplo en cursos o talleres—.

Otra actividad propia del entrenador, en este caso más concreta, es transmitir el conocimiento teórico de las prácticas ágiles utilizadas, para que el equipo pueda comprender cada técnica empleada y su razón.

No es raro que el equipo experimente incertidumbre y sobrecarga durante el periodo de entrenamiento. Si ocurre, debe estar al tanto y gestionar adecuadamente las circunstancias e información para ayudar a superarlo.

El entrenador debe transmitir expectativas realistas, tanto al equipo como a la organización, sobre el modo de trabajo ágil.

Hacer tangible la agilidad

El entrenador debe trabajar con mentalidad ágil y hacer que el equipo experimente los valores ágiles. Las simulaciones pueden ayudar en esta tarea.

Percepción de la agilidad por parte del entrenador

El entrenador debe percibir el grado de agilidad del equipo. Aquí es importante constatar que un trabajo completamente ágil sólo consigue en equipos autoorganizados.
Si un equipo está totalmente autoorganizado, la forma de trabajo ágil le resulta intuitiva —si tiene la agilidad interiorizada—.

Experiencias del entrenador

Experiencias que resultan útiles a los entrenadores ágiles.

A los coaches externos a la empresa les resulta más fácil que a los internos, percibir de forma objetiva y neutral el estado de la organización.

… los principales retos que teníamos como coaches ágiles dentro de las empresas es que muy fácilmente te intoxicas con la misma cultura. Eres una voz que tiene un color y no todo el mundo te ve como una entidad neutral que puede ayudar a toda la empresa. Así que salir fuera y poder ser considerado como una voz neutral que ayuda a todo el mundo ha sido algo muy útil para nosotros”.

Equipos diferentes se enfrentan a menudo a problemas similares. Sin embargo depende de cada equipo cómo resolver los propios. Aunque pueden ser similares entre sí, la solución siempre tiene que ajustarse a las características particulares. No existe una solución universal para un problema.

Los entrenadores experimentan dificultades con las improntas contra la adaptación de la mentalidad. En estos casos la falta de apertura dificulta el progreso.

Además es importante que la organización apoye al equipo en la evolución. Por ejemplo, llevar a cabo experimentos que pueden fracasar sólo se debería considerar cuando el equipo sabe que la organización apoya esta forma de ensayo y error.

ORGANIZACIÓN

El entrenamiento debe cubrir también aspectos relacionados con el modelo organizativo de la empresa y apoyo de la dirección

Agile coaching: organización

Colaboración entre el entrenador y la dirección

La colaboración entre el coach y la dirección es de especial importancia. El primer contacto del entrenador con la empresa, suele y debe tener lugar con la dirección de la misma. Este primer contacto permite a la dirección compartir con el coach los objetivos que quiere alcanzar.

El compromiso de la dirección es imprescindible desde el primer momento e debe incluir una comunicación adecuada entre la dirección y el equipo.
Los entrenadores comparten con la dirección los problemas que no son endógenos del equipo pero que le afectan y debe asegurar que la dirección no adopta una actitud de rechazo, porque en ese caso no será posible solucionarlos.

Conceptos erróneos y obstáculos

En esta categoría se encuentran los conceptos erróneos y los obstáculos, relacionados con la gerencia, que pueden surgir durante el proceso de transformación.

Uno de los conceptos erróneos más frecuentes es el significado de “ágil”. Es habitual considerar que se trata de una palabra de moda y se malinterpreta pensando que sólo afecta a los equipos de desarrollo. Este conocimiento distorsionado de la agilidad produce una motivación ficticia de la empresa para su implantación.

Otro obstáculo habitual son los juicios erróneos. Es frecuente que la dirección extraiga conclusiones erróneas porque la información que tiene está sesgada por problemas de comunicación con el equipo.

Y por supuesto un obstáculo importante —quizá infranqueable— es una cultura incompatible con los valores de la agilidad.

(1) Jil Klünder, Felix Trommer, Nils Prenner – cc-by 2022 – How agile coaches create an agile mindset in development teams: Insights from an interview study. (copia en caché).

La entrada Agile coaching: los 12 puntos que centran la atención de los entrenadores se publicó primero en Navegápolis.

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

Blog Bitix

Opciones de arquitectura para emitir trazas en una aplicación Java

julio 28, 2022 05:30

Incluso para emitir trazas que en principio es algo sencillo y que se da por hecho surgen varias opciones de arquitectura o diseño. Dos de esas decisiones son acoplarse o no a la librería de logging que se use e inyectar de forma estática o por el constructor la instancia de la clase con la que se emiten trazas. Estas decisiones conviene recogerlas en un documento de Architecture Decision Record por si en un futuro hay que revisar las decisiones tomadas con anterioridad o para que una persona en un futuro tenga el contexto y un registro de las decisiones que se han tomado, el contexto, opciones evaluadas, argumentos y decisiones tomadas.

Java

Una de las cosas más esenciales de una aplicación es generar trazas para tener observabilidad de que está realizando la aplicación y un registro que permita consultar qué ha pasado en cualquier momento que sea necesario, que lo será. Las trazas no son solo por observabilidad a veces también por cumplimiento de requerimientos de seguridad y auditoría.

Por tanto, usar una librería de logging es una de las dependencias básicas, en Java las librerías de logging más utilizadas son log4j 2, SLF4J y las propias clases del JDK para logging del paquete conocido como JUL.

Además de la librería en concreto que usada hay otras decisiones de arquitectura que tomar al aplicar en una aplicación. Independientemente de la opción que se use de todas estas opciones, argumentos y decisiones lo ideal es registrar en un documento que se suele denominar Architecture Decision Record de modo que en un futuro u otra persona pueda tener el contexto de qué y por qué se tomaron en su momento algunas decisiones.

En un artículo publicado en el sitio web de Martin Fowller sobre la observabilidad en el dominio hablan sobre cómo diseñar las clases para añadir esta funcionalidad al código. En este artículo comento sobre la trazabilidad de una aplicación pero lo mismo es aplicable a las métricas como se comenta en el sitio web de Fowller.

Después de leer el artículo de Fowller y este artículo, ¿qué opción usas? ¿alguna otra opción o variante? ¿qué opinas?

Contenido del artículo

Opciones

Estas cuatro opciones tratan dos asuntos diferentes. Las dos primeras tratan de si crear una abstracción o usar la librería de logging directamente sin ninguna abstracción.

La tercera y la cuarta tratan otro aspecto que es como inyectar el logger en las clases que emitan trazas, en realidad no son excluyentes y como comento se puede optar por una u otra forma de inyectar el logger según la clase.

Acoplarse a la librería que emite los logs

En esta opción las clases de la librería de logging se consideran como parte de la plataforma y el código se acopla a ellas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

public Service {

    private static final Logger logger = LogManager.getLogger(Service.class);

    public Service() {
    }

    public void method() {
        logger.info("Message");
    }
}
Service-1.java

Abstracción sobre la librería que emite los logs

Para no acoplarse a una librería en concreto de logging se crea una abstracción que independice de la librería de modo que si esta cambia no haga falta el código sino simplemente la implementación de la abstracción.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import io.github.picodotdev.blogbitix.platform.logging.Logger;
import io.github.picodotdev.blogbitix.platform.logging.LogManager;

public Service {

    private static final Logger logger = LogManager.getLogger(Service.class);

    public Service() {
    }

    public void method() {
        logger.info("Message");
    }
}
Service-2.java

Inyección estática del logger

La forma habitual que ponen de ejemplo las librerías de logging para inyectar la instancia de la clase de logger se realizan mediante una factoría e inicialización estática.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import io.github.picodotdev.blogbitix.platform.logging.Logger;
import io.github.picodotdev.blogbitix.platform.logging.LogManager;

public Service {

    private static final Logger logger = LogManager.getLogger(Service.class);

    public Service() {
    }

    public void method() {
        logger.info("Message");
    }
}
Service-3.java

Inyección por constructor del logger

En vez de inyectar de forma estática el logger, la instancia se inyecta en el constructor como cualquier otro colaborador de la clase.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import io.github.picodotdev.blogbitix.platform.logging.Logger;

public Service {

    private Logger logger;

    public Service(Logger logger) {
        this.logger = logger;
    }

    public void method() {
        logger.info("Message");
    }
}
Service-4.java

Argumentos

Evitar el acoplamiento es algo deseable dado que permite flexibilidad y realizar cambios afectando a una una pequeña parte del código. Con una abstracción es posible cambiar de una implementación a otra y los cambios solo afectan a la abstracción y no al resto del código.

El inconveniente de la abstracción es que requiere crearla y mantenerla y que posiblemente esa abstracción ofrece un subconjunto pequeño de toda la funcionalidad que ofrece la librería de logging que se use. Aún así el subconjunto de la funcionalidad es aquel que realmente se usa.

Incluso aunque el JDK incluye clases de logging y el acoplamiento sea con las clases del JDK por flexibilidad se puede desear crea la abstracción por la posibilidad de cambiar la librería de logging a otra.

La librería SL4J precisamente es una fachada o abstracción sobre otras librerías de logging que permite cambiar de una implementación de librería a logging a otra sin necesidad de cambios en el código de modo que en vez de crear una abstracción propia la abstracción a la que acoplarse puede ser esta.

Otro aspecto a considerar es cómo inyectar la dependencia del logger, esto es independiente de si usa o no una abstracción propia o de otra librería como la de SLF4J.

La inyección estática es simple pero no permite o dificulta hacer pruebas unitarias sobre el logger que es un aspecto de la observabilidad que tal vez se desea probar, por ejemplo por motivos de seguridad se desea que el código emita trazas de inicios de sesión o acciones relevantes que permite tener un log en caso de querer auditar con posterioridad. A veces el único efecto observable de un flujo de código es que se emite una traza.

La inyección como una dependencia del logger como cualquier otro colaborador permite realizar teses unitarios de forma más fácil. La dependencia se añade simplemente en el constructor de la clase. Para las clases que son construidas con el contenedor de dependencias es simple y no requiere más que añadir de forma explícita el colaborador en el constructor, crear una variable y realizar la asignación en la implementación del constructor, estos algo más complejo que la inyección estática pero aporta otras ventajas.

Para las clases que no son construidas con el contenedor de dependencias tener que pasar de forma explícita el logger es una molestia, posiblemente hace el código más complicado además de ser un aspecto de la aplicación no relacionado con la lógica de negocio.

Estas opciones no son excluyentes, en aquellas clases que son creadas por el contenedor dejar al contenedor inyectar la dependencia del logger y el aquellos puntos de la aplicación como clases de dominio no construidas por el contenedor o en clases con métodos estáticos utilizar una inyección estática, sabiendo que en la inyección estática las pruebas unitarias con más complicadas.

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

Variable not found

while (DateTime.Now.Month != 9);

julio 19, 2022 06:05

Como todos los mediados de Julio, poco más o menos, os informo de que el blog entrará en modo de bajo consumo de energía (de mi energía, básicamente 😉) hasta el próximo mes de septiembre, cuando volveremos a retomar el ritmo habitual de publicaciones.

Mientras tanto, espero descansar un poco, renovar fuerzas y disfrutar de la familia y la buena compañía, que durante el año no siempre es posible prestarles la atención que merecen.

Nos vemos a la vuelta, con las baterías bien cargadas y listos para comenzar la nueva temporada. ¡Que disfrutéis de las vacaciones!

Puesta de sol en Costa Ballena (Rota) Imagen: Puesta de sol en Cádiz (Costa Ballena)
Autor: Guillermo Martínez

Publicado en Variable not found.

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

Header Files

Documentar, sí, ¿pero dónde?

julio 14, 2022 10:45

Introducción

Mis primeras experiencias programando se podrían catalogar formalmente de garabatos: un montón de código que a duras penas hacía lo que yo quería que hiciese (el hecho de que fuese en BASIC no ayudaba mucho, todo hay que decirlo). En ese entonces tampoco disponía de conexión a Internet, y aunque la tuviese, tampoco habría encontrado gran cosa en él (aún).

Al poco tiempo aprendí la importancia de dejar, usando palabras en cristiano, una explicación de aquellas líneas. Y así se inició ese viaje en lograr que el código lo entendiese no sólo el ordenador, sino también otro ser humano (que, como pasa inequívocamente, casi siempre era yo mismo poco tiempo después).

Las etapas de la documentación

Al principio uno ve la documentación como algo tedioso e innecesario: ¿por qué he de poner en la lengua de Cervantes (o Shakespeare) lo que esa hermosa línea de código hace, si se ve a leguas? Bueno, cualquiera que haya vuelto a un código suyo escrito pocas semanas atrás sabrá responder a esta pregunta rápidamente (aunque no todo son comentarios, pero hablaremos de ello en un rato).

Poco después casi siempre uno pasa por un período oscuro, opuesto por completo a la falta de documentación pero igual de malo: la sobredocumentación. Si no poner ningún comentario es malo, parafrasear cada comando, instrucción y ciclo de reloj no solo es una pérdida de tiempo en ese momento, es además una pérdida de tiempo a futuro cuando se esté leyendo el código y una pérdida de tiempo aún mayor ya que hay que mantener una documentación que es tan rígida que con el mínimo cambio queda obsoleta.

En términos generales sabemos bien lo que una línea individual hace: leer un fichero, incrementar un valor, grabar un valor a disco… El problema no es qué hace una línea, sino qué se supone que queremos hacer con el conjunto (bloque, función, clase), el por qué se hace. Para el ejemplo anterior bien podría ser generar y almacenar el siguiente ID único. Esto hace a la documentación más útil y además más duradera en el tiempo, ya que no depende del código sino del diseño de la solución y de los requerimientos.

Código expresivo

Cuando llegamos a este punto entendemos que, aunque no haya que documentar cada línea del código, sí que hay que escribir un código que sea legible. No es lo mismo int ab23 = get_value(42, 3.14, 1984); que

constexpr auto ANSWER{42};
constexpr auto PI{3.14};
constexpr auto BEST_YEAR{1984};
int common_digits_count = get_number_of_common_digits(ANSWER, PI, BEST_YEAR);

Esto no sólo aplica a los nombres de variables, tipos y funciones. La expresividad también está en el correcto uso del lenguaje en el que programamos. Por listar algunos:

  • Uso de la biblioteca estándar (no reinventar la rueda, usando un idioma común a otros programadores). ¿Para qué usar un bucle for recorriendo todo el vector en busca de un registro específico, si tenemos std::find_if?
  • Seguir los guidelines generales del lenguaje: como el lenguaje principal de este blog es C++, acá tenéis los guidelines oficiales. Por otro lado, Python por ejemplo usa el PEP 8.
  • Un correcto uso de la semántica propia (¿por qué usar lenguaje imperativo cuando se soporta y prefiere el funcional?)

En resumen, el mejor comentario es el que no se necesita, ya que en ese caso el código habla por sí mismo. Esto no quita que debamos indicar el propósito general si éste no se puede extraer fácilmente del propio código. Veamos cómo documentar el resto.

Documentación de API

Esta documentación suele estar en los ficheros públicos del código, aquellos que ven otros programadores, y se necesita para entender cómo usar las interfaces expuestas, sus funciones, parámetros, propósito de las clases, etc.

Además, estos comentarios suelen diferenciarse de los demás en que tienen una sintaxis particular (dependiendo del lenguaje y otras herramientas de documentación). Por ejemplo, si usamos C++ y Doxygen, podríamos ver algo como

/**
 * Generate a unique private key for a given table.
 * @param table Table for which the key is being generated.
 * @return int Unique key.
 */
int generate_unique_key(const std::string& table);

Es importante destacar que si las APIs están en la frontera de nuestro servicio (por ejemplo, una API REST o un sistema de mensajes), la documentación generada debe estar disponible a otros equipos, tanto de desarrollo como de QA. Esto puede hacerse bien exportando la documentación generada, o bien mediante sistemas de definición de APIs como RAML u OpenAPI que además permitan generar las APIs requeridas por cada proyecto de forma automática a partir de la misma especificación.

Documentación de lógica

Con estos comentarios buscamos resumir el algoritmo, el propósito del código. Muchas veces puede ser un breve resumen al comienzo de una función. Otras se pondrá un comentario para describir lo que se busca con un determinado bloque de código, aunque hay que estar atentos a estos casos, ya que podría ser un indicador de que podemos refactorizar y extraer una función.

Casos particulares y casos borde

Esta documentación es de suma importancia, ya que no se suele poder deducir del código. Son casos especiales para los que el diseño no está preparado, corner cases encontrados en producción o código que simplifica la lógica atajando determinadas situaciones.

En estos casos la documentación busca salvaguardar ese conocimiento de nuestra volátil memoria (o incluso de nuestra volatilidad en la empresa). En el caso de los hotfixes, suele ser buena idea dejar constancia del ID del ticket asociado, de forma que se puede entender mejor el contexto, cómo se produce el error, etc. Comentar por último que estos comentarios son útiles para ayudar a futuros refactorers a entender mejor el problem.

Documentación externa al código

Hay otra parte vital de la documentación y es aquella que describe al conjunto. No siempre podemos entender, o siquiera usar un módulo si no sabemos qué problema resuelve, el diseño de las clases, su interoperabilidad, etc.

En esta parte digamos que siempre hay poco de conflicto sobre cómo documentar: están los que prefieren un fichero README.md en el proyecto, los que abogan por un directorio completo de documentación, los que prefieren ponerla en un gestor de documentos, en una wiki

En términos generales empecemos diciendo que lo más importante es que exista. Si no hay documentación de poco sirve enfrascarnos en una discusión de dónde tiene que ir.

Lo siguiente es que debe ser encontrable. Cualquiera que la necesite debería poder buscarla y acceder a ella (roles aparte).

Por último, debe ser usable. Es decir, que nos aporte la información que necesitamos. Esto incluye que esté actualizada (con el código, con los requerimientos), y que sea adecuada (navegación, contenido, nivel de detalle).

Documentación de especificaciones funcionales

Estos documentos nos indican lo que debería hacer nuestra aplicación, servicio, módulo… Normalmente viene dado por el Product Owner, que a su vez lo ha redactado a partir de los requisitos del Negocio. Un ejemplo de ello serían los diagramas de casos de uso.

Por definición, un desarrollador debería ser un lector de este documento, pero no un escritor, no debería modificarlo ya que podría caer en la tentación de ajustar los requerimientos al comportamiento del sistema, y no al contrario que es como debería ser.

Debido a esto, estos documentos deberían estar separados del código y en un lugar visible por todos los equipos involucrados: desarrollo, diseño, validación… Este lugar podría ser desde algo tan completo como un DMS (como Confluence), hasta algo más sencillo como una wiki o una carpeta compartida en Google Drive.

Documentación del diseño

Si los documentación de especificaciones eran el qué hay que hacer, el diseño de software viene siendo el cómo está pensada la solución, y puede presentarse en diferentes niveles de abstracción: diagramas de clases, de estados, de secuencia, de colaboración, etc. (Para más información se pueden consultar los distintos diagramas UML).

Como es evidente, dichos diagramas y demás documentos son útiles sólo si se corresponden con el código, si le representan. Si no más bien crean confusión. Por ejemplo, ¿el diagrama de secuencia es correcto y la implementación es errónea? ¿o más bien el diagrama se quedó obsoleto por no actualizarlo con los cambios en el código?

Dicho esto, lo más natural es versionar esta documentación a la par que el código, posiblemente como parte del mismo repositorio; o generar parte de ella a partir del código (por ejemplo los diagramas de clases o de colaboración).

Conclusión

Hemos comentado a lo largo de este artículo la importancia de documentar qué hace nuestro código, cómo lo hace, cómo se comunica, de dejar constancia de la experiencia adquirida. Asimismo hemos presentado una propuesta de distribución de la documentación que la pone cercana a los actores interesados así y que permite mantenerla útil a lo largo del tiempo.

Créditos

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

Picando Código

Teenage Mutant Ninja Turtles: The Last Ronin

julio 14, 2022 01:00

Teenage Mutant Ninja Turtles - The Last RoninAnoche empecé (y terminé) de leer Teenage Mutant Ninja Turtles: The Last Ronin. Se trata de una novela gráfica con un guión inicialmente desarrollado por Kevin Eastman y Peter Laird (los creadores originales de las Tortugas Ninja). El borrador fue escrito en la época del cómic original, pero se mantuvo guardado por más de 30 años. Recientemente se retomó a partir de los 10 años y 100 números del escritor Tom Waltz en el cómic de IDW de las Tortugas. Entre Eastman y Watz, con aquel guión original co-escrito por Peter Laird, crearon The Last Ronin.

La historia se desarrolla en una ciudad de Nueva York futurista donde sobrevive solo uno de los hermanos del grupo original. Éste se embarca en una misión para vengar a su familia y amigos y obtener venganza. Parte de la gracia inicial era discutir y adivinar cuál de los 4 iba a ser la tortuga, misterio que se revela ya al final del primer capítulo. Es una historia completamente autocontenida, por lo que no se necesita haber leído ninguno de los cómics anteriores para disfrutarla.

Es muy entretenido y un excelente cómic de las Tortugas Ninja. Se sitúa en este Nueva York distópico, que si bien la distopía es algo que me tiene un poco cansado en lo que vengo leyendo últimamente (culpa más que nada de mis elecciones literarias, pero seguramente también de que es difícil imaginar un futuro distinto con lo mal que viene la sociedad en el presente), no es tan protagonista. Mas bien adorna la trama y ayuda a que avance la historia.

El personaje principal es ahora una tortuga ninja vieja mutante, golpeada por los años y peleas. Van a ir apareciendo personajes clásicos y nuevos, todos conectados a lo que vino antes. Algunos aparecen mediante el uso de flashbacks que nos explican alguna que otra situación, dando el contexto justo y necesario del pasado para disfrutar del resto de la acción. Encontré varios guiños a material anterior, incluso a uno de los juegos de NES. Es divertida, atrapante y me dejó muy conforme con el desenlace general.

El arte es genial, y esos flashbacks que comentaba son dibujados por Kevin Eastman al estilo del cómic original en blanco y negro. La colección en tapa dura es excelente. Me encanta la calidad y lo bien que se ve este libro. Últimamente para algunos títulos estoy tendiendo más a comprar tapa dura por lo más lindo que se ven. Además de la introducción por el director Robert Rodriguez, al final incluye la clásica colección de tapas de los distintos números y tapas alternativas.

En conclusión, una novela gráfica recomendada para amantes del cómic y las Tortugas Ninja Adolescentes Mutantes.

Coincidiendo con la reciente publicación del cómic en formato libro, se publicó una animación creada por fans basada en The Last Ronin. Está muy bien hecha, pueden encontrar más información y los créditos en el video y su canal en YouTube. Aviso que la animación usa detalles de la trama del cómic que a lo mejor no querrían ver antes de leerlo:

YouTube Video

El post Teenage Mutant Ninja Turtles: The Last Ronin fue publicado originalmente en Picando Código.

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

Blog Bitix

Interfaz web para JMX con Hawtio

julio 13, 2022 10:00

Una cosa es la funcionalidad que proporciona una aplicación y otra las tareas de administración y mantenimiento relacionas con la aplicación. Estas tareas de administración y mantenimiento no son tareas destinadas a los usuarios sino destinadas a los administradores de la aplicación. Estas tareas pueden ser manuales y ejecutadas a conveniencia siendo muy útil poder ejecutarlas sin necesidad de realizar cambios en el código ni un despliegue de la aplicación. La tecnología JMX de Java define una arquitectura para administrar y monitorizar aplicaciones que se puede utilizar para estas tareas administrativas, Hawtio es una interfaz que permite el acceso y ejecución a JMX mediante un navegador y proporciona una librería para integrase con Spring Boot.

Java

Las computadoras y las aplicaciones realizan sus funciones de forma rápida y determinista ofreciendo su servicio a sus usuarios. El software generalmente se diseña para el caso en el que todo funcione correctamente pero también ha de estar preparado para los casos en los que se produzca un error ya sea simplemente emitiendo una traza o autocorrigiendo el problema con un reintento.

Especialmente con el advenimiento de los microservicios que se basan en la comunicación por red las aplicaciones han de estar preparadas para los errores. Si un proceso en una computadora es muy fiable salvo por fallo del hardware las redes son mucho menos fiables más cuando hay comunicación entre varios servicios dado que la conectividad de red se puede perder o un servicio puede fallar repentinamente por un fallo de software o por un fallo de hardware.

Para reparar los efectos de estos errores o simplemente para ejecutar de forma explícita ciertos procesos administrativos independientemente de si es a raíz de un error o no. Las aplicaciones puden incorporar estas adicionalmente estas funcionalidades administrativas y proporcionar una forma de invocarlas, de forma sencilla, rápida y evitando en la medida posible errores manuales.

Contenido del artículo

La funcionalidad principal y las tareas administrativas

Seguramente la funcionalidad principal que proporciona una aplicación no requiera ninguna acción, mantenimiento ni acciones manuales. La aplicación mientras esté en funcionamiento proporcionará su servicio ya sea una aplicación web que sirva contenido para un navegador web o una API basada en REST que proporcione datos y reciba peticiones de otras aplicaciones.

Otras funcionalidades relacionadas con la aplicación se desean ejecutar por ejemplo para corregir algún error puntual en la aplicación, para obtener algún dato o simplemente para realizar una acción que se desea iniciar de forma manual. Las tareas administrativas pueden ser parte una parte de la funcionalidad que es necesario ejecutar a conveniencia en momentos determinados.

Hay que poder acceder a ellas de alguna forma, idealmente mejor sin desplegar una nueva versión por los riesgos de un despliegue sobre todo si los procesos y aseguramiento de calidad no permiten hacer despliegues con confianza o los despliegues requieren demasiado tiempo o suponen una interrupción del servicio. Que esté la funcionalidad disponible e invocarla en el momento que se necesite hace más sencilla la necesidad.

La tecnología JMX de Java

La tecnología JMX es un estándar de Java que define una arquitectura para administrar y monitorizar aplicaciones y servicios Java. Desde el punto de vista del desarrollador JMX requiere programar unas clases de Java siguiendo las convenciones del estándar denominadas MBean. Las instancias de estas clases son registradas y administradas por el contenedor de JMX donde quedan disponibles para uso.

En el artículo Interfaz de monitorización e instrumentalización con JMX en aplicaciones Java comentaba cómo crear una clase MBean con unos métodos para realizar acciones y otro método para devolver datos. El ejemplo incluía la forma de usar JMX en una aplicación Java y en una aplicación de Spring Boot con el soporte que ofrece el framework para la utilización de JMX en Spring Boot.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package io.github.picodotdev.blogbitix.springboothawtio;

public interface HelloMBean {

    void sayHello();

    int add(int x, int y);

    String getName();
}
HelloMBean.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package io.github.picodotdev.blogbitix.springboothawtio;

import org.springframework.stereotype.Component;

import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedAttribute;

@Component
@ManagedResource(objectName = "io.github.picodotdev.blogbitix:type=Hello")
public class Hello implements HelloMBean {

    @ManagedOperation
    public void sayHello() {
        System.out.println("hello, world");
    }

    @ManagedOperation
    public int add(int x, int y) {
        return x + y;
    }

    @ManagedAttribute
    public String getName() {
        return "Reginald";
    }
}
Hello.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
package io.github.picodotdev.blogbitix.springboothawtio;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableMBeanExport;

@SpringBootApplication
@EnableMBeanExport
public class Main {

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }
}
Main.java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
spring:
  jmx:
    enabled: true

management:
  server:
    port: 8081
  endpoints:
    web:
      exposure:
        include: "hawtio,jolokia"

hawtio:
  authenticationEnabled: false
application.yml
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
plugins {
    id 'application'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation platform('org.springframework.boot:spring-boot-dependencies:2.7.1')
    implementation platform('io.hawt:hawtio-bom:2.15.0')

    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'io.hawt:hawtio-springboot'
}

application {
    mainClass = 'io.github.picodotdev.blogbitix.springboothawtio.Main'
}

tasks.named('test') {
    useJUnitPlatform()
}
build.gradle

La interfaz Hawtio

La tecnología de JMX es una buena opción como punto de entrada en la implementación de esas tareas administrativas. Sin embargo, es necesario una forma de poder invocarlas.

El proyecto Hawtio proporciona una interfaz web en la que poder ver, obtener datos e invocar las operaciones ofrecidas por los MBeans registrados en el contenedor de JMX, los propios de la aplicación y muchos otros que proporciona Java y en el caso de utilizarlo Spring Boot.

Hawtio utiliza el proyecto Jolokia que expone mediante una interfaz REST los MBeans del contenedor JMX, Hawtio utiliza la interfaz REST de Jolokia para invocar las operaciones. Spring Boot proporciona soporte para la implementación de JMX y Hawtio proporciona una dependencia para su integración con Spring Boot que añade en la interfaz de administración un endpoint para acceder a la consola de Hawtio.

Las operaciones administrativas seguramente sean funcionalidades que realicen tareas que no deban ser accesibles para los usuarios y han de estar protegidos. Hawtio permite la integración con Keycloak para la autenticación y permite solicitar credenciales para el acceso a la consola web.

Consola de Hawtio como un actuator en aplicación de Spring Boot

Consola de Hawtio como un actuator en aplicación de Spring Boot

Añadir seguridad a la interfaz de Hawtio con Hashicorp Boundary

Por motivos de seguridad es deseable que la consola web de Hawtio no esté accesible mediante una conexión directa. Bondary es uno de los productos de Hashicorp que proporciona la funcionalidad de un bastión y un proxy de conexión a servicios internos, es más seguro que una VPN ya que a diferencia de una VPN únicamente otorga acceso a los sistemas necesarios y no a toda una red interna completa.

El uso de Boundary requiere una conexión a una base de datos, en el modo de desarrollo inicia una instancia de PostgreSQL mediante Docker. Una vez iniciado hay que autenticarse para obtener un token que otorga las credenciales de autorización de conexión a los diferentes sistemas o targets como los denomina Boundary.

Por defecto Boundary en el modo desarrollo crea una definición del host local y un target al puerto 22 de la máquina local. Dado que Hawtio seguramente esté en otros puertos, en el ejemplo en el puerto 8081 es necesario crear un target y añadir el host para la máquina local que permita la conexión a ese puerto.

Con Boundary iniciado y el target definido hay que establecer el túnel con la conexión a la máquina destino, esto crea un túnel abriendo un puerto en la máquina local que tiene como destino el target que se ha utilizado para la conexión, en este ejemplo a la propia máquina local al puerto 8081.

Consola de Boundary

Consola de Boundary

Creación de un target en Boundary Creación de un target en Boundary Creación de un target en Boundary

Creación de un target en Boundary

Antes de establecer el túnel de la conexión hay que autenticarse en Boudary lo que otorga un token para establecer la conexión, en el siguiente comando el token se guarda en una variable de entorno que comando de Buildary utiliza para la autorización al solicitar la conexión, en la conexión se indica el target y Boundary proporciona el puerto del túnel y el identificativo de la sesión.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
$ boundary authenticate password -auth-method-id=ampw_1234567890 -login-name=admin -password=password
...
Authentication information:
  Account ID:      acctpw_1234567890
  Auth Method ID:  ampw_1234567890
  Expiration Time: Thu, 21 Jul 2022 19:03:46 CEST
  User ID:         u_1234567890
...

at_Gf2PG4GGcQ_s17U6Fz5B2DGh7EBdAuAGaifTLUCV1LSMRHZXL7vme1L6RpcroPW39DSEjAMtJcvEhN6otiod3RSMRKRX7RGUndqACd2jx2i2gHBMr7Rdih8yFF
...
$ export BOUNDARY_TOKEN="at_Gf2PG4GGcQ_s17U6Fz5B2DGh7EBdAuAGaifTLUCV1LSMRHZXL7vme1L6RpcroPW39DSEjAMtJcvEhN6otiod3RSMRKRX7RGUndqACd2jx2i2gHBMr7Rdih8yFF"
$ boundary connect -target-id ttcp_99NRL1z7Fw

Proxy listening information:
  Address:             127.0.0.1
  Connection Limit:    -1
  Expiration:          Fri, 15 Jul 2022 03:08:05 CEST
  Port:                43923
  Protocol:            tcp
  Session ID:          s_jL5oGhBjb2
boundary-connect.sh

Esto proporciona un puerto en la máquina local abierto contra Boundary y este contra la máquina y el puerto destino. En este ejemplo está todo en la máquina local pero a efectos prácticos ahora es posible utilizar el puerto proporcionado por Boundary para hacer la conexión a la consola de Hawtio, en vez del puerto 8081 la conexión a través de Boundary se realiza mediante el puerto 43923.

Conexión a Hawtio a través de Boundary

Conexión a Hawtio a través de Boundary

Además, con Boundary es posible monitorizar las conexiones y sesiones establecidas lo que proporciona medidas adicionales de seguridad y auditoría.

Sesiones establecidas y activas establecidas a través de Boudary

Sesiones establecidas y activas establecidas a través de Boudary
Terminal

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

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

Variable not found

Cómo modificar la reason phrase en una respuesta HTTP de ASP.NET Core

julio 12, 2022 06:05

ASP.NET Core

Como sabemos, la respuesta a todas las peticiones HTTP comienzan por un código de estado que indica el resultado de la operación. Ahí encontramos desde los códigos más célebres, como HTTP 200 (Ok) o HTTP 404 (Not found) hasta otras joyas menos conocidas como HTTP 429 (Too many requests) o HTTP 418 (I'm a teapot).

Sin embargo, pocas veces nos fijamos en el texto que acompaña al código de respuesta, denominado reason phrase (en los ejemplos anteriores va entre paréntesis, como "Ok" o "Not found"). Según se define en la RFC 7230 sección 3.1.2, la reason phrase...

"... existe con el único propósito de proporcionar una descripción textual asociada con el código de estado numérico, principalmente como una deferencia a los protocolos iniciales de Internet, que eran utilizados frecuentemente por clientes de texto interactivos. Un cliente DEBERÍA ignorar su contenido"

Por tanto, dado que se trata de un texto arbitrario y puramente informativo, deberíamos poder modificarlo a nuestro antojo, más allá de los textos estándar proporcionados por el framework.

En aplicaciones ASP.NET 4.x para .NET Framework, esto se podía hacer de forma sencilla estableciendo la propiedad ReasonPhrase del objeto Response del contexto HTTP:

// ASP.NET "clásico":
httpContext.Response.StatusCode = 200;
httpContext.Response.ReasonPhrase = "Done";

Sin embargo, si lleváis algún tiempo trabajando con ASP.NET Core, sabréis que no es posible, o al menos de forma tan directa, pues el objeto Response no expone ninguna propiedad con este fin:

// ASP.NET Core:
app.MapGet("/", (HttpResponse response) =>
{
response.StatusCode = 200;
response.ReasonPhrase = "Done"; // Error: no existe la propiedad
});

Sin embargo, podemos encontrar una propiedad idéntica en el objeto IHttpResponseFeature disponible en la colección de features del contexto HTTP de la petición. Por tanto, basta con acceder a esta característica a través del objeto HttpContext que podemos inyectar como parámetro:

app.MapGet("/", (HttpContext ctx) =>
{
var httpResponseFeature = ctx.Features.Get<IHttpResponseFeature>();
if (httpResponseFeature != null)
{
httpResponseFeature.StatusCode = 200;
httpResponseFeature.ReasonPhrase = "Done";
}
});

De forma muy similar podríamos hacerlo también desde una acción MVC, pues la clase Controller ya nos da acceso a la instancia de HttpContext actual:

public class HomeController: Controller
{
public IActionResult Index()
{
var httpResponseFeature = HttpContext.Features.Get<IHttpResponseFeature>();
if (httpResponseFeature != null)
{
httpResponseFeature.ReasonPhrase = "View returned!";
}
return View();
}
}

Publicado en Variable not found.

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

Variable not found

Enlaces interesantes 495

julio 11, 2022 06:39

Enlaces interesantes

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

Por si te lo perdiste...

.NET Core / .NET

ASP.NET Core / ASP.NET / Blazor

Azure / Cloud

Conceptos / Patrones / Buenas prácticas

Data

Machine learning / IA / Bots

Web / HTML / CSS / Javascript

Visual Studio / Complementos / Herramientas

Xamarin / .NET MAUI

    Publicado en Variable not found.

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

    proyectos Ágiles

    Master en Agile – MMA 2022 – 2023

    julio 10, 2022 06:50

    En octubre de 2022 se iniciará el Barcelona la 12ª 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.

    MMA-banner

    El Máster incluye el Certified Scrum Master (CSM) de la Scrum Alliance y la certificación Kanban Systems Design de la Lean Kanban University.

    SAI_BadgeSizes_DigitalBadging_CSM

    Certified Kanban Training

    Esta es una oportunidad única para aprender de profesionales-profesores de primer nivel, con varios 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 y ponentes en conferencias nacionales e incluso internacionales.

    MMA - Profesores 2022-2023

    PMA – Postgrado en métodos Ágiles

    El PMA incluye el Certified Scrum Master (CSM) de la Scrum Alliance.

    Asignaturas Temas Profesores
    Fundamentos & Inception Principios y métodos más conocidos (Scrum, Lean, Kanban y XP). Facilitadores e impedimentos.

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

    Silvia Sistaré

    Agustín Yagüe

    Scrum y Kanban Estimación y planificación ágil, framework de Scrum, retrospectivas, Kanban, métricas ágiles, herramientas ágiles físicas, radiadores de información. Tiago Garcez

    Teodora Bozheva

    Personas y equipos Gestió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 ágil Design Thinking.

    Lean Startup, OKR & Agile Product Management

    Juncal Guinea

    Gabriel Prat

    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.

    Juncal Guinea

    Álvaro García

    Pablo Gómez

    Cristina Verdi

    Trabajo Final de Postgrado Durante 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.

    MMA – Master en Métodos Ágiles

    Incluye todas las asignaturas del Postgrado (PMA), el CSM, la certificación Kanban Systems Design de la Lean Kanban University y, adicionalmente, las siguientes asignaturas especializadas en Business Agility, agilidad organizacional y transformación:

    Asignaturas Temas Profesores
    Enterprise Learning & personal efficiency Agile Kaizen, Comunidades de Práctica, Open Spaces, Talent development, gamification.

    Productividad y aprendizaje personal en Agile (eficiencia).

    Steven Wallace

    Jordi Molla

    Lean Thinking & Agile Management Lean. Escalado con Kanban.

    Visual Management Framework (VMF- Agile para cualquier área – Fuera de tecnología).

    Agile-Lean Management

    Teodora Bozheva

    Xavier Quesada

    Xavier Albaladejo

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

    Tipos de cultura empresarial, gestión del cambio organizativo.

    Joserra Díaz

    Jasmina Nikolic
    Jaume Gurt

    Transformación Continua Estrategia de despliegue de Agile en organizaciones. Contratos ágiles.

    Enterprise continuous improvement.

    Enterprise software development & DevOps.

    Xavier Albaladejo

    Ángel Medinilla

    Álvaro García

    Scaling Agile  Escalado (LESS, Spotify, Nexus, SAFe), 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áster Durante 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 (public speaking)

    También contaremos con la aparición de Ángel Díaz-Maroto (que nos hablará de resiliencia organizativa y de otros temas súper interesantes que se ven en su CAL training).

    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.

    Algunos comentarios de los alumnos en ediciones anteriores: «Cuando se acaba la clase, estamos ya esperando a que llegue la semana que viene para ver un nuevo tema con el siguiente profesor». «Muy práctico». «La calidad y diversidad de puntos de vista entre los profesores le aporta mucho valor».  Más detalles en: Mejora de la situación laboral los alumnos del PMA tras un año.

    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.

    El Máster tendrá una duración de un año académico y se realizará viernes tarde y sábado por la mañana.

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

    –> Ver también cuál ha sido la Mejora de la situación laboral de los alumnos tras un año y los Principales aspectos valorados por los alumnos.

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

    Blog Bitix

    Generar releases de un proyecto Java con Gradle

    julio 08, 2022 02:00

    Utilizar las etiquetas de las herramientas de control de versiones permite conservar ciertos hitos o commits importantes para consultarlos en el futuro. Generar una versión de un proyecto suele implicar generar una etiqueta en la herramienta de control de versiones. Dado que la generación de nuevas versiones es parte del ciclo de vida de un proyecto hay plugins tanto para Maven como para Gradle que ofrecen como funcionalidad automatizar esta proceso.

    Java

    La generación de releases es una tarea habitual en un proyecto, la release es una forma de identificar de forma exacta la versión que se utiliza para desplegar en un entorno o en producción o es la versión que utilizan otros proyectos para utilizarla como una dependencia.

    Hay varias nomenclaturas para denominar a las versiones. En Java hay varios plugins para las herramientas de construcción Maven o Gradle para los proyectos Java que permite generar releases.

    Contenido del artículo

    Las releases de un proyecto o artefacto

    En el ciclo de vida de un proyecto o repositorio hay ciertos hitos importantes como cómo son los momentos en los que se desea generar una nueva versión a partir de un commit ya sea para ser desplegada en un servidor o ser usada por otros proyectos como una dependencia.

    Las releases son los commits a los que se les asigna una versión y a partir de los cuales se generan los artefactos del repositorio o proyecto. Una forma de recordar esos hitos en el repositorio de control de versiones como Git es creando un tag. Un tag es simplemente asignar una etiqueta con un nombre más semántico y fácilmente identificable que el hash del commit.

    Una forma habitual para los nombres de las versiones o releases es utilizar una nomenclatura compuesta de tres números separados por un punto, por ejemplo 1.2.6, un número mayor en esta versiones implica una versión más reciente y seguramente con más funcionalidades y mejorada. Cada uno de estos números se denominan major.minor.patch donde por norma general el major se incrementa en cada versión destacada o incompatible respecto a las versiones anteriores, minor se incrementa cuando hay cambios importantes con alguna funcionalidad destacada añadida pero que siguen siendo compatibles con versiones anteriores y patch se incrementa cuando los cambios de la nueva versión son menores como corrección de errores o fallos de seguridad pero sin nuevas funcionalidades.

    Dado que la construcción y ciclo de vida del proyecto se gestiona generalmente con una herramienta de construcción la generación de releases se automatiza con Maven o Gradle en el caso de proyectos Java.

    Plugin de release para Gradle

    Gradle no dispone de un plugin oficial para generar releases de un proyectos y hay que recurrir a plugins desarrollados por un tercero. En Gradle hay dos plugins destacables que permiten automatizar la generación de releases en un proyecto. El segundo no ha generado una nueva versión desde hace cinco años con lo que parece más recomendable el primero por estar mejor mantenido actualmente

    El plugin de Axion para generar releases la forma que utiliza para generar una release es creando un tag en el repositorio de código fuente siguiendo la nomenclatura major.minor.patch según las etiquetas ya creadas e incrementando el número de uno de estos tres elementos.

    Que la release consista simplemente en crear una etiqueta tiene la ventaja de que no es necesario crear commits adicionales en el repositorio de código fuente lo que potencialmente invalida la versión probada en un proceso de aseguramiento de calidad.

    Plugin de release para Maven

    El plugin de release de Maven es ofrecido de forma oficial por los desarrolladores de esta herramienta de construcción.

    Su forma de funcionamiento también incrementa las versiones siguiendo la nomenclatura major.minor.patch pero dado que en Maven la versión del proyecto se especifica en los archivos descriptores de construcción pom.xml implica que el proceso de release crea commits en el repositorio de código fuente.

    Ejemplo usando el plugin de release para Gradle

    Usar el plugin de Axion en Gradle requiere añadir el plugin en la lista de plugins del proyecto. El plugin ofrece una sección en la que personalizar algunas opciones de configuración según las preferencias que se deseen en la sección scmVersion. Para diferenciar las etiquetas de releases del resto de etiquetas se puede establecer en prefijo, en el ejemplo con la letra v.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    
    plugins {
        id 'java-gradle-plugin'
        id 'maven-publish'
        id 'pl.allegro.tech.build.axion-release' version '1.13.14'
    }
    
    scmVersion {
        tag {
            prefix = 'v'
        }
    }
    
    project.with {
        group = 'io.github.picodotdev.blogbitix.build.gradle.plugin'
        version = scmVersion.version
    }
    
    repositories {
        mavenCentral()
        gradlePluginPortal()
    }
    
    dependencies {
        implementation 'net.sourceforge.pmd:pmd:6.44.0'
        implementation 'com.puppycrawl.tools:checkstyle:10.1'
        implementation 'com.github.spotbugs.snom:spotbugs-gradle-plugin:5.0.6'
        implementation 'org.owasp.dependencycheck:org.owasp.dependencycheck.gradle.plugin:7.1.0.1'
        implementation 'org.owasp.dependencycheck:org.owasp.dependencycheck.gradle.plugin:7.1.0.1'
        implementation 'pl.allegro.tech.build:axion-release-plugin:1.13.14'
    
        testImplementation 'org.junit.jupiter:junit-jupiter:5.8.1'
    }
    
    publishing {
        repositories {
            maven {
                name = "ArtifactsRespotiry"
                url = uri("https://maven.pkg.github.com/picodotdev/github-packages")
                credentials {
                    username = project.findProperty("gpr.user") ?: System.getenv("USERNAME")
                    password = project.findProperty("gpr.key") ?: System.getenv("TOKEN")
                }
            }
        }
    }
    
    gradlePlugin {
        plugins {
            javaGradlePlugin {
                id = 'io.github.picodotdev.blogbitix.build.gradle.plugin'
                implementationClass = 'io.github.picodotdev.blogbitix.build.gradle.plugin.JavaGradlePluginPlugin'
            }
        }
    }
    
    tasks.named('test') {
        useJUnitPlatform()
    }
    build.gradle

    El comando principal para generar una nueva versión es tan simple como utilizar una tarea ofrecida por el plugin.

    1
    2
    
    $ ./gradlew release
    
    
    gradlew-release.sh

    En la versión actual del proyecto se obtiene con otra tarea añadida por el proyecto. En esencia busca entre los tags en el repositorio y según el commit actual devuelve la versión actual.

    1
    2
    
    $ ./gradlew currentVersion
    Project version: 0.1.1
    
    gradlew-currentversion.sh

    Dado que las releases son simplemente etiquetas en el repositorio de código fuente estas pueden verse con el comando de Git para listar las etiquetas.

    1
    2
    3
    
    $ git tag
    v0.1.0
    v0.1.1
    git-tag.sh

    El comportamiento por defecto de la tarea release es incrementar el componente menos significativo es incrementado que estando la versión compuesta de tres elementos significa que se incrementa el número de patch, el plugin ofrece también la posibilidad de especificar el número de versión que se desea o incrementar otro elemento.

    1
    2
    3
    4
    
    $ ./gradlew markNextVersion -Prelease.version=2.0.0
    $ ./gradlew markNextVersion -Prelease.incrementer=incrementMajor
    $ ./gradlew markNextVersion -Prelease.incrementer=incrementMinor
    $ ./gradlew markNextVersion -Prelease.incrementer=incrementPatch
    gradlew-marknextversion.sh

    En caso de utilizar GitHub al generar la versión y etiqueta y subirla al repositorio lo añade en la sección de releases en la página de GitHub del proyecto.

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

    Variable not found

    ¡Microsoft MVP 2022-2023!

    julio 06, 2022 06:05

    MVP Award

    Un año más, es una alegría enorme compartir con vosotros que Microsoft me ha reconocido por duodécimo año consecutivo como MVP (Most Valuable Professional) en la categoría de tecnologías de desarrollo. Aunque ha pasado bastante tiempo desde que me sorprendiera el mail con el primer nombramiento, sigo recibiéndolo con gran ilusión, el orgullo de seguir formando parte de esta familia y también la responsabilidad de intentar estar a la altura de este honor.

    Y como en este mundo hay que entender de dónde y por qué llegan las cosas, no puedo sino haceros llegar mi eterno agradecimiento a todos los que habéis hecho este sueño posible: a los que visitáis de vez en cuando este rinconcillo de la red para obtener o compartir información, porque sois la gasolina que hace que este motor funcione; al equipo del programa MVP, por su incansable trabajo para conseguir que tengamos una gran comunidad de desarrolladores; y, por supuesto, a mis tres niñas, que asumen mis ausencias con la naturalidad de lo que siempre ha sido así.

    Aprovecho también para enviar mis felicitaciones a compañeros que continúan siendo MVP (ya sabéis que no es sólo llegar, también mantenerse) y a los que hoy han recibido ese email con una de las mayores alegrías de su vida :)

    ¡Nos vemos por aquí!

    Publicado en Variable not found.

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

    Variable not found

    Validación de servicios en entornos distintos a "Development" en ASP.NET Core 6

    julio 05, 2022 06:05

    ASP.NET Core

    Una de las (muchas) cosas buenas que trajo ASP.NET Core (y .NET Core en general) sin duda ha sido la popularización de la inyección de dependencias y la filosofía de implementación de componentes desacoplados que expone en múltiples puntos.

    Esto ha provocado que en nuestras aplicaciones sea ya habitual encontrar secciones de código dedicadas al registro de decenas o centenares de servicios usando los distintos ámbitos disponibles (scoped, singleton o transient). El problema es que esta abundancia de servicios y la asiduidad con la que registramos nuevos componentes o modificamos sus dependencias hace que se nos puedan pasar por alto detalles que pueden hacer que nuestra aplicación falle. Por ejemplo, es fácil que olvidemos registrar algún servicio, o que, por un despiste, inyectemos servicios en componentes registrados con ámbitos incompatibles.

    Por defecto ASP.NET Core nos protege de estos errores automáticamente, realizando un chequeo básico del contenedor de servicios cuando lanzamos la aplicación en el entorno "Development". Se producirá una excepción durante la inicialización de la aplicación cuando:

    • En un servicio registrado se inyectan vía constructor servicios que no se han definido. Tiene sentido, puesto que la dependencia nunca podría ser satisfecha en tiempo de ejecución y provocaría un error en el momento de intentarlo.

    • Un servicio scoped deba ser creado desde el proveedor raíz. Esto ocurre, por ejemplo, cuando en un servicio registrado como singleton inyectamos un servicio scoped, dado que el singleton es creado una única vez y es ajeno a los ámbitos que usan los servicios scoped (en ASP.NET Core, la petición que está siendo procesada).

    El hecho de que estas validaciones se realicen sólo cuando la aplicación corre en el entorno "Development" quiere decir que dejamos fuera otros entornos que quizás podrían resultar interesantes. "Production" quizás es especial porque estas comprobaciones requieren su tiempo y normalmente querremos que en producción la aplicación arranque lo antes posible. Pero en entornos de desarrollo personalizados, o incluso "Staging" podría venirnos bien este extra de seguridad para evitar males mayores.

    En versiones de ASP.NET Core anteriores a la 6.0 podíamos activar estas comprobaciones manualmente en el código de inicialización de Program.cs:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
    .ConfigureWebHostDefaults(webBuilder =>
    {
    webBuilder.UseStartup<Startup>();
    })
    .UseDefaultServiceProvider(opt =>
    {
    opt.ValidateOnBuild = true;
    opt.ValidateScopes = true;
    });

    En ASP.NET Core 6 la cosa cambia un poco, porque la configuración del host queda más escondida bajo las nuevas abstracciones del minimal hosting. Pero podemos conseguirlo de forma igualmente sencilla retocando el Program.cs:

    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseDefaultServiceProvider(c=>
    {
    c.ValidateScopes = true;
    c.ValidateOnBuild = true;
    });

    En general, creo que como medida de protección extra sería una buena idea introducir estas configuraciones en todos los entornos, quizás exceptuando "Production" en aplicaciones en las que minimizar el tiempo de inicio sea crítico. Por tanto, el código de arranque podría quedar como el siguiente:

    var builder = WebApplication.CreateBuilder(args);
    builder.Host.UseDefaultServiceProvider(c =>
    {
    if (!builder.Environment.IsProduction())
    {
    c.ValidateScopes = true;
    c.ValidateOnBuild = true;
    }
    });

    Pero ojo, no penséis que estaréis a salvo de cualquier metedura de pata en lo relativo al registro de servicios: estos chequeos no tienen en cuenta servicios genéricos, ni aquellos que no sean inyectados directamente al controlador (por ejemplo, los inyectados en métodos con [FromServices] o a través del service provider). Por defecto tampoco se tendrán en cuenta los controladores MVC, porque no son creados desde el inyector, a no ser que durante la inicialización así lo indiquemos:

    ...
    builder.Services
    .AddControllersWithViews()
    .AddControllersAsServices(); // Add controllers to the DI container

    Espero que os resulte de utilidad :)

    Publicado en Variable not found.

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

    Variable not found

    Enlaces interesantes 494

    julio 04, 2022 06:47

    Enlaces interesantes

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

    Por si te lo perdiste...

    .NET Core / .NET

    ASP.NET Core / ASP.NET / Blazor

    Azure / Cloud

    Conceptos / Patrones / Buenas prácticas

      Web / HTML / CSS / Javascript

      Visual Studio / Complementos / Herramientas

      Xamarin / .NET MAUI

      Otros

      Publicado en Variable not found.

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

      Blog Bitix

      Hemeroteca #21

      junio 30, 2022 09:00

      En el resumen de este semestre en Blog Bitix está el haber colaborado con una marca de teclados mecánicos con varios artículos promocionados la primera de este tipo en el blog. He añadido la plataforma publicitaria que hasta el momento va a suponer los ingresos del blog. En cuanto a alis un nuevo diseño para su página web y unos pocos cambios con mejoras en el script. Por la parte de artículos del blog he estado publicado habitualmente un único artículo en vez de dos como en otras épocas pasadas, unos 25 artículos únicos y originales más y van ya más de 600.

      Blog Bitix

      Hay algunos medios que hacen cosas horribles como hablar de algo y no poner ni siquiera un enlace a la página de lo que se habla, quizá por falta de tiempo, no tener que mantener esos enlaces en el futuro o quizá pensando que así no sales de su web. En mis artículos siempre trato de incluir un enlace en la primera referencia de algo.

      Otros seis meses de vida para Blog Bitix y otra buena cantidad de artículos publicados y algunas pocas novedades en el blog.

      Contenido del artículo

      Blog

      Durante estos seis últimos meses he publicado menos artículos ya que no estoy teniendo tanto tiempo para escribir en el blog, pensar en ideas y hacer pruebas para los ejemplos. Trato de que sea al menos uno por semana habitualmente cuando hace algo más de tiempo eran casi dos por semana. Un artículo por semana sigue siendo un ritmo de publicación bastante alto y que durante la semana me ocupa varios días. Los artículos ahora los estoy publicado el jueves para tratar de tener el fin de semana libre de tareas relacionadas con el blog para tratar de descansar.

      En las novedades del blog es que la marca de teclados DIERYA y KEMOVE me han enviado varios ejemplares de teclado mecánico de su catálogo que me los quedo en propiedad a cambio de publicar un artículo sobre ellos e incluir enlaces a sus web. En total han sido cuatro teclados cualquiera de ellos muy decentes, desde la gama de entrada hasta un teclado valorado en 150€, en realidad dos de estos los más caros porque se debieron confundir y me enviaron dos unidades del ARES. Además de los teclados me enviaron una funda de teclado de la que publiqué su respectivo artículo.

      Como ya tengo el Glorious que es TKL y los de DIERYA y KEMOVE son 60% y no cubren mis necesidades me voy a quedar solo con el KEMOVE DK61 que es inalámbrico y algo de uso le daré para controlar la reproducción al ver una película. El resto de teclados que están completamente nuevos salvo por tener la caja abierta los pondré a la venta en Wallapop porque no les voy a dar uso, ya he vendido uno así que me faltan por vender otros tres.

      De todos estos artículos he publicado sus respectivos análisis y desempaquetados. Seguramente la marca me contactó gracias a los artículos que había publicado con anterioridad sobre teclados mecánicos. Si esto es lo que una marca le ofrece a mi cutre blog que no le ofrecerán algunas marcas a blogs, medios y canales de YouTube con varios cientos de miles de suscriptores y seguidores.

      En cuanto a tareas de mejora del propio blog he migrado a Google Analytics 4 desde Google Universal y aún ando aprendiendo el cómo medir el tráfico. Con ver las visitas de una página y evolución de visitas durante un tiempo me basta pero de momento me aclaraba más y mejor con la versión anterior de Analytics.

      En mi blog incluyo publicidad algo que otros creadores de contenido ya sean bloggers o youtubers no consideran en sus blogs o canales de YouTube ya que no es su interés ni objetivo monetizar su medio. Yo si añado publicidad de AdSense y enlaces de afiliado y no me siento mal por ello ni siento que estoy perjudicando o engañando a nadie. Como ya he dicho los ingresos no compensan pero al cabo del año me permiten comprar algún juego de la PlayStation, juegos a los no juego tanto al menos si quiero quiero seguir escribiendo en el blog.

      Como novedad desde hace unas semanas he incluido otra plataforma de publicidad, es Videoo.tv que ofrece otra forma de anuncios complementarios a los ofrecidos por AdSense, al igual que AdSense no es muy intrusiva ni molesta. En el poco tiempo que la tengo me está generando más ingresos que AdSense, he estado dejando de ganar dinero. Ha sido alrededor de duplicar ingresos de AdSense que si normalmente los de AdSense estaban entre 20 y 30€ ahora pasarán a estar entre 40 y 50€ de forma regular, lo que es una mejora muy significativa. Aún pendiente de que me hagan el primer ingreso, espero que al finalizar este mes me emitan la primera factura.

      Me contactaron los de Videoo e insertar su red publicitaria es apenas un script poco más que lo necesario para AdSense. La publicidad de Videoo que he insertado son vídeos que dependiendo del artículo he colocado a lado de la tabla de contenidos, si ese área está visible se muestra ahí el vídeo de publicidad y si no está visible el anuncio se muestra de forma flotante en la parte inferior derecha. Son anuncios en formato vídeo pero sin audio con lo que no son demasiado molestos.

      Además, cuando no se muestra un vídeo de publicidad el área del anuncio hace las funciones de carrusel de artículos lo que permite mostrar en todos los artículos artículos ya publicados que quizá le interesen al lector de contenido relacionado.

      alis

      Hace ya un tiempo que no hago ninguna modificación importante al script para instalar Arch Linux. Al sitio web le he actualizado los estilos y le he añadido un par de páginas de contenido a su sitio web.

      En cuanto a cambios ahora permite establecer puntos de montaje completamente configurables, autodetecta si el dispositivo de instalación es sda o vda según los dispositivos disponibles con lo que en máquinas virtuales es una opción menos de configuración a establecer, al sitio web también le he cambiado de Universal Analytics a Google Analytics 4, para terminar en la lista de cambios ahora permite descargar una versión en concreto del script en vez de siempre la última para aquellos usuarios que quieran una versión que sepan funciona.

      Mantener el script requiere tiempo de vez en cuando y en este caso al contrario del blog si me parece bien aceptar donaciones si a algún usuario el script le parece útil. Aún no he completado todos los pasos que requiere GitHub Sponsors para aceptar donaciones.

      Es difícil competir con arch-install, simplemente porque esta es la versión promocionada por Arch Linux. Muchos usuarios ni conocerán alis y otros que aunque la conozcan preferirán la opción recomendada por Arch Linux. Y aún así este tweet de Arcolinux tuvo 200 favoritos.

      It takes 2 minutes and 39 seconds to have a clean install of Arch Linux and Xfce4 with Btrfs - AA - https://arcolinuxiso.com/aa

      Tweet

      Artículos publicados

      Blog Bitix es un blog temático principalmente sobre programación Java y software libre aunque también es un blog personal e incluyo otro tipo de artículos como los análisis de los juegos de la PlayStation que voy jugando y desempaquetados de los productos que compro para uso personal.

      Esta es la lista de los artículos publicados este primer semestre.

      Java

      A diferencia de muchos años anteriores que escribía sobre Java ahora parte de estos artículos los puedo aplicar en el trabajo y varios de estos y seguramente varios otros que escribiré están basados en necesidades y problemas que me encuentro en el ámbito laboral. Si a mi me han sido útiles quizá las personas que los lean les resulten de interés y por eso los comparto.

      GNU/Linux

      Aún sigo usando Arch Linux y van ya casi una misma década con la misma distribución, me funciona realmente bien, no me ha dado ningún problema grave solo unos problemas menores que con la siguiente actualización del paquete problemático se solucionan.

      Apenas personalizo el escritorio pero con Starship si es algo que cambiado en la terminal ya que ofrece más y mejor información que el prompt por defecto de Bash. Chezmoi es algo que daré uso para subir los dotfiles a un repositorio de GitHub si en algún momento reinstalo el sistema o cambio de distribución.

      Juegos

      Durante estos seis meses completé los juegos de la saga Uncharted, los cuatro principales de Nathan. Al menos la historia principal ya luego conseguir el trofeo de platino requiere mucho tiempo y en muchos juegos no es que aporte mucho más y tengo otros muchos buenos juegos pendientes en la biblioteca y por comprar, me conformo con conseguir la mayor parte de los coleccionables aunque tampoco suelo conseguirlos todos. Ahora estoy ya a punto de completar otro gran juego de la consola de Sony como es God of War del que publicaré su respectivo análisis y guía. El GoW es un juegazo, por favor no me hagáis elegir entre este y The Last of Us.

      Desempaquetados y análisis de tecnología y productos

      Gracias a la colaboración con la marca de teclados mecánicos KEMOVE que publicado varios artículos de sus modelos, salvo que me contacten de nuevo ya no publicaré más por ahora. También en la lista de artículos de desempaquetado está el smartphone de Samsung Galaxy S21 FE con el que renové mi anterior y más antiguo Samsung Galaxy S6.

      Nada que ver con la tecnología renové los mecanismos eléctricos de mi casa, una pequeña chapuza casera con la que quedado contento con el resultado final teniendo en cuenta que no sabía nada de electricidad y algunos problemas relacionados resueltos.

      Otros

      Con los ingresos de publicidad suelo hacer una donación a algún proyecto de software libre que uso, no es muy grande y solo es una pequeña parte de los ingresos del blog aún así espero que contribuya a que esos proyectos sigan mejorando y publicando nuevas versiones, esta vez fue a principio de año.

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

      Picando Código

      Película: Lightyear

      junio 27, 2022 12:00

      Fui al cine a ver la película Lightyear, producida por Pixar y distribuida por Disney. Se estrenó el 17 de junio de 2022, y es un spin-off de la saga Toy Story.

      En 1995 Andy obtuvo un juguete de su película favorita, esta es esa película.

      Lightyear Cassette Futurism

      Es una película animada con elementos de aventura y mucha ciencia ficción. Buzz Lightyear es un Guardián Espacial del Comando Estelar en una misión de exploración. La aventura empieza cuando Buzz es despertado de su hibernación y debe comandar a la nave a aterrizar en un planeta habitado para explorar. Nos vamos a encontrar con especies alienígenas, muchos robots, viajes espaciales y dilatación temporal.

      Visualmente es espectacular, creo que disfruté más lo visual que el guión. Cuando voy a ver una película de Pixar, tengo expectativas muy altas con la historia. De repente por eso la historia no me pareció súper destacable. Pero de todas formas me divertí y es una buena película de los géneros que tanto me gustan, con el toque Pixar. Toy Story 3 fue seguramente la película que más me hizo llorar en un cine. Esta película no es para tanto, pero también tiene de esas escenas que Pixar acostumbra a incluir para hacernos lagrimear.

      En algunas partes me puse a comparar al personaje Buzz Lightyear de esta película con el personaje Buzz Lightyear de Toy Story basado en el personaje Buzz Lightyear de esta película. Evidentemente esto no es otra película de Toy Story, ni pretende (ni debería) serlo. Pero me convenció de que este Lightyear es el Lightyear en el que está basado el otro Lightyear. Lo bueno es que no recurre a la nostalgia o referencias y guiños constantes a su origen. Si bien es algo que se disfruta, últimamente se ha abusado con los reboots, remakes, y demás re-anglicismos. Sí hay varios diálogos que afirman “¡es el del juguete!”, pero extiende su mitología y presenta muchos personajes nuevos.

      Tengo una figura de acción de Buzz Lightyear en Toy Story, y la parte marketinera de Lightyear funcionó conmigo, porque ahora quiero una figura de acción de Buzz Lightyear de Lightyear.

      Lo que más me gustó fue la estética retrofuturista de la tecnología en la película, más específicamente cassette futurism. Es un género de retrofuturismo donde los aparatos están basados en tecnología alternativa si se hubiera mantenido la tendencia de diseño de las décadas de 1970 a 1990. Ejemplos muy claros son aquellos conceptos de computadoras y consolas Commodore 64 que publiqué hace un tiempo. Generalmente los dispositivos de almacenamiento son más mecánicos y basados en casetes, monitores CRT y una estética general mucho más atractiva (en mi opinión) que la tecnología actual.

      Esta tendencia inspira los trajes, los botones, robots, naves y demás elementos “tecnológicos” y se ven excelentes con el nivel de detalle de la animación. Pixar ha sido pionero de la animación por computadora en el cine y ha ido avanzando el género, ya en el trailer se puede apreciar la calidad del aspecto visual. A medida que pasan los años, podemos esperar mejores animaciones por parte de Pixar.

      Las imágenes a continuación muestran un poco a lo que me refiero (son todas sacadas de los tráilers). Hay mucho más en la película, y verlo en detalle animado está muy bueno. A pesar de ser un futuro donde la humanidad domina el viaje interestelar, la “Inteligencia Artificial” sigue siendo tan mala como en la actualidad. El asistente virtual I.V.A.N. se controla por la voz y es tan molesto y poco útil como los que tenemos en 2022.
      ¿Dónde quedó esta estética? ¿Por qué la perdimos? Los botones son mucho mejor que las pantallas táctiles…

      Lightyear Cassette Futurism

      Lightyear Cassette Futurism

      Lightyear Cassette Futurism

      Lightyear Cassette Futurism

      Lightyear Cassette Futurism

      Recomiendo Lightyear, y seguramente la vuelva a mirar cuando esté en Disney+. Aunque sea las escenas post-créditos, porque me enteré después que hay 3 escenas, y sólo me quedé para la primera. Tiene potencial para una secuela o dos, veremos qué tan bien le va y si deciden continuar la saga de Lightyear en el cine. Con su historia ahora un poco extendida y un montón de personajes nuevos, da para seguir contando cuentos de ciencia ficción.

      YouTube Video

      El post Película: Lightyear fue publicado originalmente en Picando Código.

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

      Blog Bitix

      Personalizar el símbolo del sistema de la línea de comandos con Starship

      junio 26, 2022 02:00

      El símbolo del sistema o prompt en la línea de comandos de la terminal precede a la introducción del comando a ejecutar. Los intérpretes de comandos o shells ofrecen un símbolo del sistema por defecto que muestran cierta información y con el formato que sus desarrolladores han elegido. Además de que cada intérprete de comandos tenga uno propio estos son bastante limitados en cuanto a personalización además de utilizar una configuración poco intuitiva. Starship es un personalizador del símbolo del sistema independiente del intérprete de comandos, que ofrece una gran cantidad de módulos para personalizar el símbolo del sistema según el directorio de trabajo actual y cuya configuración es muy intuitiva y está bien documentada.

      bash.svg

      Para los usuarios avanzados la línea de comandos sigue siendo la forma más rápida de hacer ciertas tareas y a veces es la única forma de hacerlo ya que no se dispone de la aplicación equivalente. La línea de comandos no solo no ha desaparecido con las interfaces gráficas sino que se sigue usando mucho. Con algunas aplicaciones gráficas la línea de comandos no es necesaria y hay muchas aplicaciones gráficas para multitud de necesidades pero para algunas cosas especializadas no las hay y la mejor opción es un programa de línea de comandos.

      Dada la utilidad de la línea de comandos esta se usa y se seguirá usando. En la línea de comandos un elemento destacado es el símbolo del sistema o prompt que muestra una información básica como el nombre de usuario, directorio y cierta información de estado. Hay varias utilidades para personalizar el símbolo del sistema según las preferencias del usuario.

      Contenido del artículo

      Formas de personalizar el símbolo del sistema de la línea de comandos

      La información y formato del símbolo del sistema por defecto depende del intérprete de comandos usado, bash tiene un formato diferente de zsh. Sin utilidades adicionales tanto bash como zsh permiten personalizar el símbolo del sistema cambiando la información que muestra, el formato y los colores.

      En bash el cambiar el formato del símbolo del sistema consiste en cambiar el valor de la variable de entorno PS1 en el archivo ~/.bashrc del usuario. El formato es un tanto críptico tanto para símbolos que permiten incluir los datos como el formato para los colores. Leyendo el contenido de una variable PS1 no es fácil saber como es el aspecto final del símbolo del sistema. zsh también se puede personalizar y dispone de herramientas específicas para la personalización como Oh my zsh.

      Por otro lado, Git por ejemplo ofrece una utilidad con la que personalizar el símbolo del sistema para mostrar cierta información según información del sistema, el directorio actual de trabajo contiene un repositorio Git u otro tipo de contenido.

      Aún así las personalizaciones que ofrecen tanto bash como zsh son propias de cada uno de esos intérpretes, diferentes entre sí y limitadas en cuanto a elementos de personalización. En la siguiente configuración el prompt está personalizado con la variable PS1 modificando los colores para el nombre del usuario y host además del git prompt.

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      
      #
      # ~/.bashrc
      #
      
      # If not running interactively, don't do anything
      [[ $- != *i* ]] && return
      
      alias ls='ls --color=auto'
      PS1='[\u@\h \W]\$ '
      
      #
      complete -cf sudo
      
      GIT_PS1_SHOWDIRTYSTATE="true"
      GIT_PS1_SHOWSTASHSTATE="true"
      GIT_PS1_SHOWUNTRACKEDFILES="true"
      GIT_PS1_SHOWUPSTREAM="true"
      GIT_PS1_SHOWCOLORHINTS="true"
      source ~/.git-prompt.sh
      
      PS1='[\[\033[01;34m\]\u\[\033[00m\]@\[\033[01;35m\]\h\[\033[00m\] \W]\$ '
      PROMPT_COMMAND='__git_ps1 "[\[\033[01;34m\]\u\[\033[00m\]@\[\033[01;35m\]\h\[\033[00m\] \W" "]\$ "'
      
      export EDITOR=vim
      
      export SDKMAN_DIR="/home/picodotdev/.sdkman"
      [[ -s "/home/picodotdev/.sdkman/bin/sdkman-init.sh" ]] && source "/home/picodotdev/.sdkman/bin/sdkman-init.sh"
      .bashrc-1

      Símbolo del sistema de bash

      Símbolo del sistema de bash

      El configurador del símbolo del sistema Starship

      Starship es una utilidad para configurar el símbolo del sistema fácil de instalar, sencillo de configurar, muchas opciones y elementos de configuración, moderno, tiene numerosos módulos que soportan múltiples tecnologías de las cuales mostrar información y compatible tanto con bash como zsh entre muchos otros intérpretes de comandos.

      Está escrito en el lenguaje de programación Rust que se caracteriza por ofrecer un alto rendimiento y ser eficiente, aunque la diferencia para el usuario no va a ser apreciable para el usuario.

      Starship permite aplicar misma configuración y tener el mismo símbolo del sistema independientemente del intérprete de comandos que es útil por ejemplo si se usa equipos diferentes, uno con GNU/Linux en las que generalmente utilizan por defecto el intérprete de comandos bash y otro con macOS en el que el intérprete de comandos por defecto es zsh.

      Starship

      En Arch Linux se instala con el comando del gestor de paquetes.

      1
      2
      
      $ sudo pacman -S starship
      
      
      pacman-install-starship.sh

      Configuración de Starship

      Además de ofrecer un alto grado de personalización la configuración de Starship es muy sencilla con la ayuda de su documentación para cada módulo de configuración. Dado que tiene una buena cantidad de opciones lo más rápido es partir de una configuración ya creada y adaptarla ligeramente a las necesidades o preferencias personales.

      En la sección de Presets hay varios ejemplos de configuración. Para el caso de este ejemplo parto de la configuración Pastel Powerline. La configuración de Starship consiste en un archivo de texto en formato toml, cada uno de los ejemplos de preconfiguraciones se puede descargar su archivo.

      Editar el archivo es bastante intuitivo tanto por el nombre de las variables como por su contenido, consiste en un conjunto de variables cuyos valores modifican un aspecto de la línea de comandos. La configuración consiste en cambiar los valores de las variables cuya descripción está documentada en la sección de configuración. El archivo de configuración es un archivo dotfile en la carpeta del directorio del usuario ~/.config/starship.toml.

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      
      #
      # ~/.bashrc
      #
      
      # If not running interactively, don't do anything
      [[ $- != *i* ]] && return
      
      alias ls='ls --color=auto'
      PS1='[\u@\h \W]\$ '
      
      #
      complete -cf sudo
      
      PS1='[\[\033[01;34m\]\u\[\033[00m\]@\[\033[01;35m\]\h\[\033[00m\] \W]\$ '
      
      export EDITOR=vim
      
      export SDKMAN_DIR="/home/picodotdev/.sdkman"
      [[ -s "/home/picodotdev/.sdkman/bin/sdkman-init.sh" ]] && source "/home/picodotdev/.sdkman/bin/sdkman-init.sh"
      
      eval "$(starship init bash)"
      .bashrc-2

      Este es un archivo de configuración de ejemplo en el que algunos símbolos no se muestran correctamente por faltar la fuente que los incluye. La variable format determina el formato e información del símbolo del sistema.

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      
      format = """
      [ ](bg:#000000)\
      $username\
      $hostname\
      [ ](bg:#000000 fg:#000000)\
      [](bg:#DA627D fg:#000000)\
      $directory\
      [](fg:#DA627D bg:#FCA17D)\
      $git_branch\
      $git_status\
      [](fg:#FCA17D bg:#86BBD8)\
      $java\
      [](fg:#86BBD8 bg:#06969A)\
      $docker_context\
      [](fg:#06969A bg:#000000)\
      [ ](fg:white bg:#000000)\
      """
      
      add_newline = false
      
      [username]
      show_always = true
      style_user = "blue bold"
      style_root = "red bold"
      format = '[$user]($style)'
      
      [hostname]
      ssh_only = false
      style="purple bold"
      format = '[@](bg:#000000 fg:white)[$hostname]($style)'
      
      [directory]
      style = "bg:#DA627D fg:white"
      format = "[ $path ]($style)"
      truncation_length = 1
      truncation_symbol = ""
      
      [directory.substitutions]
      "Documentos" = ""
      "Descargas" = ""
      "Música" = ""
      "Imágenes" = ""
      
      [docker_context]
      symbol = ""
      style = "bg:#06969A fg:white"
      format = '[[ $symbol $context ](bg:#06969A)]($style) $path'
      
      [git_branch]
      symbol = ""
      style = "bg:#FCA17D fg:white"
      format = '[[ $symbol $branch ](bg:#FCA17D)]($style)'
      
      [git_status]
      style = "bg:#FCA17D fg:white bold"
      format = '[[($all_status$ahead_behind )](bg:#FCA17D)]($style)'
      
      [java]
      symbol = "J"
      style = "bg:#86BBD8 fg:white bold"
      format = '[ $symbol ]($style)'
      starship.toml

      Utilizando colores el símbolo del sistema casi tiene un aspecto gráfico y al estar cada información separada por diferentes colores hace que sea fácilmente identificable.

      Símbolo del sistema personalizado con Starship

      Las siguientes capturas muestran información en el símbolo del sistema de una carpeta que es un repositorio de Git que incluye información del estado del espacio de trabajo y en otra además en que la carpeta es un proyecto en el lenguaje Java.

      Símbolo del sistema personalizado con Starship Símbolo del sistema personalizado con Starship

      Símbolo del sistema personalizado con Starship

      La variable principal format incluye el contenido y estilos del símbolo del sistema, por ejemplo el nombre del usuario y el directorio actual, hasta aquí es lo mismo que ofrecen bash y zsh por defecto, pero además permite mostrar información de estado según el contenido de del directorio de trabajo actual como Git, múltiples lenguajes de programación y tecnologías.

      Si el directorio de trabajo actual es un repositorio de Git se muestra la rama y el estado de cambios, si es una carpeta de un proyecto muestra de que tipo de proyecto es por ejemplo un proyecto de Java y la versión actual de Java soportando muchos otros tipos de proyectos y tecnologías, también puede mostrar información de Docker.

      Otra información que puede mostrar es la hora actual que permite registrar a qué hora se ha ejecutado un determinado comando en caso de revisar la sesión de línea de comandos.

      Una vez configurado Starship con Chezmoi es posible guardar este dotfile en un repositorio de Git en caso de querer aplicarlo en una nueva instalación o en otro equipo y mantener sincronizado el contenido entre varios equipos.

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

      Picando Código

      15 años de este blog

      junio 21, 2022 09:38

      Picando Código 15 años

      Hoy se cumplen 15 años desde el día en que publiqué mi primer post en el blog “Picando Código”. El blog que me viene acompañando desde que arranqué mi carrera como programador. Con 15 años de experiencia arriba, se podría pensar que tengo un montón de cosas para escribir. Pero me está costando bastante llenar este espacio en blanco para publicar algo. Estuve casi todo el día pensando qué iba a escribir acá para “celebrar” esos 15 años. Pero no se me ocurrió nada. Así que voy a hacer el ejercicio de escribir lo que se me vaya ocurriendo.

      Siento que no amerita más “repaso” de cosas como hice cuando se cumplieron 10 años. Me da la impresión de que durante la pandemia estuve haciendo puro repaso y meta-posts relacionando cosas dentro del blog en sí mismo. Qué época rara desde el 2020, se ve que hay una parte de mí que todavía no se terminó de recuperar. Por lo menos aquella pavada de 7 días en el picandoverso me mantenía un poco ocupado y me daba algo más para hacer en épocas de encierro, pero ahora me parece eso: ‘una pavada’. Al final empecé a hacer repasos de nuevo…

      Últimamente vengo volcando parte de la energía creativa que usaba para escribir en dibujar. Es algo que siempre me gustó pero encontré mecanismos para hacerlo más un hobby regular y explotarlo más. De repente podría relacionarlo más con el blog, como hice alguna vez, escribiendo algo acompañado de un dibujo. Cada tanto publico dibujos en Twitter. Dibujar me entretiene bastante y como todo, con la práctica voy mejorando. Además me mantiene lejos de una pantalla (excepto para buscar referencias visuales). Creo que técnicamente ya me podría llamar “artista profesional”, porque con un dibujo reciente, una persona me envió dinero para mandarle una versión escaneada de alta resolución para imprimir. Prometo publicar algún dibujo acá pronto.

      Hace poco tengo un par de ideas para cosas que quiero escribir y publicar. Pero me ha costado sentarme en la computadora a escribir, por más que vengo fermentando las ideas en la cabeza. No ayuda que es verano en Escocia y tengo que aprovechar los pocos meses de sol y calor y guardar energía para la oscuridad y el frío del invierno.

      De todas formas los 15 años no son un hito en particular, capaz que ando más inspirado para escribir a los 16 o 17. En el peor de los casos, habrá que esperar a los 20…

      El post 15 años de este blog fue publicado originalmente en Picando Código.

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

      Picando Código

      Cómics: Kickstarter del 4to número de Morgan’s Organs, la aventura anatómicamente incorrecta

      junio 20, 2022 05:00

      Vuelve el cómic en el que Morgan es tan protagonista como sus órganos internos.  Llamados “Organautas”, forman una comunidad liderada por el cerebro y cada uno tiene una personalidad propia, generalmente operando en contra de los intereses de Morgan. En 2016, Daniel Brodie, junto a Robert Jennex (ilustrador) publicaron la primera campaña en Kickstarter para el libro 1. Desde entonces han tenido un total de 3 campañas exitosas publicando el cómic de Morgan’s Organs. Las historias son autocontenidas y no es necesario preocuparse de la continuidad para disfrutarlas.

      Morgan's Organs #4

      En el primer número de Morgan’s Organs, las dos “cabezas” del cuerpo de Morgan se enfrentan para controlar la toma de sus decisiones, mientras Morgan lucha con la presión de una temporada sexual complicada.

      En el segundo número de Morgan’s Organs, Morgan traga algo que no debería haber tragado y vemos las consecuencias en los Organautas a lo que se va moviendo por su aparato digestivo.

      En el tercer libro, Morgan se despierta de una borrachera sin memorias, mientras que los Organautas investigan qué pasó la noche anterior.

      Para el cuarto libro, la historia se centra en el viaje del esperma. “Nunca hubieras pensado que estos pequeños tipos tenían tanto para enseñarnos sobre apreciar la vida, porque es un momento tan efímero y preciado. Va a ser un viaje emocional sobre amistad, gloria y pérdida”.  El pasado 17 de junio se publicó la campaña en Kickstarter para publicar el cuarto libro. En la campaña podemos ver algunas páginas del cómic ya terminadas.

      Morgan’s Organs es bastante entretenido y ha sido hasta ahora de mis mejores experiencias con Kickstarter (he tenido varias de las otras). Sus creadores son muy responsables y cumplidores con los tiempos, y con 3 Kickstarters exitosos hasta ahora, no creo que la cosa cambie en esta ocasión. En la campaña dice que el libro ya tiene más del 75% terminado, y planean entregar todas las recompensas en Setiembre. Como suele pasar en estos crowdfunding, hay distintos tipos de niveles para los cuales podemos “invertir”, obteniendo recompensas distintas acorde a la cantidad de dinero que demos.

      El cómic es bastante entretenido y lo vengo recomendando desde sus inicios. En Kickstarter está la opción de obtener los números 1 al 3 también, para alguien que quiera ponerse al día. La idea del autor es que la historia se convierta en una serie animada de televisión. En 2020 tuvo la oportunidad de presentarlo a productores ejecutivos que habían trabajado en series como Big Mouth, Rick & Morty, y Bojack Horseman. Me imagino que Morgan’s Organs iría muy bien con este grupo de series animadas para adultos. Potencialmente podamos ver a Morgan y sus Organautas en la televisión en unos años, habrá que ver y esperar.

      Visita Morgan’s Organs en Kickstarter

      El post Cómics: Kickstarter del 4to número de Morgan’s Organs, la aventura anatómicamente incorrecta fue publicado originalmente en Picando Código.

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

      Navegapolis

      NFT, ¿título de propiedad o papel mojado?

      junio 19, 2022 03:02

      —Mira, tengo el contrato de esa casa.
      —¡Es fantástica! ¿La has comprado o la has alquilado?
      —No sé. Creo que la he comprado.
      —¿En el contrato qué pone?
      —Nada.

      Aunque parece imposible, esta es la situación la habitual al comprar NFTs de obras creativas:

      —Mira tengo el NFT de ese dibujo.
      —¡Es estupendo! ¿Podrás ponerlo en camisetas y venderlas?
      —No sé. Supongo que sí.
      —¿En el NFT qué pone?
      —Nada.

      Los NFTs para vender dibujos, canciones, vídeos, libros o incluso sus derechos, se están empleando como títulos de propiedad electrónicos. Títulos basados en un registro tecnológico, descentralizado sobre una cadena de bloques. Títulos capaces de ejecutar acciones en cada transacción, como transferir al autor royalties de forma automática.
      Sin duda abren muchas posibilidades, pero si no pueden determinar qué es lo que venden, se quedan en papel mojado.

      Las plataformas de videojuegos en línea (gaming) empezaron a usarlos para ofrecer a los jugadores diferentes activos virtuales: amuletos, armas, coleccionables y, en general, elementos desarrollados y empleados por la propia plataforma.

      El éxito que han alcanzado en el “gaming” y el coleccionismo digital ha extendido su uso. Ya se emplean para ostentar la propiedad, no sólo de bienes virtuales, sino también físicos como inmuebles u obras creativas, independientemente de si se trata de la propiedad plena, dividida o de algún derecho.

      El problema que están encontrando es que las reglas para reivindicar la propiedad de un activo virtual en la propia plataforma que lo ha creado se quedan cortas cuando tratan de hacer lo mismo con bienes —tangibles o intangibles— del mundo real.
      En estos casos, para que los NFTs funcionen como títulos de propiedad, es necesario que la información que incluyen vaya más allá de su propio identificador y de la cartera electrónica del propietario. Tienen además que detallar las características que el derecho de propiedad considera para el tipo de bien al que representan.

      En el caso de obras creativas, de creaciones con derechos de autor, los NFTs deben indicar qué derechos adquiere el comprador y bajo qué condiciones.

      No se trata de comprar el NFT de una fotografía —por ejemplo— sino el NFT de la licencia de uso de esa fotografía. El NFT podrá tendrá que indicar si se trata de una licencia exclusiva o no, si permite la copia y su distribución, si está limitada en el tiempo o en determinados canales, etc.

      La entrada NFT, ¿título de propiedad o papel mojado? se publicó primero en Navegápolis.

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

      Arragonán

      Píldora. Desplegar un monorepo en Heroku

      junio 13, 2022 12:00

      Por defecto cuando queremos desplegar en Heroku, nos encontramos una relación 1:1 entre repositorio de git y aplicación, ya que se espera tener un Procfile en el directorio raíz de tu proyecto con el tipo de procesos y comandos que arrancan la aplicación.

      Pero con Heroku Multi Procfile buildpack tenemos la posibilidad de cambiar ese comportamiento, y poder tener varias aplicaciones en un sólo repositorio. Las instrucciones para ello:

      Antes asumiremos que tenemos ya una aplicación en heroku en un git remote con nombre heroku, que hemos movido la primera aplicación del directorio raíz a my-application y la nueva la hemos creado en my-new-application.

      Instalamos el buildpack en local

      $ heroku create --buildpack https://github.com/heroku/heroku-buildpack-multi-procfile.git

      En la aplicación de heroku existente añadimos el buildpack

      $ heroku buildpacks:add -a my-application heroku-community/multi-procfile

      Le asignamos el path del fichero Procfile que queramos asignar a la variable de entorno PROCFILE

      $ heroku config:set -a my-application PROCFILE=my-application/Procfile

      Lo pusheamos a heroku

      $ git push heroku

      Para la otra aplicación, la creamos en heroku

      $ heroku create -a my-new-application

      Añadimos el buildpack en la aplicación de heroku recién creada

      $ heroku buildpacks:add -a my-new-application heroku-community/multi-procfile

      Le asignamos el path del fichero Procfile que queramos asignar a la variable de entorno PROCFILE

      $ heroku config:set -a my-new-application PROCFILE=my-new-application/Procfile

      Añadimos el repositorio git remoto heroku-new

      $ git remote add heroku-new https://git.heroku.com/my-new-application.git

      Y lo pusheamos a heroku

      $ git push heroku-new

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

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

      Open Space, para un roto o para un descosido

      abril 28, 2022 07:03

      NOTA: Estoy escribiendo la guia de facilitación de Open Space. Hemos hablado varias veces aquí ya de los Open Space como un formato increible para la organización y facilitación de conferencias. En Agile-Spain hemos organizado ya tres a nivel nacional, y han surgido multitud de pequeños "opens" para tratar muchos temas alrededor del agilismo. Si no sabes qué es un Open Space, echa un ojo a esta

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

      Header Files

      Extendiendo el autocompletado en Bash

      abril 26, 2022 06:45

      Introducción

      Personalmente creo que hay cuatro acciones de teclado que consumen el 70% de mi tiempo en una terminal: Enter, Control-C, Arriba y Tab. Las dos primeras para iniciar y parar comandos, y las dos últimas para agilizar la escritura, bien sea buscando en el historial o bien completando el nombre del comando actual.

      Respecto al autocompletado, algunas shell, como Bash, permiten además hacer un autocompletado contextual, es decir, que una vez introducido el nombre del comando que se quiere ejecutar el motor de autocompletado ofrecerá las opciones pertinentes en base a dicho comando y a las opciones previamente seleccionadas. Esto no sólo ahorra tiempo de escritura, sino que además sirve de complemento a la ayuda del propio comando.

      En esta entrada expondremos cómo crear un script de autocompletado propia, de forma que podamos incluirlo en nuestros proyectos. Aunque me centraré en la shell Bash, esta funcionalidad también es posible para otras: en cmd (Windows) mediante clink (usando Lua), PowerShell mediante funciones TabExpansion, zsh mediante zsh-autocomplete (aunque en este caso habría que extender el proyecto base).

      Pre-requisitos

      Además de tener Bash como shell activa, necesitaremos el paquete bash-completion y activarlo en nuestra sesión. Podemos seguir las instrucciones listadas acá.

      Diseñando el script

      Comenzaremos detallando el comando al que queremos dar soporte, para luego mostrar y explicar el script en cuestión.

      Sintaxis del comando

      Vamos a suponer que nuestro comando se llama headerfiles y tiene la siguiente sintaxis:

      headerfiles [-h --help -j -f <nombre_de_fichero> -e [-x|-p] -o [slow|fast]]
      

      Particularidades:

      • -x y -p sólo están disponible si -e ha sido definido previamente.
      • -x y -p son mutuamente excluyentes.
      • -f <nombre_de_fichero> puede ser especificado varias veces.
      • -j -e no presentan problems si se indican varias veces, pero es equivalente a que sólo se indicasen una vez.
      • -o sólo puede ser especificado una vez.
      • -h --help tienen prioridad sobre cualquier otra opción.

      El script

      El primer paso será crear un fichero para guardar las funciones del script. Personalmente los suelo guardar en una ruta del tipo <proyecto>/scripts/autocomplete/headerfiles.bash, pero queda a vuestra discreción.

      Hay, como es imaginable, varias formas de programar este autocompletado personalizado, pero mostraré la que a mí particurmente me resulta más sencilla mentalmente, aunque no necesariamente sea la más eficiente: definir una función que fije la variable de entorno COMPREPLY. y pasar dicha función como argumento de complete, junto con el nombre de nuestro comando (Bash usará este nombre para determinar si debe llamar a nuestro autocompletado particular o a algún otro). La variable COMPREPLY es usada por complete como la lista de opciones que se mostrarán. Como ayuda, usaremos el comando compgen para generar, de forma amigable, dicha lista de opciones.

      Presento el script correspondiente a la sintaxis antes mencionada y luego procedo a su explicación:

      #/usr/bin/env bash
      
      # Prints 1 if the given option has already been specified, 0 otherwise
      has_option() {
          for i in "${COMP_WORDS[@]}"; do
              if [[ "$i" == "$1" ]]; then
                  echo "1"
                  return
              fi
          done
      
          echo "0"
      }
      
      # Function to be called when auto-completing
      _headerfiles() {
          COMPREPLY=()
      
          # These options have the highest precedence, so ignore any other if they've been specified
          if [[ "$(has_option -h)" == "1" || "$(has_option --help)" == "1" ]]; then
              return 0
          fi
      
          local cur=${COMP_WORDS[COMP_CWORD]}
          local prev=${COMP_WORDS[COMP_CWORD - 1]}
      
          case $prev in
              # Options with additional arguments
              "-f") COMPREPLY=(`compgen -f -- $cur`) ;;
              "-o") COMPREPLY=(`compgen -W "slow fast" -- $cur`) ;;
              # Any other option
              *)
                  # This variable will contain the list of available options
                  local AVAILABLE_OPTIONS=()
      
                  # List of supported options that can be used only once
                  local ALL_ONCE_OPTIONS=("-e -o -h --help")
      
                  # Add dependant options
                  if [[ "$(has_option -e)" == "1" ]]; then
                      # Mutually exclusive options
                      # Do not remove current word in shell to allow finishing its autocompletion
                      if [[ "$(has_option -x)" == "1" ]]; then
                          ALL_ONCE_OPTIONS=("${ALL_ONCE_OPTIONS[0]} -x")
                      elif [[ "$(has_option -p)" == "1" ]]; then
                          ALL_ONCE_OPTIONS=("${ALL_ONCE_OPTIONS[0]} -p")
                      else
                          ALL_ONCE_OPTIONS=("${ALL_ONCE_OPTIONS[0]} -x -p")
                      fi
                  fi
      
                  # Most options are allowed only once, so remove the ones already in use,
                  # but do not remove current word in shell to allow finishing its autocompletion
                  local PREV_COMP_WORDS=("${COMP_WORDS[@]}")
                  unset "PREV_COMP_WORDS[-1]"
                  for i in ${ALL_ONCE_OPTIONS}; do
                      for j in "${PREV_COMP_WORDS[@]}"; do
                          if [[ "$i" == "$j" ]]; then
                              continue 2
                          fi
                      done
                      AVAILABLE_OPTIONS+=("$i")
                  done
      
                  # The -f option can be used several times
                  AVAILABLE_OPTIONS=("${AVAILABLE_OPTIONS[*]} -f")
      
                  COMPREPLY=(`compgen -W "${AVAILABLE_OPTIONS[*]}" -- $cur`)
                  ;;
          esac
      }
      
      complete -F _headerfiles headerfiles
      

      Como notas particulares:

      • Las opciones de máxima prioridad, aquéllas que cuando se especifican dejan sin efecto a las demás, se procesan de primero y con un early return.
      • Las opciones con argumentos adicionales se procesan de forma independiente, pudiendo generar un autocompletado específico para dicha opción:
        • compgen -f: nombres de ficheros.
        • compgen -d: nombres de directorios.
        • compgen -W "...": una lista de palabras (nótese que éste es el mismo método empleado en otras partes del script).
        • La opción anterior puede usarse en conjunto con una función que extraiga los términos disponibles (de un fichero, de otro comando, etc). Por ejemplo, Git lo hace cuando detecta una línea tipo git checkout, entonces el siguiente autocompletado son nombres de las ramas disponibles, que son extraídas de una consulta a git branch -a.
      • Cuando hay que listar las opciones disponibles, primero se enumeran las que se pueden elegir una única vez y se filtran para quitar las ya introducidas. Posteriormente se añaden las que pueden repetirse

      Activando el script de autocompletado

      Para activarlo bash con que carguemos el script: source /path/to/script.bash. Además, podemos agregar esta línea en nuestro .bashrc para que esté disponible en cualquier nueva sesión Bash que ejecutemos.

      Si nuestro proyecto incluye un comando de instalación o un paquete, deberemos añadir el script en el mismo e instalarlo en /usr/share/bash-completion/completions/.

      Conclusión

      Hemos estudiado cómo extender el autocompletado de Bash con algunas de las opciones más frecuentes. Otras combinaciones más complicadas pueden resolverse con una extensión de éstas (por ejemplo, el caso de que la lista de subvalores de una opción deba ser extraída de un fichero o comando). Para más información podemos consultar la documentación oficial.

      » 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