La dificultad del trabajo final de Ingeniería de Software 2 @fiuba

El trabajo final de la materia consiste en resolver una problemática de negocio a partir de la implementación de una solución basada en software. Hasta aquí puede sonar como tantos otros trabajos de una materia de una carrera de sistemas. Pero en nuestro caso hay un par de cuestione (que tal vez tampoco son tan novedosas) que a los alumnos les cuestan bastante.

La primera cuestión es que no hay «un enunciado» ni una lista de funcionalidades, hay un «cliente» (rol ocupado por uno de los miembros del equipo docente) con un problema de negocio, los alumnos deben relevar el problema y plantear un proyecto para solucionarlo. Son los alumnos los que tienen que identificar las funcionalidades, darles forma de stories validarlas con el cliente, diseñar, codear, testear e implementar. Parece una desafío usual en una carrera de sistemas pero a pesar de eso muchos alumnos no saben por dónde empezar. Incluso cuando se supone que en materias anteriores ya vieron técnicas para lidiar con relevamiento y modelado de dominio.

Otra cuestión es que el proyecto deben desarrollarlo en 3 semanas, con iteraciones semanales al estilo XP. Eso implica planificar el trabajo a alto nivel (release plan) y también semana a semana, ejecutar dando visibilidad en un esquema de entrega continua y al final de la semana revisar lo realizado tanto a nivel producto como a nivel proceso. Insistimos en que el trabajo sea time-boxed lo cual implica que en caso de retrasos negocien/gestionen alcance. No hay problema en que no logren completar el plan de la semana siempre y cuando lo gestionen. No puede ocurrir que prometan X y luego caigan sorpresivamente a la revisión con menos de X. Seguir este proceso les cuesta muchísimo, en parte porque no tienen práctica en planificación, es un tema que tal vez vieron en alguna materia anterior pero casi sin práctica. Lo otro que suele constarles mucho es la negociación/gestión del alcance. En general si planifican X, hacen lo imposible por cumplir con X cuando muchas veces sería mucho más conveniente gestionar un recorte de alcance o simplemente avisar el cliente que no llegarán a cumplir con el plan. Incluso en ocasiones dejan de lado las buenas prácticas (modularización, testing, convenciones, etc, etc) lo cual no hace más que aumentar/generar deuda técnica que deberán pagar en el corto plazo.

Una de las cuestiones más novedosas para los alumnos es tener que lidiar con dos ambientes cloud, uno de pruebas y otro de producción. Esto en general no lo han hecho en ninguna materia. Esto por momentos se convierte en un gran desafío cuando algo les funciona localmente pero no en los ambientes cloud. Si bien les damos la infraestructura pre-armada y acceso a un log centralizado, muchas olvidan escribir mensajes de log con cual es como si estuvieran a ciegas. Esta cuestión de «build for operations» es uno de los temas de la materia y no esperamos que traigan conocimientos previos.

Finalmente lo que más me llama la atención es cuando los alumnos no aplican los conceptos que hemos estudiado durante toda la materia. El trabajo final juega un rol de trabajo integrador, previo a eso los alumnos trabajan en tareas individuales donde ponen en práctica diversos conceptos. Luego en el trabajo final deben volver a aplicar los conceptos ya estudiados pero ahora en un problema más complejo y trabajando en grupo. Una y otra vez vemos grupos que parecen haberse olvidado por completo de todo lo estudiado.

Historia de dos presupuestos

En los últimos meses me contactaron para presupuestar dos proyectos en distintos contextos. Fueron dos casos radicalmente distintos a lo que suelen ser mis presupuestos.

En un caso el contacto llegó por medio de un colega que me recomendó. Resulta que la organización que me contacto estaba buscando una persona con perfil de «arquitecto» para trabajar en un proyecto de 3 meses que consistía en armar una especificación técnica/funcional para con eso salir a buscar un proveedor que se encargara de desarrollar un software acorde a la especificación. ¡Recorcholis! tres meses para armar una especificación y que luego otra organización construya acorde. Sinceramente me interesaba trabajar con la organización así que apenas terminaron de contarme la idea les dije: «no creo funcione» y a continuación les ofrecí mi ayuda para armar un plan con mejores probabilidades de éxito. Creo que no lo convencí pues no me han vuelto a llamar 🤷‍♂️.

El otro caso fue bastante distinto me contactaron unos colegas de confianza, con quienes ya he trabajado, para armar una propuesta para un servicio de mentoring/capacitación/acompañamiento. Si bien es el tipo de trabajo que realizo habitualmente en este caso la propuesta era para un trabajo de +4 meses. En general mis propuestas, al menos inicialmente, son bastante más acotadas, unas 10 o 20 horas y luego vamos viendo y extendiendo si resulta necesario. De todas formas, en este caso parece que la propuesta ya está en proceso de aprobación, en un par de semanas les cuento ✌️.

Estimación y Planificación en contextos de Entrega Continua

Cuando una organización y/o equipo pretende comenzar a trabajar en un esquema de entrega continua, se pone un esfuerzo casi exclusivo en cuestiones de automatización lo cual en muchos casos no resulta bien.

Trabajar en un esquema de entrega continua requiere automatización pero también algunas otras cuestiones que son incluso necesarias para poder automatizar. La automatización en un contexto de entrega continua incluye principalmente la automatización de pruebas y de despliegues. Ahora bien, para automatizar pruebas y despliegues es necesario tomar ciertas «precauciones» en términos de arquitectura y diseño. Pero eso no es todo, si queremos trabajar en un esquema de entrega continua, entonces nuestro trabajo de planificación debe estar en línea con ello.

Es muy difícil (por no decir imposible) trabajar en un esquema de entrega continua si cada story/funcionalidad lleva semanas de desarrollo. Es clave que podamos particionar las stories/funcionalidades de forma tal de poder completarlas en un par días. Al mismo tiempo, la entrega continua implica, como su nombre lo indica, entregar continuamente, o sea: (casi) todos los días. Si cada story/funcionalidad lleva semanas, entonces es posible que nuestras entregas sean cada un par de semanas. En cierto modo es como un efecto en cadena: cuando más grandes las stories, más tiempo insume su desarrollo y más tiempo insume su pruebas y más tiempo insume su despliegue y más riesgos enfrentamos, etc, etc.

Desde otras perspectiva, ocurre que cuanto más diferimos la entrega, mayor relevancia toman nuestras estimaciones. Si hacemos esperar a nuestros usuarios/clientes, aumentamos su «ansiedad» y su necesidad de saber cuanto más tendrán que esperar.

Por otro lado, si trabajamos en pequeños incrementos habilitamos la entrega más rápida y continua, lo cual nos saca presión de estimación. Al mismo tiempo, las técnicas y dinámicas de estimación no son precisamente las mismas de cuando pretendemos hacer entregas frecuentes/continuas que cuando apuntamos a entregas esporádicas a mediano y largo plazo.

En línea con todo esto, estoy armando un taller muy práctico sobre diversas técnicas para estimar y planificar en contextos de Entrega Continua. Aún no tengo fecha, pero los potenciales interesados pueden escribirme para que los mantenga al tanto.

Libro Recomendado: Getting Real

Hace un par de días que terminé de leer Getting Real. Me parece que no es un libro demasiado conocido a pesar de tener casi 20 años. Yo lo tenía en mi lista de pendientes desde hace un tiempo porque uno de sus autores es David Heinemeier Hansson (conocido como «DHH», creador de Ruby on Rails).

La lectura me resultó muy amena, en parte por sus capítulos cortos (1 o 2 páginas) y en parte por ser contenido muy práctico: en cierto modo cada capítulo es un consejo sobre algún tema concreto sobre el desarrollo de productos web.

Creo que este libro es una lectura obligatoria para todo aquel que pretenda crear productos online/digitales.

Debo admitir que no estoy de acuerdo con todo lo que dice pero sí estoy totalmente de acuerdo con la mayoría de las cuestiones que plantea.

Es importante destacar que varias de las cuestiones que proponen los autores son, a mi parecer», de aplicación «universal» pero algunas otras claramente aplican puntualmente a escenarios de «startups».

Libro recomendado: Joy of Agility, how to solve problems and succeed sooner

Compré este libro pura y exclusivamente por el autor: Joshua Kerievsky. Su libro «Refactoring to Patterns» me resultó excelente. Luego tuve la oportunidad de conocerlo personalmente allá por 2009 y desde entonces lo sigo. En general coincido con las ideas que comparte y por eso cuando vi este nuevo libro, «Joy of Agility», no dude en comprarlo.

Lo empecé a leer e inicialmente pensé que no me gustaría. Me parecía que era como muy filosófico, poco práctico, medio humo. Pero a pesar de esa sensación inicial seguí leyendo.

Lo terminé de leer hace unos días y debo decir que me gustó. Algo que me ayudó mucho a la lectura es que los capítulos son cortos, apenas dos páginas en muchos casos.

En cierto modo el libro es como un compendio de «anécdotas con moraleja». Cada capítulo cuenta una de estas anécdotas y termina con una moraleja/consejo que obviamente está relacionada a la agilidad.

Las anécdotas me resultaron muy entretenidas y muchas de ellas también muy útiles y de aplicación directa a mis tareas cotidianas.

Ojo, no es un para todo el mundo, si esperas ver código y demás nerdeadas, no es por acá. Pero si te consideras: agilista, coach, facilitador, agente de cambio o similar, entonces no dejes de leerlo.

Nuevo Stream de Desarrollo de Software

Con los miembros del equipo de la materia de Ingeniería de Software de UNTreF, Diego Marcet y Gonzalo Cozzi, decidimos hacer un experimento: un stream.

Vamos reunirnos una vez por semana a desarrollar una aplicación de punta a punta aplicando las prácticas de desarrollo que habitualmente enseñamos en nuestra materia y lo vamos a hacer mientras los transmitimos por YouTube. La idea no es solo mostrar código sino también tener las discusiones/decisiones que típicamente surgen en cualquier equipo de desarrollo.

En principio vamos a hacer una transmisión por semana por YouTube, los días miércoles en el horario de 19:00 a 21:00 (hora argentina, GMT-3) comenzando la semana próxima, el miércoles 26 de marzo.

Hablaremos (e implementaremos) de BDD, TDD, Integración Continua, Trunk-Based Development, Pair-Programming, Feature Flags, Infra as Code, Continuous Delivery, DevOps, Patrones, Arquitectura, Calidad y mucho más.

Los interesados nos vemos aquí en el miércoles próximo, pasen y vean.

Los dos estilos de backlogs

El término «backlog» alcanzó una gran popularidad de la mano de Scrum llegando incluso a trascenderlo. Muchos utilizamos en la actualidad el término «backlog» aún sin estar trabajando necesariamente con Scrum. En este sentido he visto enfoques de uso de backlog muy diversos entre los que me parece destacan 2.

En un extremo está la visión más cercana a Scrum donde el backlog está centrado en el producto, sus ítems están expresados en términos negocio, típicamente con forma de user stories y épicas.

En el otro extremo tenemos un backlog que representa el trabajo por hacer y si bien todos sus ítems tienen alguna relación con el producto/servicio que estamos construyendo, esa relación no siempre es tan directa o evidente. El backlog es en este caso una herramienta de gestión del trabajo y en parte por ello sus ítems no siempre toman la forma de user stories, sino que muchas veces son tareas.

He visto equipos trabajando con uno u otro enfoque de backlog y también he visto equipos trabajando con ambos tipos de backlog en simultáneo. Y obviamente también he visto equipos trabajando con enfoques distintos a estos dos.

En lo personal, y desde mi posición de miembro del equipo de ingeniería, tiendo a inclinarme por el segundo enfoque, es fundamental para mi tener en bien en claro y visible todo el trabajo por delante. Me ha pasado de trabajar con equipos «novatos» en términos de gestión que intentan trabajar con un backlog puramente de producto y que pierden de vista tareas indispensables para la entrega de valor como ser la gestión de ambientes, configuración y demás tareas relacionadas a la puesta en producción.

De regreso al Desktop 15 años después

Duramente más de 15 años trabajé con una computadora portatil independientemente de si trabaja en la oficina de un cliente o en mi oficina. En este último caso solía usar dispositivos externos(monitor, teclado y mouse, etc) para trabajar más cómodo.

Hablo en pasado porque hace un par de meses decidí comprar una computadora de escritorio para dejarla fija en mi oficina. Una de las principales motivaciones para esto fue contar con Linux, ya que mi computadora portatil es MacOS y eso me trae dificultades cuando tengo que dar soporte a mis alumnos que en su gran mayoría no usan MacOS. Por otra lado yo había dejado de usar máquina de escritorio por el tamaño físico de los gabinetes que realmente me resultaba incómodo. Pero resulta que desde hace un tiempo hay mini-pcs muy potentes. Así que con todo esto en mente comencé a investigar para comprar una mini-pc y ponerle Linux.

Luego de varias averiguaciones decidí comprar una mini-pc Bmax B4 Pro, 16 GB de RAM y 500 GB de disco. Vino con Windows 11 Pro de fábrica, el cual decidí conservar e instalarle un Linux en paralelo. La decisión de la distribución de Linux ya lo compartí en un post anterior: ubuntu.

Todo el set de periféricos ya lo tenia, paso a detallar:

  • La BMax viene con dos puertos HDMI en los cuales conecté mis monitores gemelos Dell. Nota al margen para el modelo del monitor: Dell P2018h de 20 pulgadas, una joya, puede ponerse en orientación vertical y funciona como hub USB (tiene 4 entradas USB), conexión HDMI, VGA y DisplayPort.
  • Camara USB Logitec C922 Pro Stream Full Hd.
  • Parlantes Edifier R1000TCN
  • Micrófono USB Fifine K669B
  • Impresora laser Samsung M2020w
  • Teclado y Mouse estoy utilizando los de una vieja iMac conectados por USB. Hice una configuración custom en el Linux para que el mapeo de teclas resulte igual al que tengo en la MacBook.

Con todo esto, del CPU salen 5 cables: alimentación electrica, 2 hdmi para los monitores, audio y un USB para el monitor que funciona como hub. A su vez el monitor hub recibe: cámara, micrófono, impresora y teclado (que a su vez tiene conectado el mouse).

Luego de 1 mes de trabajo con este setup estoy muy cómodo.

Pair-Programming: una práctica subestimada y malinterpretada

La práctica de Pair-Programming es en mi opinión una práctica poco utilizada. Creo que muchos la prueban en algún momento pero luego la abandonan. Al mismo tiempo creo que mucha gente tiene una idea equivocada de lo que es esta práctica.

Respecto de la mala interpretación: la idea general es que dos personas trabajan juntas en una única máquina. Eso no es pair-programming, o mejor dicho faltan cosas. La práctica de pair-programming implica una serie de cuestiones adicionales como ser: cada uno de los programadores tiene un rol que va rotando siguiendo una dinámica predeterminada de forma tal que el teclado de cambia de manos, se trabaja en pequeños incrementos, etc, etc.

Respecto de la subestimación: hay gente que cree que esta práctica baja la productividad y por ello algunos se oponen a su uso. La realidad es que hay varios estudios desde hace mucho tiempo que demuestran que esto es falso, ya escribí sobre esto hace un tiempo.

Ahora bien, justamente por estas dos cuestiones es que en mis cursos de ingeniería de software estudiamos y practicamos pair-programming y en general tiene una muy buena aceptación por parte de los alumnos (más detalles en otro post).

En lo personal hago mucho pair-programming con los equipos que trabajo y suelo complementarlo con otras prácticas como trunk-based development, integración continua y TDD. Creo que justamente el combo de prácticas es lo que hace «que cierre».

Sobre la Orientación a Objetos y su pobre uso en la actualidad

La programación orientada a objetos (POO) tiene ya más de 40 (¿50?) años y sin embargo….

Para empezar me parece importante destacar el hecho que la POO no solo es una «tecnología de programación» sino algo mucho más amplio: es un paradigma. Esto implica que además de programar utilizando ciertas herramientas (encapsulamiento, polimorfismo, etc, etc), también tiene impacto en la forma en que planteamos los problemas y diseñamos nuestras soluciones.

Hoy en día creo que todos los lenguajes de programación de uso masivo tienen soporte para POO. Al mismo, en las carreras universitarias de sistemas se enseña POO.

Sin embargo, una y otra vez vemos (en la industria y en la academia) soluciones que utilizan objetos pero que no son orientadas a objetos. Abundan las soluciones con objetos contenedores de datos por un lado y objetos con lógica/algoritmos (pero sin datos) por otro. Para el resto del artículo me voy a referir a estas soluciones como «soluciones procedurales (SP)». Este fenómeno de «datos por un lado» y «comportamiento por otro», no es nuevo. De hecho hay varios frameworks que proponen este enfoque. Ya desde los años 2000 J2EE proponía nombre a estos objetos: «session beans» y «entity beans». Esta estrategia puede resultar práctica e incluso conveniente pero es contraria a la propuesta de la orientación objetos donde se supone que cada objeto encapsula dentro de sí, datos y los algoritmos que operan sobre esos datos.

A esto se suma al hecho de que hay gente que cree que construye soluciones orientadas a objetos porque usan clases, herencia, y demás herramientas de la OO pero que en realidad son soluciones procedurales porque siguen separando datos y comportamiento.

No digo que esté mal hacer soluciones procedurales, de hecho creo que hay situaciones donde este enfoque puede ser el más conveniente. Pero esta confusión entre soluciones procedurales y soluciones orientadas a objetos traen dos situaciones potencialmente problemáticas.

Un problema es cuando decimos (o creemos) estar haciendo algo (una solución OO) pero en realidad estamos haciendo algo distinto (una solución procedural).

El otro problema es usar un enfoque cuando en realidad sería mejor utilizar el otro.

Los primeros 15 años de mi trabajo docente fue intentando enseñar POO y por ello soy consciente de la dificultad de enseñar/aprender este tema. Hoy en día en los cursos que dicto en la universidad se supone que los alumnos ya llegan sabiendo OO aunque lamentablemente en la mayoría de los casos vemos importante falencias. Creo que en parte esto se debe a que muchas veces se enseña OO utilizando «problemas simplificados», o sea: los alumnos saben hacer modelos computables orientados a objetos de ciertos problemas, pero sin tener que lidiar con infraestructura (interfaces de usuario, persistencia, etc.).

Lo que veo en mis cursos es que cuando les planteamos problemas en los que tienen que lidiar interfaces de usuario, persistencia, etc, se «desvían» y terminan haciendo soluciones procedurales :-(.