Sobre flojera e invitaciones de Zoom

Una de las «virtudes» de todo buen programador es la flojera. Y es que los programadores, al encontrarse con una tarea repetitiva o lenta, tienden a preguntarse: «¿Cómo podría hacer esto más automático/rápido/eficiente/barato/divertido?» Tenemos muy poca tolerancia a la ineficiencia.

Se los ilustro con un caso mío reciente.

Para las reuniones de mi iglesia usamos Zoom. Yo me encargo de agendar y enviar las invitaciones para cada reunión (no usamos reuniones recurrentes).

Zoom genera un texto que puedes copiar y pegar para compartir con otros todos los datos pertinentes de la reunión, así:

Mi cuenta de Zoom está en inglés, si quisiera generarla en español tendría que cambiar el lenguaje a toda mi cuenta. Por otro lado, hay ciertos detalles, como la presentación de la fecha y la hora que prefiero cambiar. Como esto es algo que hago 5 veces o más a la semana, decidí poner patas a la obra.

Siendo flojo, ni siquiera miré la API de Zoom. Zoom te permite copiar con un solo click el texto de la invitación. Mi estrategia fue trabajar sobre la base de tal texto.

Programé un script que extrae los datos pertinentes (regexp magic!) y escribe a STDOUT la invitación en español y con el formato que quiero.

Siguiendo la filosofía Unix («Expect the output of every program to become the input to another») hice un segundo script que lee el portapapeles, lo envía al script «traductor» y reescribe el portapapeles con la nueva invitación.

Mi operación final es:

  • Copiar la invitación desde Zoom al portapapeles (un click).
  • Ejecutar mi script.
  • Pegar la invitación al grupo de WhatsApp de mi iglesia.

Sé que podría automatizarse todavía más, pero me da flojera.

Extrayendo un rango de texto de un fichero grande

Necesitaba extraer un rango de líneas de un fichero de texto de varios gigabytes. Hacerlo a través de un editor de texto era impráctico. Mi solución fue usar sed:

sed -n 'INICIO,FINp;(FIN+1)q' FICHERO > NUEVO_FICHERO

Por ejemplo, para extraer desde la línea 10 hasta la línea 500 del fichero gigante.txt y guardarlo en extracto.txt:

sed -n '10,500p;501q' gigante.txt > extracto.txt

Devorando el manual de Laravel

Dediqué mi tiempo de lectura para devorar el manual de Laravel; me lo leí de principio a fin con el fin de tener un entendimiento en anchura (mas no en profundidad) del framework.

Lo leí en mi Kindle Paperwhite usando la versión Mobi de este repositorio: https://github.com/driade/laravel-book que genera ficheros ePub, Mobi y PDF actualizados del manual.

Tengo pendiente escribir acerca de las cosas que me gustan de Laravel, luego de haber escrito lo que no me gustó de Laravel ya tiempo atrás.

Lo que no me gusta de Laravel

He estado leyendo, probando y viendo un poco de cerca Laravel, buscando agilizar los desarrollos que hacemos en Nodos.

Estas son algunas cosas que no me han gustado de Laravel. Quizás en algunas esté equivocado, dado que sólo he construido algo pequeño con el framework para tener un hands-on experience y no tengo un conocimiento a profundidad de éste. Corríjanme si me equivoco.

NOTA: Al momento que escribo esto, la versión más reciente de Laravel es 5.6.

La magia

Este es un código de ejemplo copiado del manual de Laravel acerca de validación:

/**
 * Store a new blog post.
 *
 * @param  Request  $request
 * @return Response
 */
public function store(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
    ]);

    // The blog post is valid...
}

Lo que se puede ver es que hay una llamada a $request->validate().

Lo que no se ve es que si validate() encuentra contenido inválido, arroja una Excepción y se redirige automáticamente a la página anterior (con toda otra funcionalidad detrás de cámaras para preparar los errores y la persistencia de los valores antiguos).

Este comportamiento «mágico» no es visible ni intuitivo en el código, violando el Principle of Least Surprise. Solamente alguien con conocimientos de Laravel sabe lo que va a suceder.

Por otro lado, los Exceptions están siendo usados para controlar el flujo de la aplicación, lo cual es una mala práctica. Citando a Philip Brown:

An exception is basically an exceptional circumstance that is often unrecoverable from. This means something went wrong and we can’t proceed with running the application because the program is unable to carry on executing.

For example, I see a lot of code where the developer is using exceptions to control the flow of logic.

Exceptions should only be used in exceptional circumstances and therefore should be used sparingly.

Los famosos «Façades»

Mathias Verraes lo sabe decir mejor:

Laravel’s Facades have global state, which is precisely the thing you *shouldn’t* do. It is bad design and should be deprecated. They are nothing more than an elaborate $_GLOBALS.
(And they are a misnomer, as they are not Facades in the OOP meaning.)

Los formularios

Zend Framework 2 y 3 tienen Forms, que son colecciones de Form Elements con validación. Puedes crear nuevas clases de Form Elements como por ejemplo, «DNI» que incluye validadores, filtros, atributos, etc.
Laravel no tiene un concepto similar, estas funcionalidades están dispersas. Menos que eso, los helpers para renderizar los elementos de formulario fueron retirados del framework. No hay una base sobre la cual crear elementos reutilizables.

Service Container y PSR-11

Debido a requerimientos de clientes, en Nodos seguiremos usando tanto Zend Framework como Laravel. Revisando la interoperabilidad de Laravel en relación a su Service Container, veo que no se ajusta al PSR-11 — tampoco al ahora obsoleto container-interop.

Quizás tengamos que usar zend-servicemanager o algún otro Container PSR-11 para los Layers framework-agnostic.

Coda

Sobre el tema de la magia, cabe mencionar lo obvio: todo framework, por definición, trae consigo cierta medida de magia. Desde Rails, esto viene siendo un debate; y como ex-Rails developer, tengo tolerancia a cierta medida de magia pero ahora estoy gravitando más hacia lo explícito.

Hay «magia buena» (e.g. convention-over-configuration) y «magia mala» (e.g. leaky abstractions). La primera es aceptable, la segunda no.

Es mi sentir (y meramente mi opinión personal) que Laravel sacrifica mucho por darle prioridad al aspecto «beautiful code» y el «developer as an Web Artisan.» Para que Laravel pueda ser más interoperativo y desacoplado tendría que cambiar mucho estructuralmente, pero dudo que formen parte de las metas de Taylor Otwell. Mientras no pretenda convertirse en omakase, estamos bien.

Para equilibrar la balanza, en un próximo post haré una lista de las cosas que me gustan de Laravel.

Frustrante

Desde Noviembre del año pasado estoy programando de a poquitos y muy lentamente un blog para mis fotos. Se está volviendo una experiencia frustrante porque quiero terminarlo ya. Pensé que podría avanzarlo unos 15 o 30 minutos libres que tuviese al día como lo hice con mi video One Year, One Second Every Day, pero estoy aprendiendo que es distinto editar videos que programar. Este último requiere más tiempo y mayor concentración. Cuando ya recordé dónde estaba y he planeado en mi cabeza cómo voy a programar lo que necesito, Ding! se acabó el tiempo, hora de hacer otra cosa. No es como cuando editaba los videos, podía continuarlo con facilidad. O dejar la máquina procesando, lo que producía avances en el proyecto. Para programar requiero una cantidad mayor de tiempo ininterrumpido.

Se está volviendo muy frustrante. Quiero tenerlo listo ya, quiero subir y publicar mis fotos. Tengo varias ideas por implementar, features, etc. pero ni siquiera he terminado lo básico. Es más, frecuentemente programo algo y luego lo voy refinando, así que lo que tengo avanzado no es el código final, hay cosas por pulir, algunas funciones feas que, debido a la fragmentación de tiempo, ni siquiera estoy seguro de cómo funcionan y no quiero ni tocarlas ni cambiarlas a pesar que, hey, creo que preferíria reducirle el ancho a las imágenes. Lo intenté y todo se desarmó. Oops, a regresarlo como estaba. Epa, no está generando bien las cachés. ¿Por qué? Pero sólo tengo 30 minutos y tenía planeado implementar otra cosa. Lo voy a dejar allí y luego veo por qué. Pero me incomoda dejarlo sin resolver.

Y… se está volviendo muy frustrante.

Empecé a considerar la idea de volver a intentar usar WordPress y usar mi función que arma bonito las imágenes como un plugin, pero recordé que quiero también publicar en inglés y español. Y que tendría que armar un theme con el diseño que tengo ahora. Luego descubrí Koken que se ve absolutamente genial — en serio, es asombroso — pero recordé otra vez: English and Spanish. Y usa un lenguaje propio para templates. Y quizás el tiempo que me tarde implementando mi blog tal como lo quiero con Koken sea el mismo que si continúo con lo que ya tengo.

Frustrante.

jwzhacks

Ya que estamos con la onda retro, hacía tiempo que no visitaba la página de hacks de jwz. Hay algunas cositas nuevas por allí. Un día de estos voy a publicar todos esos scripts pequeños que tengo regados por allí. Siempre pienso que sólo son útiles para mí, pero seguramente otros los encontrarán interesantes aunque sea como ejemplos o puntos de partida. Por cierto, nunca encontré el easter egg de la portada de jwz.

Complicación innecesaria

Los feeds RSS de Drawr (un website de dibujo japonés) muestran sus imágenes reducidas a 500 pixels, pero yo quería verlos con las imágenes a tamaño completo.

Luego de escribir gran parte de un script usando Ruby, Mechanize y Nokogiri, me topé con el problema que el feed está mal formado y eso no le gusta a Nokogiri. Pensé en usar expresiones regulares, como en los viejos tiempos, para sacar los datos de cada item y me comenzó a tomar más tiempo.

Tras analizar el problema nuevamente, me di cuenta que estaba tratando de resolverlo de la manera más complicada posible: hacer parse del feed RSS y armar uno nuevo sólo para cambiar la URL de la imagen, de «imagen_500.jpg» a «imagen.jpg».

La solución, quizás ya obvia para ustedes, fue tomar el feed RSS como una gran cadena de texto y hacer un search and replace para eliminar la cadena «_500». Listo. En menos de un minuto. Creo que me estoy oxidando.