2019/09/14

Sobre desarrollo de software


La administración de la energía creativa sería la clave para un proyecto exitoso

Desarrollar software es un proceso que se viene descubriendo.

Hay quienes han intentado amoldarlo a un esquema como el que se sigue en la ingeniería o la arquitectura. Parece funcionar en algunos casos, pero no ha resultado satisfactorio siempre.

Aún hoy, décadas después de creada la ingeniería de software o las ciencias de la computación, a veces no es claro por qué un proyecto de desarrollo que parece bueno fracasa. O por qué uno que parece absurdo temina triunfando sobre todas las demás opciones.

Algo que hay que tener en cuenta es que el software no solamente debe correr en la computadora, sino en el sistema determinado por las personas que lo usen.

La ingeniería de software y las ciencias de la computación suelen concentrarse en cómo crear algoritmos que corran eficientemente en una computadora. La UX, o experiencia de usuario, se concentra en cómo sintonizar con las necesidades reales de las personas que usarán la solución que se desarrolla.

Desarrollar software no es como realizar una tarea, donde cada paso es sobre terreno conocido. Es más como resolver un problema. Es decir, es como avanzar por una curva cuyo curso no es evidente. Hay que recurrir a la experiencia pero también a la intuición. Como cuando se hace arte.

Me parece que la mejor manera de desarrollar software es iterádamente, iniciando con una base muy simple y luego ir evolucionando para alcanzar lo que se requiere.

Esto requiere un proceso de desarrollo que sea sostenible y escalable. Sostenible significa que se pueda repetir una y otra vez el ciclo de mejora. Escalable significa que puede soportar el siguiente estado de evolución del producto.

Muchos desarrolladores se preocupan mucho por si el producto es escalable. De si podrá soportar diez veces más usuarios, o cien veces más datos. Creo que más importante que la escalabilidad del producto es la escalabilidad del proceso para desarrollar el producto.

Creo que la razón principal por la que los proyectos de desarrollo de software a menudo fracasan es porque no logran formar un proceso de desarrollo escalable. Suelen usar un esquema de producción en línea, como en una fábrica donde cada pieza es conocida, en lugar de espiral, como en un laboratorio donde cada pieza se está ensayando sobre un diseño que se va descubriendo. Conforme la complejidad aumenta, distintas partes del proyecto van cayendo bajo su propio peso, hasta que todo colapsa. O sigue adelante con montones de parches y apuntalamientos de emergencia que hacen que no sea posible continuar con su evolución de manera clara.

Quizás esto se pueda ver mejor considerando que existe una energía creativa. Es la energía con la que se cuenta para convertir una idea en un producto de software.

Mientras no se llega a  un un producto concreto, la energía creativa va disminuyendo. Es como cuando un móvil se va empujando. Para que gane altura o gane velocidad, hay que gastar energía empujándolo contra la gravedad o la fricción. Cuanto más largo es el salto, más fuerza, velocidad y energía se requieren.

Pero cada vez que se llega a un producto concreto, ganamos un nuevo punto de apoyo para dar el siguiente paso desde allí. Esta energía permite ir por una siguiente versión. Es más fácil, y más sostenible, llegar al quinto escalón desde el cuarto que desde el primero.

Podemos ilustrar esto imaginando que el proyecto es como llevar una bola de nieve cuesta arriba. Al inicio, reunimos nieve de aquí y de acá y empezamos a rodar esa bola inicial fácilmente. Conforme la bola crece, va requiriendo más energía. Entonces llegamos a una pequeña meseta. Eso nos permite recuperar energía, apreciar lo que hemos recorrido y ver mejor cómo continuar. Luego seguimos subiendo, gastando energía hasta que lleguemos a la siguiente meseta, donde nos recuperamos. En el viaje, vamos decidiendo si necesitamos ayuda de más personas para seguir empujando la bola, despejando el camino, apuntalando, etc. Cada vez requerirá más energía poder avanzar y llegar a una meseta segura. Puede ser que esa meseta sea la cima, y el proyecto llegue así a buen término. Puede ser que no sea la cima pero una meseta cercana y aceptable. O puede ser que no se encontró una meseta a tiempo y, sin un apoyo adecuado ni energía para continuar, la bola se tuvo que soltar, yéndose cuesta abajo.

Versionado frecuente. Una buena estrategia es tener mesetas frecuentes. Es decir, sacar versiones completamente funcionales frecuentemente. No importa si es un paso corto si podemos continuar andando. Los pasos acrobáticos son un lujo que puede no ser sostenible. Los periodos de desarrollo largos que no concretan van consumiendo la energía riesgosamente.

Ir ligero (LEAN). Otra buena estrategia es mantener la bola en un tamaño manejable. Es decir, ir dejando atrás aquello que ya no es necesario para que siempre podamos avanzar con los recursos que tenemos.

Dividir y vencer. Otra buena estrategia es dividir el trabajo en varias bolas que lleguen a la cima. Es decir, poder separar el proyecto en partes independientes y fáciles de manejar que puedan ser conectadas luego.

Testing (TDD). Otra buena estrategia es apuntalar el avance de la bola. Es decir, contar con pruebas de código o de flujo que validen el estado del proyecto. Se pueden poner luego de que la bola ya alcanzó cierta posición pero suele ser mejor estrategia ponerlas primero y luego mover la bola hacia allí.

Sinergia. Otra buena estrategia es rodar armoniosamente la bola. Es decir, que cada persona del equipo sintonice con el propósito del proyecto, y tenga la autonomía que le permita usar sus habilidades con maestría para colaborar en su realización.

La trampa del perfeccionismo. Una estrategia no muy buena es querer empezar con un montón de nieve demasiado grande. Es decir, requerimientos iniciales demasiado complejos, por número o por dificultad. Son más firmes las bolas de nieve que van creciendo y haciéndose redondas por su propio rodar. A menudo, querer empezar con algo que parezca perfecto para impresionar a los demás suele conducir a parálisis por análisis: el proyecto empieza a procrastinar, la energía creativa se diluye, y finalmente no despega.

La trampa de la temeridad. Otra estrategia no muy buena es ignorar la ayuda de apuntalamientos y confiar únicamente en el propio esfuerzo para mantener la bola en curso. Es decir, no tener pruebas que permitan verificar que se está donde se debe estar. Implementar pruebas requiere algo de energía creativa, pero luego permite ahorrar mucha más.

La trampa de la insensibilidad. Otra estrategia no muy buena es ignorar que quienes ruedan la bola son personas. Es decir, se cae en tentación de creer que bastan las herramientas, las técnicas o la infraestructura, o la capacidad de hacer algo, para que ese algo se pueda realizar, ignorando que hay un aspecto social, con una voz que debe ser escuchada y honrada. Hay redes de confianza que deben ser tejidas y mantenidas, para que las personas puedan realizarlo.
Hay proyectos con pendientes de dificultad muy llevaderos, donde parece que se puede ir con facilidad hacia cualquier dirección y se llega a la cima de un modo predecible.

Hay otros proyectos donde el terreno no es parejo, la nieve es irregular y sopla la ventisca.

Llevar exitosamente la bola de nieve a la cima no depende solamente de cuánta gente la empuja ni cuánta fuerza tenga. Depende de ser capaz de llegar oportunamente a las mesetas adecuadas. Es entender el terreno, el clima, la nieve, la gente, su fuerza, sus habilidades, y poder manejar todo eso.




2018/12/31

Hello Jenkins: Como root

En el post Hello Jenkins, exploré cómo podría automatizar el deploy de un site estático simple con ayuda de Jenkins.

Este site estático está alojado en mi directorio web personal ~/public_html. Para que Jenkins pudiera hacer pull allí, fue necesario que tuviera derechos sobre los archivos de ese directorio, así que opté por agregarlo a mi grupo de usuario.

Ahora exploro cómo sería si quisiera que Jenkins pudiera hacer pull en el directorio web /var/www.

En mi Jenkins, proyecto hello-jenkins, Configuration, Source Code Management:

  • En Aditional Behaviours, pruebo agregar:
    • Chek out to a sub-directory
      • Local sub-directory for repo:
        /var/www/html/demos/hello-jenkins/
Una prueba muestra un error de acceso al directorio. Probé agregar jenkins al grupo sudo y tambien visudo, pero no pude solucionarlo.

Opto por agregar el siguiente script en Build:
  • echo "hello-jenkins build"
  • cd /var/www/html/demos/hello-jenkins
  • sudo git pull
Hago la prueba y funciona como se espera. Se hace pull al hello-jenkins en mi directorio personal public_html/ y tambien en el directorio web /var/www/.


2018/12/30

Hello Jenkins


En días recientes estuve viendo un poco de Continuous Integration / Continuous Deployment (CI/CD), con Jenkins.

La idea que he captado es que Jenkins corre en el servidor donde normalmente ejecutamos a mano los pasos para deployar un proyecto. Luego configuramos las cosas para que Jenkins las haga por nosotros.

Por ejemplo, puedo tener en mi hosting un site estático hello-jenkins, cuyo repositorio está en GitHub. Luego que hago push en el repo desde mi máquina local debo entrar a la consola de mi hosting y hacer pull. Quizás alguna cosa más, como bower o npm, dependiendo de la complejidad del proyecto.

Empezaré con un simple site estático llamado hello-jenkins.

Ahora, haré un cambio y un deploy manual.
  • En mi local, agrego un title, commit y push
  • En mi hosting, hago pull
    • Lo pesado de esta tarea es cuando no estoy logueado a la consola. Es necesario hacer ssh, ubicar la carpeta y hacer pull.
    • Si Jenkins vive en este servidor, podría hacerlo por mi ante una señal. Por ejemplo, cuando se hace un push en GitHub.
  • https://rulokoba.me/~rulo/demos/hello-jenkins/
En el hosting, tengo instalado Jenkins siguiendo la guía de:
En mi Jenkins, creo el job hello-jenkins:
  • Elijo create new jobs
  • Enter an item name: hello-jenkins
  • Elijo Freestyle project
  • OK
  • En la sección de consiguración:
    • Source Code Management
      • Git
        • Repository URL: https://github.com/akobashikawa/hello-jenkins.git
        • Credentials: none
        • Additional Behaviours
          • Check out to a sub-directory
            • Local sub-directory for repo:
              /home/rulo/public_html/demos/hello-jenkins/
            • Para que jenkins pueda escribir en este directorio se le puede agregar al grupo del usuario y reiniciar jenkins:
              • $ sudo usermod -a -G rulo jenkins
              • $ sudo systemctl stop jenkins
              • $ sudo systemctl start jenkins
    • Build Triggers
      • GitHub hook trigger for GITScm polling
    • Build (opcional)
      • Execute shell
        • Command
          • echo "hello-jenkins build"
En el repo de GitHub, Settings:
  • Webhooks
    • Add webhook
      • Payload URL: http://myjenkins_url/github-webhook/
        • Es importante el trailing / al final
      • Content type: application/json
      • Which events would you like to trigger this webhook?
        • [x] Let me select individual events.
          • [x] Pushes
            • [x] Pull requests
      • [x] Active
      • Add webhook
      • Es importante que GitHub pueda encontrar a Jenkins ya configurado
Para probar, manualmente:
  • En mi Jenkins, en el projecto hello-jenkins, wlijo Build Now
  • En Build History aparecerá un nuevo item numerado, y le hago click.
  • Elijo Console Output para ver la salida
Para probar el build automático:
  • En mi local, hago un cambio, commit y push al repo
  • En Build History aparecerá un nuevo item numerado, y le hago click.
  • Elijo Console Output para ver la salida

2018/09/18

Solucionando conexión de strapi a mLab



Strapi es un framework para node que facilita la creación de un cms.
  • Como base de datos puede usar mongo, mysql, postgres.
  • Como frontend puede usar vue, react, angular.
  • El panel de administración luce bastante similar al de wordpress.
  • Tiene un plugin para servir los datos con graphql.
  • El idioma se puede configurar a español.
mLab es un servicio que provee acceso a bases de datos mongo.
  • Tiene una capa de uso gratuita (via AWS de Amazon)

Instalación simple

  • Para usarlo con mongo, debe estar iniciado el servicio localmente
  • $ node --version
    • Se requiere al menos la versión 9
  • $ npm install -g strapi@alpha
    • Por alguna razón, recomiendan que trabajemos con la versión más fresca
  • $ strapi --version
    • Actualmente 3.0.0-alpha.14.1.1
  • $ strapi new myapp
    • Creará la estructura de directorios.
    • Hay que elegir como base de datos a mongo e indicar los parámetros
      • Esta data se guarda en myapp/config/environments/development/database.json
      • La base de datos aún no se crea en este punto
  • $ cd myapp
  • $ strapi start

Problema con mongo externo

Por alguna razón, cuando se indica que se conecte a una base de datos mongo externa para development, strapi devuelve un error.

Encuentro que en la configuración para production hay una propiedad extra uri.

Cuando se usa esta propiedad uri en la configuración para development, ya es posible conectarse a una base de datos mongo externa, como mlab, por ejemplo.

Solución

  • $ strapi new myapp
    • Crear la aplicación indicando una base de datos mongo local
    • Esto aún no creará ninguna base de datos
  • Editar myapp/config/environments/development/database.json y agregar la propiedad uri:
  • $ cd myapp
  • $ strapi start
La configuración sería similar a:
{
  "defaultConnection": "default",
  "connections": {
    "default": {
      "connector": "strapi-hook-mongoose",
      "settings": {
        "client": "mongo",
        "uri": "mongodb://username:password@hostname.mlab.com:12345/dbname",
        "host": "hostname.mlab.com",
        "srv": false,
        "port": "12345",
        "database": "dbname",
        "username": "username",
        "password": "password"
      },
      "options": {
        "authenticationDatabase": "",
        "ssl": false
      }
    }
  }
}