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

Más artículos