Acerca de Dani

Soy un ingeniero de software actualmente trabajando como desarrollador web que vive en la zona del Valle del Henares, una comarca situada al este de Madrid, España. Me interesan las buenas prácticas en el desarrollo de aplicaciones, el código bien testado, la usabilidad y la accesibilidad del software. En internet, te enseño a programar a través de mi canal de YouTube, makigas.

¿Cómo te describirías?

Minientrada

No quisiera ofender a nadie, pero a esta pregunta que me salió el otro día respondiendo al survey de Stack Overflow respondí «No lo sé». Supongo que preguntar estas cosas son las costumbres de los estadounidenses y tendré que respetarlas.

El futuro era esto

Estado

Hace poco intentando resolver un problema en JavaScript*, puse en Google un par de palabras para describir mi problema esperando encontrar respuestas en Stack Overflow.

El primer enlace apuntaba a un blog de Medium. No lo pude leer, porque la página me pedía registro.

El segundo enlace apuntaba a otro blog de Medium. Tampoco lo pude leer, porque la página me volvía a pedir registro.

El tercer enlace apuntaba a otro blog de Medium. Y no, no lo pude leer tampoco, porque la página otra vez insistía en pedir registro.

Dejando a un lado que este tipo de páginas probablemente vulnere las normas de Google, a saber qué otros sitios web algún año se quitarán la careta después de convertirse en silos en los que la gente vuelca contenido.

* Es casualidad que intente conectar JavaScript con Medium. Creo.

Consideraciones sobre el volcado de posts

Minientrada

A raíz del volcado de posts que cargué el otro día estoy considerando próximos datasets a importar. Exports procedentes de la GDPR, viejas entradas de blog sacadas de Wayback Archive, incluso tal vez puede que crosspost de cosas cargadas a YouTube o Twitter (algo que llevo años persiguiendo).

Algunas consideraciones técnicas que he aprendido para la próxima:

  • Es mejor usar un entorno de staging mientras se hacen pruebas para no ensuciar el sitio web, porque lo más posible es que falle al principio.
  • Por lo tanto, es mejor ir de poco en poco, y no intentar importar un dataset muy grande hasta que no se ensaye con algo más pequeño que se pueda borrar fácilmente si se hace mal.
  • Por si hay que borrar, es mejor ponerles a los posts importados una etiqueta nueva para poder filtrar fácilmente posts con esa etiqueta y borrar todo. En mi caso, esa etiqueta ha sido hn-import.
  • Si el blog lo alojas por tu cuenta, no tienes que dar parte del API Rate Limit a nadie, pero corres el riesgo de causarte un ataque de denegación de servicio a ti mismo. Como casi hago, de hecho, porque mi código JavaScript intentó lanzar las 49 peticiones HTTP POST a la vez.
  • Por asociación de ideas, mejor apagar los hooks externos que se llaman al crear posts mientras se estén importando cosas. No pingbacks, no trackbacks, no webmentions, no ActivityPub. (Aparte que muchos de estos posts tienen unos cuantos años y no tiene mucho sentido generar notificaciones por esto.)
  • El feed RSS va a sufrir.

El problema, como ya he dicho alguna vez, son los títulos. Muchas redes sociales no usan títulos en sus publicaciones, pero algo hay que poner para que la sindicación por RSS o al usar temas y widgets de WordPress que traten de mostrar el título de un post, tenga o no, puedan mostrar algo distinto a (sin título).

Re: Lista de deseos para la WWDC21

Minientrada

Parece que he acertado unas cuantas.

Espero seriamente que iPadOS 15 sea una versión cargada de mejoras para los power users.

Aquí no puedo dar el punto completo. He mirado las notas de la previa y la mayoría de funciones que veo son para consumo, no para creación. Poder integrar mejor una segunda pantalla hubiese estado bien que lo que se ofrece actualmente podría estar mejor…

No obstante, Swift Playgrounds va a pasar de ser una aplicación para “aprender a programar” a ser un entorno donde se va a poder programar de verdad (en Swift) y hasta enviar apps directamente a la AppStore desde iPadOS. Medio punto mientras le hago un seguimiento a esto.

Una mejor forma de lanzar aplicaciones en iPad.

Con lo del cajón de aplicaciones y el nuevo menú para la multitarea esto va a ser una realidad, o al menos mejor que lo que hay ahora mismo. También la llegada a iPadOS del directorio de aplicaciones, para poder eliminar iconos inútiles de la pantalla de inicio o del dock sin recurrir al viejo truco de empujarlos en una carpeta.

En iPadOS e iOS, más atajos para las opciones.

Opinaré sobre esto cuando vea los nuevos atajos. El nuevo modo Focus (que ya veremos cómo se llama en español) podría facilitar una forma flexible de configurar el dispositivo de distintas formas según la hora y el lugar. Es el caso de uso que más se le parece (poder silenciar el móvil en algunos momentos, por ejemplo), por lo que habrá que prestar atención a esto.

Ojalá una versión de Atajos para macOS.

A la orden. Aunque de poco me va a servir porque esta va a ser la primera versión de macOS que no se podrá instalar en mi mid-2014. (No es que me haga mucha falta…)

Lista de deseos para la WWDC21

Minientrada

Resulta que la WWDC21 es hoy. La verdad es que yo ya estaba acostumbrado a que estos eventos cayesen en martes, pero… ya.

Admito que últimamente no le presto mucha atención a las WWDC y conferencias de este estilo. Creo que estaban mejor con público, aunque tengo la ligera sospecha de que con lo que se ahorra Apple en concepto de organizar un evento con público*, no creo que regresen cuando pase la pandemia.

Sin embargo, me gusta luego leer titulares y estos son los titulares que me gustaría leer:

  • Apple presentó hace poco un iPad equipado con un procesador M1, que es su procesador de ordenadores. Hasta ahora siempre tenían procesadores A, que son los de la serie móvil. Tener un procesador tan potente sin exprimir suena mal, por lo que espero seriamente que iPadOS 15 sea una versión cargada de mejoras para los power users.
  • Una mejor forma de lanzar aplicaciones en iPad. Ahora mismo, para exprimir al máximo la multitarea y las múltiples aplicaciones a la vez, es necesario tener todas las apps (o al menos las más esenciales) en el dock, porque es el único punto de partida desde el cual se puede arrastrar un icono de aplicación sobre una aplicación abierta para iniciar un modo de pantalla dividida.
  • En iPadOS e iOS, más atajos para las opciones. La mayoría de mis ideas para crear atajos se frustran cuando veo que se trata de usar una opción dentro de los Ajustes del sistema que no está expuesta en Atajos.
  • Ojalá una versión de Atajos para macOS. Existe Automator, pero las aplicaciones de terceros nunca le han hecho mucho caso.

(*) Juraría haber leído esto hace poco, pero ahora no encuentro los enlaces que lo prueben.

Notas sobre el conjunto de Mandelbrot

Minientrada

Ayer cerré un stream en Twitch en el que intenté programar la típica representación gráfica del conjunto de Mandelbrot. No lo terminé porque se me alargó, pero lo continuaré. Dejo aquí algunas notas para cuando haga la segunda parte.

El conjunto de Mandelbrot es el conjunto de números complejos donde se cumple que la evolución de la serie definida por la función f(c, n) = f(c, n-1)^2 + c, siendo f(c, 0) = 0, no tiende al infinito. Por ejemplo, para c=1 se obtiene la serie 0,1,2,5,26…, no acotada, pero para c=-1 se obtiene la serie 0,-1,0,-1,…, que sí está acotada. (Por supuesto, c=1 y c=-1 son ejemplos muy simples, pero esta fórmula se usará con números con parte imaginaria como 0.2265+0.331i.)

Para facilitar las cosas, lo normal es asumir que si la magnitud del número complejo supera en algún punto de la serie el valor 4, entonces con seguridad no se acota. Como no podemos pedirle al ordenador precisión infinita, si después de un número máximo de iteraciones sigue sin tender al infinito, podemos asumir que sí se acota.

O sea, que al final en un programa de ordenador repetiremos la función hasta que se superen 50, 100, 1000 iteraciones (lo cual nos diría que está acotada), o hasta obtener algún valor con un absoluto mayor a 4, lo que nos deja interrumpir la ejecución asumiendo que no se acota. Cuantas más iteraciones apliquemos, más precisa será la evaluación, ya que puede ocurrir que una serie para un complejo tarde más tiempo en divergir, aunque también tomará más tiempo.

En cuanto a la clásica imagen del fractal generado a partir del conjunto de Mandelbrot, que seguramente muchos habremos visto alguna vez, lo que vemos es la representación en un sistema de coordenadas 2D del valor de esta función para todos los números complejos. El eje X representa la parte real del complejo y el eje Y, la parte imaginaria.

En el programa de ordenador generaríamos la imagen transformando del sistema de coordenadas de la imagen (por ejemplo píxeles del (0,0) al (640,480)) a una interpolación más aceptable en el rango de los complejos que vayamos a comprobar (como (-1,-1) a (1,1), aunque podríamos reducir el área para hacer zoom), y luego consultando si ese número complejo está en el conjunto o no. Si está en el conjunto, lo podemos representar de negro. Si no está en el conjunto, lo típico es crear algún tipo de paleta de colores para representar con un color diferente aquellos complejos que escapen antes al infinito de aquellos que escapan más tarde.

 Representación del conjunto de Mandelbrot
La clásica foto del conjunto de Mandelbrot tomada de Wikipedia.

Invirtiendo esferas

Enlace

Las recomendaciones de YouTube me han lanzado este vídeo que me deja tan fascinado como confuso sobre cómo se pueden invertir círculos y esferas, y toda la matemática y condiciones que hay detrás de este proceso.

(No, no puedes darle la vuelta como un calcetín a un balón de baloncesto; se conoce que esto sólo se puede hacer con esferas hipotéticas hechas de un material hipotético que puede atravesarse a sí mismo.)

El vídeo es de 1994 y está subido a YouTube en 2011, y debe estar en esa lista que se hace el algoritmo de YouTube cada mes de «vídeos viejos que deben resurgir en el feed de recomendados sin razón alguna»…

Importando de redes sociales con XML-RPC

Minientrada

Una de las cosas bonitas de la GDPR es que casi obliga a las redes sociales y sitios similares a tener un sistema de exportado de datos. Y casi siempre lo hacen con algún formato estructurado como CSV, JSON o XML, fácil de procesar por un ordenador.

Paralelamente, WordPress tiene el viejo confiable XML-RPC para crear posts de forma programática. Si no tienes mucha idea, recomiendan cerrar ese endpoint al exterior para evitar problemas. Pero en verdad, si sabes protegerlo, resulta muy práctico para crear posts a golpe de petición HTTP. (En teoría existe la API REST, pero bueno…)

Con la ayuda de un cliente XML-RPC para WordPress que hay en NPM y de la API de Hacker News, hice en Node.js un script de un solo uso que crease una entrada por cada comentario y enlace enviado para enlazar hacia el comentario o la historia, siguiendo el modelo de sindicación PESOS de IndieWeb (Publish Elsewhere, Syndicate to Own Site). Le he puesto la etiqueta hn-import a la colección. ¿Cuál será el próximo archivo que importe?

En sí la librería no es muy complicada de utilizar. Una vez tienes un cliente conectado es muy fácil chutarle un array de posts a crear (por ejemplo, procesar fila a fila un CSV o item a item un JSON o un XML). Primero se crea un cliente:

const { createClient } = require("wordpress")

const client = createClient({
  url: "https://example.com",
  username: "mi user",
  password: "mi password"
})

Luego definiendo el payload. Aquí es donde encuentro más cómodo crear un objeto JSON que declarar todo el chorizo XML de XML-RPC:

const payload = {
  title: "El título de mi entrada",
  content: `
    <p>El contenido de mi entrada.</p>
    <blockquote>Aceptamos HTML.</blockquote>
    <p><a href="https://www.example.com">Y enlaces</a></p>
  `.trim(),
  status: 'publish', // podría ser 'draft' o 'private'
  termNames: {
    category: ['Categoría'],
    post_tag: ['tag 1', 'tag 2', 'tag 3'],
  },
  date: '2006-01-02 15:04:05',
  format: 'link' // podría ser 'aside', 'status', 'photo', ...
}

Y ya postear usando newPost. La librería es previa a promesas así que su único punto malo es que está orientada a callbacks.

client.newPost(payload, (err, id) => {
  if (err) {
    console.error(err)
  } else {
    console.log(`ID del nuevo post: ${id}`)
  }
})

Borrando ramas locales de Git que ya no existen en remoto

Minientrada

En la mayoría de mis repositorios Git, correr git branch suele suponer abrir un cubo de basura bien grande. Cuando una rama de Git desaparece en el remoto (por ejemplo, en GitHub cuando se borra desde la interfaz web automáticamente), luego te tienes que acordar en local de borrar también tu rama. De lo contrario, vas a acabar con ramas stale que son aquellas de las que se hizo git push para abrir PR y que quedan ahí.

Una forma de identificar estas ramas es hacer un git fetch --prune, manteniendo ese prune para que se ocupe de detectar qué ramas han desaparecido del remoto, seguido de git branch -vv | grep gone. En el modo verbose de branch, las ramas locales que hacen tracking de un remoto que ya no está se identifican porque aparece [gone] en su línea de terminal. Por lo que esta pipeline lista únicamente esas ramas locales que han desaparecido del repositorio remoto.

Cortando la primera columna (mejor con awk '{ print $1 }' aunque con cut también se pueda hacer), puedes listar únicamente los nombres de las ramas. Y si estás de acuerdo con la salida de git branch -vv | grep gone | awk '{ print $1 }', (y sólo si estás de acuerdo, porque ya sabes, no refunds), entonces puedes envolver todo en un git branch -D $(git branch -vv | grep gone | awk '{ print $1 }') para cargarte todas esas ramas de un plumazo.

Follow-up sobre el portapapeles de Vim

Minientrada

Compartí por el Discord de mi comunidad de YouTube mi post del otro día en el que compartía un atajo para copiar y pegar de Vim al portapapeles. Aparentemente no a todo el mundo le funcionó a la primera.

Para poder utilizar compartir el portapapeles, Vim tiene que haber sido compilado con soporte para el mismo. Esto se puede saber ejecutando vim --version y comprobando que en la salida del comando aparece la opción +clipboard (tiene que ser un +, porque un -clipoboard precisamente avisa que no). Las versiones de Vim que trae Homebrew en macOS lo suelen tener. En otros UNIX y en GNU/Linux, es posible que haya que cambiar el paquete vim por vim-x11 o por una versión de Vim más completa.

Probando en mi instalación de FreeBSD con X11, funciona tanto para el portapapeles CLIPBOARD ("+) como para el portapapeles PRIMARY (el del botón central del ratón, "*).