2017/12/13

Test de internet con ping en NodeJS


En estos días he tenido intermitencias en el servicio de internet.

Mi forma de comprobarlo es entrar en una consola y hacer ping a un host, como google.com, y ver si está ok o no.

$ ping google.com -t


El -t permite que el ping se haga indefinidamente, hasta que se presione CTR + C.

Sin embargo, quería una forma de mostrar los cambios de estado, a qué hora ocurrían y cuánto duraban.

Programé esta solución usando nodejs:

GitHub Gist: Internet test with ping in NodeJS

const ping = require('ping');

let host = '8.8.8.8';

if (process.argv[2]) {
  host = process.argv[2];
} else {
  console.log("Syntax: \nnode ping-test-ifchanges-host host");
}

console.log("Testing host: " + host);

let isAlivePrev = false;
let nowPrev = new Date();

function doPing() {
  ping.sys.probe(host, isAlive => {
    if (isAlive !== isAlivePrev) {
      let now = new Date();
      let diff = (now.getTime() - nowPrev.getTime())/1000;
      let timestamp = now.toISOString() + ' after: ' + diff + ' s';
      console.log("\n" 
        + host + ': ' 
        + (isAlive ? ' OK' : ' KO') 
        + ' ' + timestamp);
      isAlivePrev = isAlive;
      nowPrev = now;
    } else {
      process.stdout.write('.');
    }
  });
}

setInterval(doPing, 1000);

Para correrlo en consola:

$ node ping-test-ifchanges-host google.com

Idea

setInterval() establece un llamado, cada 1000 ms, a doPing(), que hace un ping al host que se haya indicado y revisa si hay un cambio de estado.

Si hay un cambio de estado, anota el tiempo y muestra las diferencias respecto al tiempo anterior.

Si no hay cambio de estado, imprime simplemente un punto.

2017/12/04

CSS: Checkbox hack para controles personalizados

¿Cómo aplicar un estilo como respuesta a un click, usando sólamente CSS?

Se puede hacer con el checkbox hack.

Principio

  • Un label asociado a un input puede recibir el click por él
    • Puede haber varios labels para un mismo input
    • Ocultando el input (difícil de personalizar), queda el label para contener un control más fácil de personalizar
  • La pseudoclass :checked permite ubicar un checkbox seleccionado
  • El selector aaa + bbb permite seleccionar un bbb que esté (declarado) inmediatamente después de un aaa

Patrón 1

HTML:
<input id="checkbox-control" type="checkbox">
<label for="checkbox-control">Control</label>

CSS:
#checkbox-control:checked + label {...}

Patrón 2

HTML:
<label for="checkbox-control">Control</label>
<input id="checkbox-control" type="checkbox">
<div class="target">Target</div>

CSS:
#checkbox-control:checked + .target {...} 

Patrón 3

HTML:
<input id="checkbox-control" type="checkbox">
<label for="checkbox-control">Control</label>
<div class="target">Target</div>

CSS:
#checkbox-control:checked + label {...}
#checkbox-control:checked + label + .target {...}

Ideas de aplicación

  • Checkbox personalizado
    • Toggle
  • Tabs
  • Dropdown menu
  • Dot control para slider
  • Árbol desplegable
Ver unos ejemplos en A check studio, en CodePen

Referencias




2017/10/18

La solución imperfecta


¿Por qué el mundo esta lleno de soluciones imperfectas?

Porque la solución depende del contexto.

Digamos que tienes cinco minutos para ordenar la salida de un sistema y un plugin ya listo que lo hace.

El algoritmo hace una ordenación simple tipo burbuja pero cumple con lo que necesitamos.

Si tuvieras un par de horas, quizas podrías hacer desde cero un plugin con el mejor algoritmo de ordenación posible.

Si tuvieras una hora, quizás podrías modificar este plugin y mejorar el algoritmo de ordenación.

Si tuvieras media hora, quizás podrías buscar si alguien más ha hecho ese plugin.

Pero tienes cinco minutos.

Poner este plugin te llevará un minuto, un pequeño test otro minuto, y ya estás gastando tiempo en analizar las alternativas. Alternativas que requieren más tiempo del que dispones. Y todas con un quizás. No existen. Sólo existe este plugin imperfecto, aquí y ahora.

No se trata de usar las respuestas de un libro de texto. Se trata de la vida real, retándote a hacer lo mejor que puedas con lo que tienes disponible en este momento.

Lo eliges. No es la respuesta perfecta, pero es la solución. En este contexto, es la respuesta.

Te gustaría que alguien te comprenda por usar una respuesta no optima.

Ahora te parece tan obvio.

Realizar una solución imperfecta es mejor que una respuesta perfecta que no se puede realizar.

Lo aceptas, y sigues adelante. Quizás en la siguiente iteración la puedas mejorar.

También es un quizás. Pero es es un quizás con algo corriendo.


Imagen de http://news.nationalgeographic.com/content/dam/news/2017/04/27/frog-gallery/01-frog-day-gallery.jpg

2017/08/28

El problema de la sobrecarga innecesaria

Problemas reales

Pienso que resolver problemas es una cuestión de prueba y error.

Que no es como te lo enseñan en la escuela, donde aprendes a copiar soluciones de los libros de texto.

Resolver un problema es como andar a tientas por una habitación a oscuras, tratando de llegar a la puerta.

Lo que te dan los libros de texto son como escenarios prefabricados de juegos con finales conocidos. Llenos de cosas que los maestros han puesto y con rutas de solución que ellos ya conocen.

En los problemas reales, puede haber más de una ruta de solución. O ninguna.

También encontraras montones de cosas que te sirven mezcladas con cosas innecesarias. Y necesitarás aprender a notar cuál es cuál.

Enfrentarte a problemas reales despierta cierto sentido. Aprendes a escuchar al problema. Aprendes a buscar dentro de ti. Aprendes a construir caminos.

Patrones

Conforme vas resolviendo problemas, te das cuenta que se repiten ciertos patrones para solucionarlos.

Identificar estos patrones ayuda a catalogar las soluciones y facilitar su reutilización.

Por ejemplo:
  • Qué tal si divido el problema en partes. Si varias de esas partes me son familiares, podría avanzar por allí.
  • Qué tal si solo considero algunos detalles (eso se llama abstracción). A lo mejor veo más claro en esa versión simplicada.
Ayuda dividir el trabajo web en partes separadas.

También ayuda quitar de en medio una problemática innecesaria.

MVC

Modelo-Vista-Controlador es un patrón de desarrollo web que divide el trabajo en tres areas:
  • Vista: la interfaz de usuario, HTML, CSS, Javascript
  • Modelo: los datos que la Vista mostrará
  • Controlador: el que orquesta las actuaciones de la Vista y el Modelo
Se trata del patrón Qué tal si divido el problema en partes. La idea es concentrarse en cierto aspecto del desarrollo para simplificar el trabajo.

Componentes

El desarrollo de un site o una aplicación web, no es una tarea definida. Es un problema cuyas tareas hay que ir descubriendo en el camino, durante sucesivas iteraciones. No es ir de la A a la Z y ya. Es ir por las letras de un mensaje desconocido, fallando y acertando mientras se va haciendo más claro.

Para iterar con agilidad, necesitamos poder hacer cambios con facilidad.

¿Ayuda MVC en esto?

MVC ayuda a enfocarse en cierto aspecto del problema y a organizar todas las cosas en esas tres grandes areas. Pero esa virtud también tiene su inconveniente. La navegación por el mar de las posibilidades se vuelve muy, muy pesada. Cierto que sabemos donde queda cada cosa y eso es muy bueno. Pero, por otro lado, la implementación de cada idea se vuelve engorrosa.

Imaginamos las cosas naturalmente como componentes, pero en MVC cada solución o variante que imaginemos tiene que ser dividida en tres partes antes de poder implementarlas. Es un ejercicio constante de traducción entre lo que imaginas y lo que haces para producirlo.

Está bien, pero quizás podría ser mejor.

Entran los componentes.

¿Qué tal si dividimos las cosas no por areas M, V, C, sino por funcionalidades, por componentes?

Es parecido a decir, que tal si en lugar de tener carpetas css, js, images, tenemos varias carpetas home, contact, menu, header, product, etc, cada una representando una funcionalidad o conteniendo otras carpetas de funcionalidades.

Confusiones papistas

Más papista que el Papa, dice un refrán. En algunos proyectos hay personas que adoptan esta actitud de defender algo como cierto porque sí, porque así es.

Gente que toma MVC como una biblia o estresa al equipo que obvia una ceremonia del scrum.

Lo importante es honrar el por qué de las cosas. MVC busca claridad. Scrum busca bienestar del equipo.

¿Los componenentes podrían hacerlo mejor? ¿Podríamos sentirnos menos estresados? Probemos.

El problema en el Frontend

Este es más o menos el flujo de trabajo que se sigue al desarrollar web:
  1. Se propone un diseño gráfico base
    Algunos insisten en querer tener todo resuelto en este punto, pero es crear falsas expectativas y sufrimiento innecesario.
    Es importante que el cliente entienda que el desarrollo es iterativo (hablando de eso, también es importante que el equipo de desarrollo lo entienda ^^).
  2. El diseño gráfico se maqueta con HTML, CSS y Javascript
    Los datos son hardcodeados.
    Algunos insisten en querer maquetar directamente sobre un framework, pero es crear lastre mental innecesario, además de amarrar la maqueta a ese ambiente.
  3. La maqueta es vuelta template, según el framework que se va a usar
    Los datos son mockupeados. Es decir provisto por endpoints que devuelven data hardcodeada.
    Algunos insisten en hacer endpoints reales de una vez, pero también es crear lastre mental innecesario tratar de enfrentar más de un problema a la vez.
  4. La aplicación es provista de datos reales
    Ya que las anteriores etapas han resuelto una cosa a la vez, se reduce bastante el número de posibilidades de error en este punto.
  5. El cliente quiere un cambio
    Procedemos a iterar.
Aquí es donde se presenta el problema. En la atención de los cambios.

Como las revisiones ya se están haciendo con datos reales, las circunstancias presionan para no ir al paso 1, sino iterar sobre el paso 4.

No se actualiza la propuesta gráfica, ni la maqueta en puro HTML. Se percibe como demasiado engorroso. Se hacen los cambios directamente sobre el template con toda la infraestructura corriendo.

Paradójicamente, eso no es más rápido, ni más seguro.

Para hacer cualquier cambio en el template, con la infraestructura corriendo, tienes todo un ecosistema de base de datos, modelos y controladores funcionando... innecesariamente.

Resolver un cambio en un template es un problema más complicado porque tienes que cargarte mentalmente de todas las convenciones y protocolos del framework, y de todas las circunstancias y problemas que otras areas estén atravesando (que la configuración del entorno ha variado, que por ahora no uses este endpoint sino este otro, que hay un servicio que se ha caído y debemos esperar, etc, etc).

En cambio, hacer los cambios sobre la maqueta es un problema aislado, más sencillo y rápido de resolver.

Creo que es mejor resolver los problemas en la maqueta y luego recién llevar esa solución al template.

Si el paso de convertir una maqueta a template no fuera manual sino automático (o si no existiera), creo que sería más sencillo y rápido hacer cambios de UI.

juno-cheeriounophp han sido algunas iniciativas personales para automatizar el paso 3. La idea de unophp se puede adaptar incluso para WordPress.

Pero por ahora, tenemos este problema en Frontend: cómo atender con más facilidad los cambios que se requieren durante las iteraciones del proyecto.

Antipatrón

Yo diría que es un antipatrón que el frontend requiera que todo el motor del proyecto, con su base de datos, endpoints, etc, deba estar corriendo para hacer sus cambios.

Es complejidad innecesaria para esa tarea.

Entiendo que en Integración Contínua se prueban las cosas sobre infraestructuras reales corriendo. Es porque necesitan hacer pruebas en ese nivel. Pero hacer el desarrollo en ese mismo nivel no me parece lo más optimo.

Sería mejor poder aislar esa parte a voluntad, poder crear un entorno donde no exista otra complejidad más allá de lo que quieres resolver, hacer el cambio, y luego, mágicamente, incorporarlo al proyecto completo.

2017/08/09

UX para todo(s)


Nota: Por favor, lee esto con la mente abierta. Si eres frontend, creo lo entenderás. Si eres backend, por favor, no me malinterpretes; también he hecho algo de backend y muchos de mis amigos son backend. No tengo nada en contra de los backend. Excepto quizás la optimización prematura, el overkill (pero eso es algo que se ve en todas partes), y esto.

Encuentro que hay una discusión entre frontend y backend. Entre los chicos que hacen las interfaces para el usuario y los que preparan la data que se mostrará.

Es más o menos así: los backend pretenden que los frontend tienen que usar sus apis cómo a ellos les de la gana de hacerlas.

Por supuesto pueden esgrimir un montón de argumentos; que el mejor modelamiento de las tablas, que la auto documentación, que la optimización, etc.

Lo que yo digo es solamente esto: imagínate que los frontend pretendiéramos que los usuarios tienen que arreglárselas para usar las interfaces que nos diera la gana de hacer.

¿Que así es como haces tus interfaces de usuario? Detente, stop, para un momento.

Por supuesto que durante muchos años se ha hecho así; con la dictadura de los diseñadores sometiendo al usuario y obligándoles a aprender que la opción que buscaban estaba nada más a cuatro clicks de distancia, debajo de un menú desplegable que actuaba cuanto pulsabas la tecla alt después de escape (bueno quizás no tanto, pero seguramente captas la idea).

Pero la abundante oferta de aplicaciones y la despiadada elección de los consumidores ha hecho que recapacitemos y escuchemos al usuario y qué tipo de experiencia realmente le ayuda a conseguir lo que necesita. Porque lo que la UX busca no es que las interfaces sean más bonitas (es un malentendido de marketing); lo que busca es que las interfaces puedan dar lo que se necesita sin obligar a hacer un esfuerzo innecesario.

Además, mira el nombre, "interfaz de usuario", no dice "interfaz del programador frontend". No se supone que debas sentirte cómodo programándola; quizás tengas suerte y sea entretenido, estimulante, o quizás no y sea un dolor de cabeza y un verdadero desafío cómo resolver una interacción; lo importante es que el usuario pueda sentirse cómodo usándola, sin esfuerzos innecesarios.

Pues bien, del mismo modo, la API que se entrega a los frontend es la interfaz con la que nos comunicamos con la fuente de datos. Una buena API no es aquella que sea cómoda o fácil de programar para los backend; puede que lo sea, si se organizan bien, pero es un rollo interno, que no debe atravesar la interfaz. Porque recordemos que se trata de una interfaz: la comodidad y facilidad deben estar del lado de quién la va a usar.

Un backend debería hacer con el frontend el mismo ejercicio que el frontend hace con el usuario. Observarlo, ver cómo va a usar la API, conversar con él acerca de sus necesidades reales, empatizar.

No creo que necesitemos una especie de Frontend eXperience (no más siglas, por favor), sino que comprendamos que los mismos principios que venimos a reconocer como válidos al aplicar UX son aplicables también a la hora de desarrollar interfaces para otros desarrolladores. Puede ser un API REST, o puede ser una librería, o un framework, o cualquier herramienta en general.

En una interfaz, la comodidad y facilidad deben estar del lado de quién la va a usar. Creo que es el principio que guia a la UX y está ayudando a crear más software realmente valioso para los usuarios. Y creo que es hora que apliquemos lo mismo a la relación frontend-backend (y en todas aquellas donde veamos una interfaz), y ayude a crear herramientas realmente valiosas para desarrollar mejor mejores aplicaciones.

2017/06/30

Problemas vs Tareas


Resolvemos problemas cada día. Pero a veces no sabemos qué lo estamos haciendo, ni cómo. Y otras, nadie parece valorarlo.

¿Qué es un problema? Algo cuya solución no es evidente.

Si la solución fuera evidente ya no sería un problema, sino una tarea.

Por ejemplo, si fuera un pintor, tengo los utensilios y la habilidad para pintar tanta area de pared cada hora, ¿cuánto me demoraré en pintar cierta pared?, pues tanto tiempo. El camino es conocido y está libre. Es una tarea.

En cambio, sería un problema si alcanzar alguna parte de la pared no fuera evidente.

O, si en lugar de ser un pintor de brocha gorda tuviera que pintar un retrato. ¿Qué espera mi cliente?, ¿cuál será la pose adecuada para esta persona?, son preguntas cuya respuesta no es evidente. Es un problema.

Lo evidente

¿Qué es evidente? Depende de tus conocimientos y habilidades. Algo evidente para una persona puede no serlo para otra.

Cuando pagas con un billete algo que cuesta menos, es evidente para un adulto que le tienen que dar vuelto. Pero no es tan evidente para un niño que está aprendiendo a comprar en la calle.

Tampoco es evidente que se tenga que distinguir entre problemas y tareas. Pero espero que notes la utilidad de notar la diferencia.

Notando la diferencia

A veces llamamos problemas a tareas que se realizan rutinariamente. O tratamos a quienes resuelven problemas como si estuvieran realizando tareas rutinarias.

Para no formar falsas expectativas, es importante distinguir qué es una tarea y qué es un problema.

Cuando te enfrentas a un problema, sueles encontrar un no dándote el primer encuentro. Este no, muestra que la respuesta no es evidente y aclara que no se trata de una tarea.

Si fallas al realizar una tarea, es que en realidad se trataba de un problema.

Entonces, casi como por instinto, pasas a preguntarte cosas. Si hay algo que se parezca a alguna tarea que conoces. Quizás resolviendo eso primero se aclare cuál es el siguiente paso. O tal vez se trate de dividir el problema en partes conocidas. O, a lo mejor, se pueda expresar alguna parte en términos de algo que ya conozca.

Intentas, fallas, pruebas otra cosa, aciertas, y así vás construyendo un camino hacia la solución.

Cuando realizas una tarea, no aparecen ese tipo de preguntas. Si aparecen, entonces no es una tarea, sino un problema.

Resolviendo

Resolver un problema requiere un trato diferente que realizar una tarea.

Resolver un problema requiere ciertas habilidades adicionales a las que se necesitan para realizar tareas.

Debes ser capaz de aceptar un reto, de imaginar alternativas, de probar un plan y fallar en el intento, de reconocer la información que un intento fallido te puede estar dando, de ubicarte en ese viaje.

Estimando

¿Cuánto tiempo te toma hacer una tarea? Tanto tiempo.

¿Cuánto tiempo te toma resolver un problema? No lo sé, depende del problema.

Pero, un momento, ¿en los exámenes, acaso no hay problemas que hay que resolver en cierto tiempo? Sí, pero en realidad no son problemas para quién propone la prueba, que ya los ha resuelto tantas veces que sabe cuánto es lo que se suele tardar en resolverlo. Sería más correcto llamarlas preguntas.

Un estudiante que no ha estudiado el tema ni practicado preguntas similares, puede tardar mucho más tiempo en resolver una pregunta, porque para él sería realmente un problema. En cambio, otro estudiante, que ha estudiado el tema y practicado ese tipo de preguntas hasta que le resulten tareas, tardará mucho menos.

Puedes ser muy habil realizando tareas y saber cuánto te toma hacerlas. Pero ¿qué pasa cuando te enfrentas a cuestiones cuya respuesta no es evidente?.

Resolver un problema no es un tour al mercado de un pueblo conocido, sino un viaje de exploración. ¿Cuánto tiempo te tomará entrar al bosque desconocido y encontrar allí la fruta que me gusta?

No se puede presupuestar un problema. Sólo se pueden presupuestar tareas.

Si necesitas presupuestar un problema, busca a alguien para quien ese problema sea solo una tarea. O que maneje el proceso para convertir problemas en tareas.

Agile

En el desarrollo agile se trata de tomar un problema y determinar tareas lo más pronto posible para poder presupuestar sobre eso.

Para resolver un problema, se asigna una cantidad pequeña de tiempo y recursos para dar un pequeño paso cada vez. Es como una apuesta. Puede que alcance para resolver algo, puede que no, pero es un riesgo limitado y calculado. Viendo el resultado, podemos decidir si volvemos a apostar por lo mismo o cambiamos de número.

Preparación

Saber cómo manejar un problema es importante, pero hay que reconocer que si no hay alguien capaz de realizar las tareas que surgirán, el problema no se podría resolver.

Familiarizarnos con las tareas nos da más oportunidades de encontrar cosas conocidas al enfrentar un problema.

Nuestro repertorio de tareas conocidas puede ser visto como un vocabulario que nos ayuda a expresar una solución.

Conocer más número de tareas ciertamente puede ayudar. Pero, igual que con las palabras del lenguaje, es importante saber usar eficazmente aquellas que tengamos disponibles.


Herramientas

Es común que se entregue un problema a alguien y se lo deje solo, a ver cómo lo resuelve. Y lo resolvemos, a veces sin saber exactamente cómo. Así aprendimos a interpretar el mundo, a hablar, a tratar con otras personas y situaciones.

Sin embargo, puede ser útil visualizar las cosas que usamos cuando resolvemos problemas. Estas son las que yo suelo distinguir.

Contexto. Es un conjunto de consideraciones que tenemos en cuenta a la hora de tratar con algo. Para abstraer, quitamos consideraciones. Por ejemplo, al tratar con formas geométricas, podemos dejar de lado el peso o el color. Tener claro el contexto y saber aplicar abstracciones ayuda a resolver problemas.

Analogías. Es encontrar un contexto paralelo que ya conozcamos y representar allí nuestro problema, resolverlo, y luego volver al contexto inicial para representar allí la solución.

Semejanza. Así abajo como es arriba. Es encontrar analogías dentro del mismo contexto. (También se podría decir que una analogía es una semejanza entre contextos.)

Patrones. Son como figuras que vemos repetirse en diversos contextos.

Conclusión

Resolver problemas es una actividad que requiere una disposición mental y unas habilidades distintas a hacer algo rutinario.

Pienso que muchas trabas y malentendidos en el desarrollo de proyectos se deben a que no se entiende está diferencia de la actividad creativa.

Creo que hacer la distinción entre problemas, como algo cuya solución no es evidente, y tareas, como una actividad plenamente determinada, es útil para visualizar mejor lo que tenemos frente a nosotros. Para resolver el problema de los problemas.




2017/06/02

Jugando con asteriscos en CSS

Inspirado por el logo de JWT, se me ocurrió jugar a formar asteriscos como una rotación de una barra.

Logo JWT


Para el caso de 6 líneas, probé crear con Sass un mixin que escriba el código repetitivo.

2017/05/30

Simplificando el desarrollo

Webpack, Babel, TypeScript, Gulp, Sass, Stylus, Pug, son algunas de las cosas que se ven en el desarrollo frontend hoy en día.

Pug (Jade) permite escribir una especie de html sin brackets, que se ve más limpio y legible, y luego es traducido a html.

Sass y Stylus hacen algo parecido con el css.

CoffeeScript lo hacía con el javascript. Pero parece que va cayendo en deshuso, frente a TypeScript y ES6.

Pug te permite escribir html de manera más clara y sencilla y está bien.

Styles te permite escribir css de manera más clara y sencilla y está bien.

CofeeScript te permite escribir javascript de manera más clara y sencilla y también está bien.

Está bien que produzcas html, css o javascript de la manera que te resulte más cómoda y fácil de mantener.

Sospecho que muchos programadores provenientes de otras canteras, resintieron tanto las incomodidades de los brackets, y puntos y comas, que usaron sus potentes habilidades para construir herramientas que les recordaran sus lenguajes preferidos.

Además, herramientas como Gulp, Babel y Webpack pueden automatizar el proceso de traducción.

Pero entonces comenzó a complicarse la cosa.

Si miramos las cosas desde una perspectiva más amplia, lo que ha sucedido es que se ha creado una capa adicional entre el programador y el código. Una capa de pre procesado.

¿Qué pasa cualdo alguien más quiere participar en el desarrollo de un proyecto como este? Esta persona conoce todo lo necesario para actuar en la capa del código html/css/javascript.

-- Pero no, un momento, no puedes hacer eso.

-- ¿Por qué no?

-- Porque yo escribo en mi hermoso pug/stylus/coffeescript para producir ese horrible html/css/javascript y no se me ocurre cómo hacerlo en sentido inverso para que tus cambios actualicen los míos.

-- Bueno, me voy a ayudar a otro proyecto.

¿Y para qué publicas un proyecto en GitHub, como open source, y en inglés, si no es para facilitar que otras personas puedan colaborar contigo para evolucionar una idea que te apasiona?

Entonces, no tiene mucho sentido restringir esa facilidad con herramientas que no todo el mundo quiere usar, aunque tú las adores.

Lo que debería haber en tu proyecto compartido es cosas que sean fáciles de compartir: html, css y javascript. Producidos con las herramientas que gustes; pug, sublime, atom, notepad o dreamweaver. Pero, así como no puedes exigir que alguien use dreamweaver, sublime o atom para poder participar en tu proyecto open source, tampoco deberías exigir que usen tal o cual pre procesador.

El efecto de encarecer las cosas

Imagina que tienes una cita con una chica que te gusta. Por alguna razón, lo comentas en casa, a tu abuela. Ella se opone, por varias razones importantes:

-- No sabe cocinar; ¿cómo te va a atender después?

-- Pero, abue...

-- Además es demasiado flaca; con esas caderas sufrirá mucho para tener hijos

-- ¡Es sólo una cita, abuela!

Si sales con alguien pensando en si se casarán, ves todo con otros ojos. Hasta los defectos más pequeños se convierten en gigantes cuando los proyectas sobre la pantalla de un futuro de deberás soportar todos los días.

La abuela piensa así porque en su época, donde vivía, una cita era algo muy importante y costosa, pagada con el dinero que la familia ahorraba con esfuerzo, así que no podías estar en plan de "salir para ir conociéndonos".


Algo así aparece en el proceso de desarrollo cuando un proceso es caro de hacer.

Antes, con un simple editor de texto y el navegador, podías moverte rápidamente entre el html y los resultados, probando diversas librerías, plugins, etc, con mucha agilidad. Como ir en bicicleta.

Ahora, es un camión. Si quieres probar y jugar con una librería, un plugin, etc. ya no puedes hacerlo directamente, como antes. Debes traducir mentalmente el html de la documentación del plugin, y calcular tu código para que produzca el html que se requiere. Son dos lenguajes en la cabeza y un paso extra para depurar. Es como caminar con ayuda de un espejo.

Así que ya no tienes citas por diversión. Todo se vuelve más serio.

Cómo el builder establece de antemano dónde irá cada cosa hasta el fin de los tiempos, con ese mal ejemplo la gente empieza a sentirse presionada a hacer el código limpio directamente. De pronto, la elaboración progresiva de soluciones, la refactorización y la restructuración de directorios quedan al margen de la ley, porque son más caros.

Además, la gente empieza a usar Gulp y Webpack como herramientas con las que pueden instaurar un régimen de código opinionado ("así es cómo se deben hacer las cosas, tontos").

Y todo empezó con el afán de trabajar más cómodos. De buenas intenciones está hecho el camino al infierno... como reza el dicho.


Creo que es importante mantener un punto de vista amplio acerca de las cosas que hacemos en desarrollo. Del mismo modo que un máximo en cada división de una empresa no garantiza un máximo de la empresa en conjunto, una mejora en un aspecto individual no garantiza que todo el proceso de desarrollo será mejor. Los máximos locales no garantizan máximos globales. Producir html rápidamente no garantiza que mantenerlo será igual de rápido. Es mejor un enfoque holístico.

Creo que una buena referencia para tomar decisiones es considerar el número de pasos, capas y herramientas que significa corregir un bug, o introducir un cambio. Un problema se puede resolver de muchas maneras. Es posible usar un cañón para matar moscas. Pero es una buena idea empezar con las soluciones más simples primero.

Y, construir las cosas de modo que no obstruya los siguientes pasos. Evitar los compromisos innecesarios y mantener el camino libre y fresco para avanzar progresivamente. Ya que el viaje es el camino.

2017/05/24

Emponderar a los usuarios

Cuando estaba en la universidad, retomé el contacto con las computadoras después de un largo tiempo y conocí el DOS de Microsoft.

Estaba frente a una pantalla negra con el prompt C:\> esperando a que ingresara algo. Cuando lo hacía, me respondía.

Me sentía fascinado.

Aprendí a usar casi todos los comandos de la consola, y a programar nuevos comandos.

  • En la consola command, se pueden ejecutar comandos cuyas salidas pueden ser entradas de otros comandos.
  • Se pueden crear fácilmente nuevos comandos batch ejecutables desde la consola. Ya que los batch son archivos de texto simple y la consola tiene algunos comandos para generarlos.
  • Un comando podría generar nuevos comandos dinámicamente. Es decir, un batch se podría generar dentro de la rutina de un comando y ser ejecutado luego dentro del mismo comando.
  • Los programas de pantalla completa, aunque impresionantes, rompen el esquema de reutilización de comandos al apropiarse de toda la interfaz.
Más tardee, conocí Linux y la consola de comandos bash, donde se pueden observar puntos similares.


En la interfaz gráfica de Windows, en cambio:
  • En el escritorio, se pueden ejecutar aplicaciones, pero estas ejecuciones son aisladas y no se puede realizar ejecuciones compuestas donde la salida de una aplicación sea la entrada de otra, dinámicamente.
  • No hay herramientas para construir fácilmente nuevos programas desde el escritorio. Las aplicaciones no son interpretadas, sino ejecutadas desde un binario, y construir ese binario requiere conocimientos y herramientas especializadas.
  • No hay una forma sencilla de construir aplicaciones que puedan generar otras aplicaciones dinámicamente, dentro de su ejecución. No es sencillo construir compiladores.
  • La reutilización de las características de una aplicación es difícil. Cada característica está pegada a la aplicación. Cada mejora de características requiere una nueva versión realizada principalmente por quienes la programaron.
Algo parecido se puede decir de las interfaces gráficas de Linux (Gnome) y de la Mac (OSX), que vine a conocer luego.


En la interfaz gráfica de la Web, en el browser, se muestra una aplicación:
  • Cómo hacer que la aplicación sea un entorno donde se puedan ejecutar componentes que puedan componerse para formar nuevos componentes?
  • Cómo hacer que sea fácil crear componentes con los componentes presentes en el entorno?
  • Cómo hacer que un componente pueda generar dinámicamente otros componentes dentro de su ejecución?
  • Cómo prevenir que un componente pueda apropiarse de la interfaz?

Me parece distinguir que ese conjunto de características facilita que un sistema pueda ser extendido con la participación de sus usuarios.

El conjunto de comandos DOS y bash, puede ser fácilmente extendido por sus usuarios. Habrá programadores capaces de hacer nuevos binarios, pero la capacidad de hacer scripts, batch o bash, está disponibles de inmediato.

El conjunto de aplicaciones en Windows (o Gnome, o OSX) no puede ser fácilmente extendido por sus usuarios. Sólo puede serlo a través de programadores capaces de hacer nuevos binarios.

Uno se puede preguntar si esta limitación es puesta a propósito.

Al limitar que los usuarios puedan extender el sistema que usan, las empresas proveedoras de software se aseguran el papel de intermediarios, entre los usuarios y las soluciones que los usuarios requieren.

Y es conocido en el comercio que el intermediario siempre gana.

Así que me parece que la cuestión de limitar la extensibilidad del sistema por parte de los usuarios puede ser algo diseñado.

Sin embargo, ¿por qué ocurre también en la interfaz gráfica de Linux?. Siendo la comunidad Linux un fuerte representante del movimiento de software libre (promotor de dar a la gente la libertad de usar el software como quiera), esperaría que hubieran escritorios que permitieran componer aplicaciones visualmente, siguiendo la filosofía de composición de comandos que está presente en la consola.

Quizás sea que están distraidos por las complejidades de otros problemas.


Pero me parece que resolver esta situación sería muy interesante. Un escritorio así, emponderaría a los usuarios para crear cosas, sus propias cosas, y compartirlas en comunidad.

A mediados de los 80, Hypercard, de Bill Atkinson, fue una aplicación gráfica que facilitaba a los usuarios la creación de sus propias soluciones y a compartirlas. Atkinson insistió en que se distribuyera de modo gratuito Apple insistió en encontrarle alguna manera de obtener ganancias. Finalmente, el desarrollo de Hypercard se estancó y Steve Jobs canceló su desarrollo, cuando volvió a mediados de los 90.

Aunque hoy hay fans que recuerdan el legado de Hypercard, me parece que se enfocan más en las cualidades técnicas (como la interfaz gráfica, que sirvió de inspiración a VisualBasic y otras herramientas), que en la cualidad social de emponderar a los usuarios para hacer sus propias soluciones.


Quizás sea posible implementar la idea en la web, usando componentes que puedan componerse para formar nuevos componentes, tanto a mano como dinámicamente.

Quizás React pueda ser una buena opción para eso. (Sin embargo, la forma en que se suele usar React, con Webpack para generar compilados, parece una especie de barrera. A veces parece como si las compilaciones fueran una forma de dejar fuera a los demás y ponerse uno como intermediario.)

2017/05/18

Programando tu propia comida

En un inicio, si alguien tenía una computadora era para programar algo que solucionara su problema en particular.

Habían recetas de soluciones que se compartían entre la gente que programaba.

Cuando mucha gente trabajaba sobre cierto programa, se iban estableciendo costumbres y estándares para facilitar la comunicación entre las personas.

Nuevas formas de programar fueron emergiendo para facilitar que más gente pudiera programar soluciones más complejas con más facilidad.

Poco a poco, ya no fue necesario conocer de electrónica, ni de cuestiones específicas del hardware de la computadora. Luego, no fue necesario usar siglas mnemotécnicas sino expresiones muy parecidas al inglés.

Entonces, en algún momento, alguien notó que una computadora podía tener usuarios que no programaran, sino que usaran interfaces simples para realizar acciones sin componer nuevos programas.

Más tarde, alguien más notó que esos programas con interfaces simples podrían ser vendidos. Y luego, que para asegurar la dependencia podían limitar la posibilidad de hacer nuevos programas.

El software comercial permite resolver muchos problemas. Pero cada nueva característica, cada mejora, depende de que el proveedor del programa lo incorpore en la siguiente versión, por la que tendremos que pagar.

El software libre aparece como una respuesta a esta situación. Al obligar a que el código fuente de cada programa este disponible y cada usuario tenga la libertad de modificarlo y redustribuirlo, ayudó a que quienes tuvieran el conocimiento técnico suficiente pudieran ayudar con la evolución del software.

Sin embargo, la barrera es muy alta. El software actual, comercial o libre, sigue el esquema de aplicaciones paquete de muy difícil manufactura. Se necesita avanzados conocimientos de programación para lograr algo así. Además, son productos de uso final que difícilmente se comunican entre sí y que prácticamente no se pueden desagregar ni componer para formar nuevas soluciones.

A fines de los '80, Apple, una empresa con el estilo de proveer productos de cómputo que los usuarios no pueden alterar ni extender, tuvo un producto llamado Hypercard, creado por Bill Atkinson, que permitía a los usuarios componer visualmente secuencias de acciones y expresar los detalles en el lenguaje Hypertalk, muy simple y fácil de leer y escribir. Es decir, creó un entorno que permitía que los usuarios finales pudieran hacer programas para solucionar sus problemas particulares. Como antes, apareció una comunidad que compartía sus recetas.

Por alguna razón, está iniciativa no recibió el apoyo adecuado. Las siguientes versiones del producto limitaban las capacidades de creación y buscaba colocar a Apple como intermediario, otra vez, de las soluciones que la comunidad de usuarios era capaz de realizar por si misma.

Cuando Steve Jobs (precisamente, uno de los primeros en notar cómo hacer negocios con el software) regresó a la dirección, uno de los proyectos que canceló fue el de Hypercard.

Cosas como Hypercard necesitan una comunidad de usuarios emponderados, capaces de crear soluciones cuya explotación no puedes controlar.

Hay proyectos que tomaron la posta de ciertas ideas de Hypercard. Como VisualBasic, con su interfaz visual. Pero parece que siempre orientados a programadores, no a un público laico.

Parece más probable que una iniciativa que herede el espíritu de Hypercard provenga del software libre que del software comercial.


Hoy, el software comercial ha logrado que prácticamente cada persona cuente con una computadora en la mano. Gracias a ella puede consumir los productos que les preparan. La barrera técnica para preparar esos productos es tan alta y los consumidores tan ávidos de soluciones que se ha vuelto notoria la falta de capacidad para cubrir esa demanda.

Es como si hubiera pocos restaurantes para muchos comensales.

La comunidad de programadores, que son como los cocineros, ha optado por buscar modos de mejorar su respuesta, optimizando la forma en que programan, automatizando procesos, etc.

Los gobiernos están promoviendo la enseñanza de programación para aumentar el número de programadores. Es como aumentar el número de chefs y restaurantes.

Y sigue el aumento de gente con nuevas ideas de aplicaciones. Son como comensales con nuevas ideas de platillos, buscando chefs que los entiendan, o incluso financiandose un pequeño restaurante para poder ofrecer al mundo ese platillo que imaginan.

Ellos necesitan programadores porque, a diferencia del mundo de los comensales que también pueden cocinar, en el mundo de las aplicaciones es tan alta la valla de entrada que es como si sólo existieran cocinas industriales y ollas gigantes y sólo ingredientes al por mayor. La poca gente que puede preparar sus alimentos son los que saben hacer sus propias hogueras y utensilios para cocinar. O las que comen sushi.

¿Qué podemos hacer en este escenario?

Además de los cocineros tratando de cocinar más rápido y de los gobiernos tratando de hacer más cocineros, hay otras iniciativas en curso.

Hay el equivalente a cocinas comunitarias, donde cocineros pueden alquilar un espacio.

Hay el equivalente a máquinas expendedoras, donde se pueden conseguir golosinas, cafe o sandwich. Administradores de contenido que te permiten combinar algunas opciones para armar un refrigerio.

Los avances en inteligencia artificial están permitiendo máquinas expendedoras capaces de preparar algunas comidas básicas. Es decir, acciones simples como encender las luces, monitorear el refrigerador, sintonizar la tv o hacer consultas en Google, obedeciendo comandos en el lenguaje del usuario.


Quizás a estas alturas ya hayas notado qué ha pasado y qué se podría hacer.

Es como si se hubiera convencido a todo el mundo que la única forma de comer decentemente es en un restaurante o comprando algo hecho por un cocinero profesional.

¿Qué vendría a ser Hypercard? Quizás algo así como una máquina expendedora pero no de comida, sino de pequeños utensilios para cocinar, o de partes modulares para armar esos utensilios, y de ingredientes al por menor.

El símil deja ver que así como todo el mundo puede cocinar aprendiendo unas pautas básicas, la programación podría ser algo más asequible también.

El poder de la inteligencia artificial también podría ayudar, si se le permitiera disgregar soluciones existentes y componerlas en nuevas soluciones y a la comunidad de usuarios compartirlas libremente.

La clave es una libertad efectiva para componer nuevos programas a partir de otros, y de poder compartirlos libremente.

Si no puedes cocinar, dependes de alguien más para algo que debería ser una libertad básica.

No digo que no haya restaurantes. Tampoco que atendamos restaurantes usando expendedoras. Digo que no debe ser prohibitivo cocinar uno mismo.

Cada persona debe tener la libertad, y el poder, de resolver sus propios problemas, sin intermediarios.

Programar debe ser una actividad al alcance de cualquier persona.

Porque cada cambio en el mundo nace de una persona, no de un rebaño.

Y el mundo está necesitando cambios significativos más rápido de lo que se le puede proveer.

Necesitamos herramientas de programación más asequibles. El equivalente a una cocina de hogar o una hornilla. Ollas pequeñas y personales. Ingredientes al por menor. Recetas familiares.

Necesitamos liberar la creatividad de las personas para descubrir nuevas experiencias y soluciones... nuevos sabores.

2017/05/10

Solución al problema del high DPI con Freeplane en Windows 10

En una computadora corriendo Windows 10 con pantalla con high DPI (de muy alta resolución, por ejemplo, 4K), algunos programas (como Photoshop CS6, GimpShop, Inkscape y Freeplane), muestran los menús o botones de un tamaño diminuto, casi ilegible.

Freeplane es una de las aplicaciones que muestra botones diminutos
en panallas con high HDPI


Para Inkscape funcionó bien el truco de declarar un .manifest: http://www.danantonielli.com/adobe-app-scaling-on-high-dpi-displays-fix/

Quizás porque Freeplane es un programa que corre bajo Java, el truco del manifest no funcionaba. Finalmente, pude solucionarlo entrando a las propiedades del ejecutable freeplane.exe: Compatibility, Override high DPI scalaing behavior. Scaling performing by: System


Propiedades de freeplane.exe
Luego del cambio, los botones aparecen con un tamaño adecuado:

Luego de indicar que el escalamiento high DPI será
manejado por el sistema

Sabiendo esto, comprobé con Inkscape (sin ningun .manifest) que también funcionaba. Así, este método es una alternativa más simple al de ener que crear el .manifest.

2017/04/30

Tú debes poder programar

Porque los programas están construyendo tu vida


En la Edad Media, la gente recurría a escribientes para que les redactara sus escritos.

Cosas como Actas, Títulos, Leyes, Poemas, Cartas, Cosas Importantes.

Mientras la demanda estuvo limitada a religiosos y nobles, los escribientes fueron suficientes.

Cuando la gente aprendió a usar los escritos en su vida, la demanda aumentó, y los escribientes que había no eran suficientemente numerosos ni suficientemente rápidos para redactar lo que les requerían.

En el mundo actual, la gente recurre a los programadores para que les haga sus programas.

Mientras la demanda estuvo limitada al gobierno y las empresas, los programadores fueron suficientes.

Cuando el Internet acelera a que la gente use los programas en su vida, la demanda de programadores aumentó y ya estamos notando que no son lo suficientemente numerosos ni lo suficientemente rápidos para hacer los programas que queremos.

(Sí, quizás es mejor dar un paso atrás e imaginar que no eres un programador para tener una perspectiva más amplia de estas cosas).

¿Qué está pasando ahora?

Los escribientes están mejorando sus técnicas para crear escritos.

Como ha quedado patente, casi nunca el cliente sabe cuál es exactamente el mensaje que quiere que se escriba, eso se va descubriendo en el camino, iterativamente, de manera ágil.

En realidad, hay un conjunto de técnicas de redacción defensiva y buenas prácticas para facilitar cambiar las cosas si el cliente de pronto cambia de opinión sobre algo. (Quizás ya no quiera mandar el poema a Rosa sino a María. Quizás no quiere un tono tan formal, etc.)

Por supuesto está la cuestión de la calidad. Es bien sabido que es mejor recibido un mensaje bien presentado, así que elegimos el mejor pergamino y las mejores tintas. También cuidamos el estilo de la letra y el arte de las iluminaciones que van alrededor.

Cada cierto tiempo se prepara un pergamino con la caligrafía y las iluminaciones propias del final, para que el cliente vaya evaluando el resultado. Esto es gracias a que los avances tecnológicos han permitido abaratar enormemente el costo de los pergaminos y la tinta.

Los escribientes más vanguardistas han optado por indagar en el destinatario (Rosa o María) para estar seguros que el mensaje será el que les gustaría escuchar en primer lugar. El tipo de letra y papel o pergamino que les guste, los colores, etc. y así tener una mejor experiencia de usuario.

Pero la demanda sube y sube y los programadores escribientes no se dan a basto.

Muchos están tratando de automatizar algunas cosas, creando formatos con espacios en blanco donde pueda ir el mensaje customizado.

Hay quienes invierten en mecanismos de relojería capaces de tomar las plumas y la tinta y reproducir la caligrafía de los escribientes de manera asombrosa, pero aún es una solución demasiado sofisticada y cara.

También hay por ahí un tipo proponiendo el uso de unos moldes de letras y tipos movibles.


Bueno, como habrás notado, estamos en el siglo XXI con un patrón de problema del siglo XV.

Sabemos cómo sigue la historia.

Sí, la imprenta fue algo muy importante que ayudó a difundir más fácilmente los textos. Pero lo que realmente cambió al mundo fue que la gente estaba usando textos para cambiar su vida.

El conjunto papel y lápiz, pergamino y tinta fue potenciado por la imprenta.

Hoy hay sistemas equivalentes a pergaminos caligrafiados. Con escribientes defendiendo con su corazón por qué usar ese tipo de pergamino y tinta, y ese tipo de caligrafía. Casas de escribientes tratando de tener a los mejores o formarlos lo más pronto posible, porque el mercado no espera.

Curiosamente, nadie parece preocuparse por dar a la gente papel y lápiz que pueda usar sin necesidad de ser educado en las artes de escribiente.

Porque eso es lo que necesitamos ahora. Una herramienta que permita programar a cualquier persona, sin necesidad de ser educada en las artes, o la profesión, de la programación.

Sí, Internet es algo muy importante que ayuda a difundir más fácilmente el conocimiento y a comunicarnos. Pero lo que realmente está cambiando al mundo es que la gente está usando a los programas para cambiar su vida.

Necesitamos dejar de depender de escribientes que lo hagan por nosotros. Necesitamos nuestro propio papel y lápiz para programar nosotros mismos el mundo que imaginamos.

Escribir no es solo un arte o una profesión; es un derecho. Igual programar.



2017/04/04

Termux para programar en un android

Termux (https://termux.com) es una aplicacion que emula una consola Linux en el Android.

Una vez instalada, se puede instalar ssh:

$ apt update
$ apt install openssh
$ ssh myuser@myserver.com

Una vez conectado a un servidor, se puede usar los comandos Linux de ese servidor.

Yo probe entrar a un servidor en Digital Ocean, crear un proyecto React, usar el editor vim, ejecutar el proyecto y ver el resultado en una pagina web, abierta en Chrome en el mismo celular (Android reconocio alternar  entre aplicaciones con Alt+Tab).

Si ademas cuentas con un teclado conectado via bluetooth, la sensacion puede ser como la de tener una mini laptop con touchscreen ^^

Tip:
En Termux, para abrir mas de una consola, arrastrar el dedo desde afuera del borde izquierdo hacia adentro.

2017/02/22

Imprimir formas en consola

En un aviso de Workana encontré un pedido como este:

Escribir un programa que pregunte al usuario elegir una forma para dibujar en la pantalla.
La forma puede ser: Circle, X, Box y un Box con una X.
También el usuario indica cuántas filas se usarán para dibujar la forma.
La forma debe ser dibujada con asteriscos (*).

Me parece que se trata de un programa para correr en consola.

En mi caso, me pareció más práctico intentarlo con php.

shapes.php

<?php
do {
 print "1. Circle\n";
 print "2. X\n";
 print "3. Box\n";
 print "4. XBox\n";
 fscanf(STDIN, "%d\n", $option);
} while (!$option);

do {
 print "Number of rows: ";
 fscanf(STDIN, "%d\n", $rows);
} while (!$rows);

for ($i=0; $i<$rows; $i++) {
 for ($j=0; $j<$rows; $j++) {
  $print_dot = false;
  switch ($option) {
   case 1:
    $print_dot = is_circle($i, $j, $rows);
    break;
   case 2:
    $print_dot = is_x($i, $j, $rows);
    
    break;
   case 3:
    $print_dot = is_box($i, $j, $rows);
    break;
   case 4:
    $print_dot = is_xbox($i, $j, $rows);
    break;
  }
  if ($print_dot) {
   print "*";
  } else {
   print " ";
  }
 }
 print "\n";
}

function is_circle($i, $j, $rows) {
 $r = $rows - 1;
 $d = pow(($i - $r/2), 2) + pow(($j - $r/2), 2) - pow($r/2, 2);
 return abs($d) <= $rows/3;
}

function is_x($i, $j, $rows) {
 return ($i == $j) || ($j == ($rows-1) - $i);
}

function is_box($i, $j, $rows) {
 return ($i == 0) || ($j == 0) || ($i == $rows-1) || ($j == $rows-1);
}

function is_xbox($i, $j, $rows) {
 return is_x($i, $j, $rows) || is_box($i, $j, $rows);
}


El ejercicio me pareció interesante para ver una manera simple de tomar una entrada desde consola. Y cuando llegué a la parte de impresión de formas me pareció más interesante. En particular la del círculo, que dejé para el final.

Algunos conceptos de coordenadas y geometría analítica me ayudaron a completar el programa.

El problema del círculo es, en el fondo, cómo imprimir una imagen en un medio de baja resolución.

Esta es la forma en que se me ocurrió resolverlo, con una especie de detección de borde seteado a $rows/3, al tanteo (para que se vea bien el círculo en 4, 8 o 16 filas).

Seguramente hay muchas maneras de resolverlo. ¿Cómo lo harías tú?


2017/02/17

Invertir una cadena con javascript

¿Cómo harías una función que invirtiera una cadena dada?
Es decir que f("abcdef") sea "fedcba".


Yo pienso que no hay una "forma correcta" de resolverlo. Simplemente hay formas, y cualquiera que se te ocurra y haga el trabajo está bien.

De todas esas formas habrá algunas que logran hacerlo con menos variables o menos código, o usando técnicas esotéricas. Formas optimizadas.

Hay programadores que se familiarizan con esas técnicas optimizadas y las aplican luego directamente en los siguiente problemas que enfrentan. Puede ser impresionante, como cuando ves a un mago sacando del sombrero cosas que no creías posible. Igual que con los magos, se requiere de práctica y ensayo para lograr esas cosas. Pero, igual que con los magos, no significa que esa es la forma en que todo el mundo debería pretender hacer las cosas.

La optimización prematura es la raíz del mal, es la advertencia de Knuth, comprobada una y otra vez en la experiencia de los programadores. Está bien optimizar, por supuesto, pero tiene su momento, y definitivamente no es al inicio.

En la vida real, la solución de los problemas se produce por tanteo. Como en un cuarto oscuro, estiras los brazos y tientas. Tocas algo una y otra vez, formándote una idea de lo que hay. Así, descubres la puerta hacia la solución. Una vez que la descubriste, podrías volver al punto de partida y hacerlo más rápido, en menos tiempo o de manera más elegante. Recién ahí es que se realiza la optimización. Si intentaras salir a toda velocidad al inicio, sería muy probable que te lastimaras con algún obstáculo o fueras rápido en la dirección equivocada. También sería un poco raro hacer movimientos elegantes si ni siquiera sabes a dónde vas a ir.

Así que para este problema, quizás se te podría ocurrir algo como:

// recorrer la cadena en reversa
function f(s) {
 var result = "";
 for (var i=s.length; i>0; i--) {
  result = result + s[i-1];
 }
 return result;
}

Ok, es lo primero que se me ocurrió. Veamos si se puede hacer mejor. Quizás se pueda recorrer la cadena de otro modo:

// recorrer la cadena de frente pero acumular en reversa
function g(s) {
 var result = "";
 for (var i=0; i<s.length; i++) {
  result = s[i] + result;
 }
 return result;
}

¿Y si vemos como luce con reduce?:

// usando reduce y acumulando en reversa
function h(s) {
 return s.split("").reduce(function(result, c) {
  return c + result;
 });
}

¿Y usando la notación fat arrow?:

// usando reduce y fat arrow
function j(s) {
 return s.split("").reduce((result, c) => c + result);
}

Quizás con la práctica sea esta forma la que aparezca primero en tu cabeza en el futuro. Podría ser impresionante. Pero hay que recordar que las cosas empiezan tanteando. Y que está bien.

2017/01/28

Qué hacemos



Es diferente el sentimiento de desarrollar algo sin tener que hacerlo por cumplir sino porque realmente te interesa.

En lugar de simplemente cubrir las horas por las que te están pagando, o los tickets que se acordaron para el sprint, te encuentras jugando con la idea de cómo podría ser mejor. Y cuando sabes que esas ideas podrían aplicarse, sientes como la alegría de estar yendo por un bonito camino.

Me pregunto cómo en un trabajo pagado podría incentivar ese tipo de actitud.

Me parece que podría ser cuando hay claridad en lo que se quiere lograr, y el sentimiento de autonomía.


No es una buena idea recordar a alguien que se le está pagando por hacer cierto trabajo. Eso baja el nivel de la conversación hasta el primer peldaño de la pirámide de Maslow.

Es triste que  tu jefe o tu cliente crean que solo trabajas por el pago que recibes. Tú sabes que lo haces por un propósito mayor, o te gustaría que así fuera, pero esos comentarios motivan a cumplir solo lo mínimo necesario.

Más arriba en la pirámide de Maslow, cuando las necesidades básicas han sido cubiertas, trabajamos para ejercitar las habilidades que disfrutamos desarrollar. Si recibimos algo por ello, qué bien. Pero si no nos pagaran, igual lo haríamos.

Ese es el tipo de trabajo que es difícil de entender para quienes se han acostumbrado a trabajar para sobrevivir.

Hay personas que siguen pensando así aunque sean ricas y ya no tengan procupaciones económicas. Y lo transmiten a sus hijos, familiares, amigos o colegas o empleados.

Antes, quizás era necesario pensar así para poder sobrevivir. Dejar atrás lo sueños y sacrificarse por lograr un mérito material.

Pero hoy, pensar así conduce a la extinción.

Las soluciones de antes van quedando obsoletas. Hay que ir imaginando lo que construiremos mañana mientras van cayendo los edificios a nuestro alrededor.

Las nuevas soluciones están viniendo de la mano de gente apasionada por lo que hace. Logran ver cosas que nadie más. Logran hacer cosas que nadie más.

No puedes hacer que tu hijo se enamore de la mujer que te parece que más le conviene.

Tampoco puedes hacer que un empleado sienta pasión por lo que más conviene a la empresa.

Tienes que encontrar alguien que ya lo sienta, y cuidarlo.

También puedes orientar tu empresa para que aproveche lo que sus apasionados miembros son capaces de construir juntos.


Las empresas están descubriendo que, en lugar de vender lo que haces, hay más éxito vendiendo el por qué lo haces.

Pero no es lo mismo preguntárselo a alguien que trabaja por encargo que a alguien con pasión por ello.

2017/01/21

La importancia de solucionar algo

Amazing Grace

A Grace Hopper se le dio el encargo de elaborar el manual de instrucciones de una de las primeras computadoras creadas en los Estados Unidos.

A la Marina, le interesaba averiguar de qué modo podría aprovechar el potencial de la nueva máquina Mark I.

No era común que una mujer perteneciera a la armada, y tampoco tenía los estándares de peso y talla, pero sus habilidades matemáticas le ayudaron a ser admitida y abrirse camino.

Ella propuso organizar bajo nombres más asequibles las rutinas que había coleccionado con su equipo, y un esquema para reutilizarlas con más facilidad y automatizar la generación de las secuencias binarias que eran la forma normal de programar las computadoras en aquella época.

Normalmente, para programar la solución de un problema, había que enfrentarse con el hardware y los interruptores necesarios para implementar el programa. Era como tener que atravesar continuamente una bruma mental para distinguir lo que se quería conseguir.

En cambio, usar un compilador de código tenía la ventaja de permitr pensar con más claridad en el problema que se quería resolver.

Sin embargo, su propuesta fue desechada porque el código binario generado de ese modo era más largo y menos eficiente.

Grace persisitió en ello como un proyecto personal. Desarrollando lo que vendría a ser conocido como lenguaje ensamblador, o Assembler.

Uno de sus amigos, que había estado meses con un equipo tratando de programar la solución de un problema especialmente difícil, logró hacerlo en unas horas usando Assembler.

Poco a poco, el uso del Assembler se fue extendiendo.

Años después, creó COBOL, el primer lenguaje de programación, que permitía expresar un programa en algo parecido a sentencias en inglés.

Menos eficiente pero más eficaz

Hoy en día, prácticamente toda la programación se hace con ayuda de compiladores y los lenguajes de alto nivel que aparecieron luego del COBOL. De ese modo, los problemas no solo se resuelven con más rapidez, sino también con menos errores. Y si los hubiera, son mucho más fáciles de localizar.

La propuesta de Grace de usar lenguajes de más alto nivel para solucionar problemas encontró resistencia en otros programadores que desdeñaban el código binario repetitivo, largo e ineficiente que se producía de ese modo. Ellos podían hacerlo más simple, más elegante, del "modo correcto".

Los programadores que podían programar directamente en binario no eran muchos y quizás se sentían un poco como sumos sacerdotes. Los intermediarios exclusivos entre la gente y las máquinas todopoderosas.

Los lenguajes de alto nivel tuvieron la virtud de hacer la programación de computadoras accesible a más personas.

Sigue siendo cierta la observación de que el código binario producido por los compiladores es más repetitivo, largo y menos eficiente que el que se podría producir directamente. Sin embargo, con la mejora de la velocidad de procesamiento, la programación directa en binario ya es muy poco práctica.

Es más importante llegar primero a la solución de un problema. La eficiencia del resultado se podría ir mejorando luego de eso (finalmente reemplazando código por assembler y luego por binario si el rendimiento fuera algo vital).

Algo hecho es mejor que lo perfecto

¿Qué es mejor, una solución perfecta que tarda tanto que nunca llega, o una solución que funcione?

"Done is better than perfect" es una famosa frase acuñada por la gente de Facebook.

La comunidad hacker tiene además "Primero que funcione, luego optimizas".

Y Donald Knuth, la famosa "La optimización prematura es la raíz de todo lo malo".

No son opiniones. Expresan un hecho, comprobado una y otra vez en la experiencia de los programadores y los equipos de programadores y los proyectos de programación.

Aún así, de cuando en cuando encontrarás a otros programadores o desarrolladores de software insistiendo en buscar la perfección o hacer optimizaciones durante la solución.

Es la optimización mal entendida.

Optimizar algo está bien, pero su momento es después que haya una solución.

Solo puedes mejorar algo que tienes, si no, la optimización es una falacia (y las falacias son peligrosas porque suelen tener ese aire de verdad que hace que uno las acepte si no se anda con cuidado)

Código limpio

A la computadora le da igual si el código está limpio o no.

El código limpio es una optimización orientada a los programadores para facilitar el mantenimiento del programa.

Pero, igual que toda optimización, su momento es después que tengas una solución, no antes.

Hay que disfrutar garabateando con código, esbozando algoritmos, en el proceso de concretar una solución.

Pretender escribir código limpio durante el proceso de solución es tan contraproducente como pretender pintar la versión final de un retrato directamente sobre un lienzo en blanco.

Cómo odio a los haters :-)

Hay programadores que automáticamente tienen actitudes hostiles o de desdén hacia ciertos lenguajes de programación, ciertos frameworks o ciertas librerías.

"PHP es el peor lenguaje de programación jamás inventado"

"Javascript es un lenguaje de juguete que no se puede tomar en serio"

"Todos esos frameworks son basura que complica las cosas"

Pero minimizar lo que nos disgusta no hace que nuestras soluciones sean mejores. De hecho, impide ver las soluciones de otros.

PHP es un lenguaje que ha ayudado mucho a democratizar la programación en Internet. La valla es más baja y mucha más gente puede entrar y cometer errores que hacen sonreir con desdén a ciertos académicos y profesionales. Pero ha permitido que muchas ideas geniales vean la luz. Más de la mitad de los blogs en Internet están hechos en WordPress, que es un administrador de contenidos escrito en PHP. Wikipedia está escrita en PHP. La base de Facebook también estuvo escrita en PHP.

Javascript ha evolucionado. No es solo para hacer efectos especiales en una página web. Permite crear interfaces complejas. Y en el lado del servidor, facilita el desarrollo de soluciones ligeras, asíncronas y sin bloqueos. Paypal usa Javascript en el backend. Hay quienes consideran que actualmente Javascript tiene uno de los más completos ecosistemas de desarrollo web.

Los frameworks son herramientas para resolver problemas. Como un martillo, o una sierra. Puede tomar su tiempo conseguir maestría en su uso. Muchos dedos golpeados, cortes accidentales. Y puede que no sean para todo tipo de problemas. Quizás haya herramientas más sofisticadas, o más ligeras, pero posiblemente te enfrentarás a más problemas si intentas hacer carpintería con una piedra, un cuchillo, o una navaja suiza.

Creo que siempre es más constructivo tratar de ver las buenas partes, usar esas buenas partes y evitar las otras.

También aquí es cuestión de ver el vaso medio lleno.

Referencias

2017/01/13

La falacia de "hacerlo sin frameworks"

Hay una idea difundida entre muchos desarrolladores acerca de que es mejor no usar un framework en lo posible.

El Framework F tiene las deventajas a, b y c; por lo tanto, si no lo usan, evitarán esas desventajas, concluyen.

Veamos por qué esto es una falacia (un razonamiento errado que parece correcto). Las falacias son peligrosas porque parecen correctas.


Un framework es, en esencia, un conjunto de convenciones sobre cómo usar un conjunto de librerías.

Cuando usas un framework, vas notando cómo sus convenciones condicionan el modo en que abordas las tareas y resuelves los problemas. Poco a poco, empiezas a visualizar las soluciones en términos del framework.

Esa pauta que establece el framework puede ser de gran ayuda para mantener orden y estabilidad en un proyecto. Y también para darle continuidad.

Pero también puede ser que las convenciones sean demasiado reguladoras, restrictivas o limitantes. O que haya problemas que sean de solución muy dificil o imposible en términos del framework.

Entonces tenemos:

Framework F
Pros Contras
m a
n b
p c


Para analizar qué framework elegir, sería:

Framework F Framework G Framework H
Pros m
n
p
Contras a no no
b no no
c no no

Así que si esos frameworks tienen esas desventajas, no los usemos y así las evitaremos.


Suena lógico. Sin embargo, es un error.


Lo que realmente están proponiendo es esto:

Framework F Framework G Framework H Framework X
Pros m ?
n ?
p ?
Contras a no no ?
b no no ?
c no no ?

¿Qué es el Framework X?

Es el framework (propio aunque negado) que se irá definiendo (sobre la marcha).

Las preferencias de uso, las posibilidades y limitaciones, y el contexto de trabajo del equipo de desarrollo, determinarán un conjunto de librerías y cómo se deben usar.

Es decir, un framework.


Por eso, lo que realmente están proponiendo los desarrolladores que "evitan frameworks" es:

"No uses un framework conocido (con todas sus ventajas, horas de prueba, comunidad y documentación) y usa mi framework (que aún no existe pero va a ser mejor que todos ellos)"


Si aceptas esa propuesta, automáticamente estás asumiendo un proyecto extra que deberá correr en paralelo al que quieres realizar. Porque hacer un buen framework consumirá tiempo y recursos en codificación, documentación y capacitación.

No es que te estés ahorrando el costo de usar un framework; estás asumiendo el costo de hacer uno.

"No hemos usado ningún framework, así que no tienes que aprender nada nuevo para empezar".

No es verdad. Verás que tendrás que familiarizarte con el conjunto de funciones y librerías que están usando, la forma en que las llaman y la particular (o peculiar) manera como el proyecto se ha organizado (o ha resultado ser).

Si usas un framework conocido, puedes tener más apoyo de la comunidad, documentación, casos de ejemplo, etc. Habrán más personas que ya lo conocen y están disponibles para colaborar contigo.

Es cuestión también de saber ver el vaso medio lleno y valorar las virtudes del modelo open source.

El efecto Dunning-Kruger

Es un efecto psicológico que se observa en todas las personas, de pensar que son más competentes en aquellas cosas en que realmente tienen más limitaciones:

Why Do Incompetent People Think They're So Great?


¿Estamos siendo afectados por el efecto Dunning-Kruger?

Usando las buenas partes

Creo que es importante ser claro en lo que se hace, y tratar de mostrar claramente lo que sucede cuando nos damos cuenta que está sucediendo.

Porque solamente podemos construir castillos de verdad usando ladrillos de verdad.

Reinventar la rueda es muy util para desarrollar las habilidades de invención.

Poder hacer un propio framework que sea comparable con los frameworks conocidos es algo admirable.

Pero no es el mejor camino minimizar lo que esos frameworks conocidos son para que así la tarea de competir con ellos resulte más fácil o nuestro trabajo parezca más meritorio.


Siempre es posible encontrar algo desfavorable en un framework, algo que no puede hacer tan bien y que quizás nosotros podamos hacer mejor (en un contexto más simple, aisladamente).

Me parece más interesante juzgar los frameworks en función de las cosas favorables. De lo que nos permiten hacer. De los problemas que nos pueden ayudar a resolver.

Porque tampoco podemos construir castillos con ladrillos que no tenemos. Hay que usar lo que sí tenemos.


Hay una cita de Addy Osmani como recomendación acerca de los frameworks:

“First do it, then do it right, then do it better.”

Primero usa lo que hay, conócelo realmente. Si encuentras algo que mejorar, corrígelo. Luego intenta hacerlo mejor.