archivo

Archivo de la etiqueta: programación

Interesante la reflexión que Martin Fowler realiza en su libro “Refactoring: Improving the Design of Existing Code” (traducción libre): “Al compilador no le preocupa que el código sea feo o limpio. Pero cuando cambiamos el sistema, hay una persona involucrada y ahí sí que importa. Un sistema mal diseñado es complicado de modificar”.

En última instancia somos las personas las que tenemos responsabilidad sobre la deuda técnica no hay nadie más entre nosotros y el código. Es cierto que podemos apoyarnos en generadores de código y en frameworks pero es decisión de la organización, del departamento o nuestra elegirlos y en muchos casos de su evolución. Son importantes en cuanto a que te evitan la realización de tareas mecánicas y en cuanto a que marcan un camino común en el desarrollo pero hay que tener en cuenta que es importante que el código generado sea de calidad porque es posible que en un futuro el equipo que se vaya a encargar de seguir evolucionando el producto no disponga de ese generador (desgraciadamente es algo que casi nunca se tiene en cuenta).

Hay software como Sonar que utilizado de manera conjunto con un software de integración continua nos permite conocer al día el estado de la deuda técnica pero se trata solo de métricas que nos pueden alertar de situaciones anómalas (o potencialmente anómalas) al final habrá una persona (no necesariamente un gestor ya que el programador también tiene mucho que ver en esto) que tomará la decisión de refactorizar o no determinadas partes de la aplicación.

Lo más recomendable es que la propia refactorización sea parte del proceso de desarrollo que surja como algo natural y que nos apoyemos en software para conocer si hay módulos en donde el trabajo de refactorizar no ha sido suficiente o no ha sido bueno.

Este antipatrón surge como consecuencia de múltiples cambios en una aplicación que se llevan a cabo de forma simultánea en el mismo, de manera que es posible que se haya aplicado la misma solución en diferentes partes del código, de manera que tendremos clases y/o métodos con un comportamiento parecido aunque tengan codificación diferente.

También es posible que se haya llegado a él, no por el hecho de no poder controlar la programación de personas distintas en diversas funcionalidades de la aplicación, sino por la mala práctica de ir copiando secciones de código, realizando las modificaciones oportunas, achacándolo a las prisas y a la presión por la entrega y/o por terceros.

Como consecuencia tenemos un código más complejo, con más deuda técnica y, por tanto, con un mayor esfuerzo de evolución y mantenimiento (hay que tener en cuenta que es posible que con estas prácticas, para hacer un cambio sea necesario hacer modificaciones en tantos puntos como ese código haya sido replicado).

El desarrollo de software es un continuo adelante y detrás no solo fruto del feedback o del cambios en las especificaciones sino también como parte del proceso de construcción. ¿Quién no tiene que corregir errores?, ¿quién no mejora una sección del código que no termina de convencerle?, ¿quién no tiene que realizar ajustes como consecuencia de evolución solicitada por el área usuaria?.

Este tema lo traté en artículo: “¿Qué es el mantenimiento?” y lo vuelvo a hacer ahora porque realmente el hecho de que en el desarrollo de software la frontera entre la construcción y el mantenimiento sea tan débil (por no decir inexistente) me parece muy interesante ya que refleja un aspecto inherente al desarrollo de software como es su naturaleza evolutiva, es decir, el sistema se desarrolla poco a poco y con el paso del tiempo va adquiriendo forma, en todo ese proceso hay evolución y no solo por los aspectos funcionales (o no funcionales) que se van añadiendo, modificando o eliminando sino porque en ese proceso el software también cambia y no necesariamente para cambiar una funcionalidad (refactorización, corrección de incidencias, etc…).

Esta naturaleza evolutiva junto a otra característica inherente al proceso de desarrollo como es la incertidumbre ponen de manifiesto que el software estará sometido a cambios a lo largo del proyecto (por muy diversas causas) y que será necesario habilitar los mecanismos necesarios para que la adaptación a los mismos se realice lo antes posible.

Me gusta el enfoque que Dave Thomas da sobre este tema (traducción libre): “Si nos fijamos en el tiempo que pasamos programando, escribimos un poco y luego volvemos atrás y hacemos un cambio. O volvemos atrás y corregimos una incidencia. O lo tiras todo o lo reemplazas por otra cosa”.

“Ya he terminado”, “esto ya está hecho”. Puede parecer que todos interpretamos lo mismo pero no es así. En absoluto es así.

En muchos casos “estar hecho” significa que ha programado la funcionalidad y que en el mejor de los casos le ha hecho un testing por encima a la misma, en otros casos “estar hecho” implica haber verificado en profundidad que funcione.

Muchas veces hemos podido escuchar sobre una persona: ¡qué rápido programa!. La velocidad de programación solo es un indicador válido si se contrasta con el número de errores que se han entregado y con la calidad del código.

Es importante que a personas con menos experiencia les indiquemos que es importante entregar pero todavía más importante entregar bien o lo que es lo mismo, es importante que todos tengan una interpretación común de lo que significa “estar hecho”. Si haces tu trabajo rápido y después hay que dedicar el doble de esfuerzo para ponerlo bien (y eso si se han detectado los errores a tiempo y no han llegado a producción) se han creado más problemas que soluciones.

Cuando hablamos de mejorar la productividad o velocidad del desarrollo no solemos pensar en primera instancia en que ese software hay que probarlo, algo que es un error muy frecuente.

De hecho no se puede hablar de incremento de la productividad o de la velocidad si no va aparejado de un mantenimiento o mejora de la calidad de los entregables. De nada sirve llegar una semana antes si después te tienes que llevar dos semanas corrigiendo errores (en el mejor de los casos).

Ya sabemos que el testing se trabaja a distintas escalas, desde las pruebas unitarias, pasando por las de integración hasta llegar a las de sistema/aceptación. En función de la estrategia de desarrollo que utilices podrás trabajar a nivel de testing a menor o mayor nivel pero en ningún caso se puede renunciar a comprobar si lo que has desarrollado funciona y se corresponde con las especificaciones y esta tarea recae en el propio desarrollador y en personal dedicado al testing (si se dispone de él).

Estoy harto de ver casos en los que los desarrolladores no prueba de manera adecuada el software que desarrollan e independientemente de que en algún caso pueda haber dejadez, lo que falla principalmente es la técnica, aunque parezca mentira se puede saber programar estupendamente y después no tener ni idea de cómo hacer un testing efectivo.

Para terminar, os dejo una cita de Mary y Tom Poppendieck (traducción libre): “No importa lo rápido que desarrolles software si no eres capaz de hacerle un testing a la misma velocidad”.

Si un usuario tiene dudas sobre el comportamiento de una funcionalidad y prevé la evolución de la misma en un futuro y no se sabe a ciencia cierta si se van a disponer de recursos en un futuro para poder realizar los cambios, nos encontramos ante una situación candidata a aplicar una solución configurable (teniendo en cuenta que tampoco podemos hacer magia y que el número de opciones de configuración serán limitadas).

Por ejemplo, recuerdo hace tiempo un sistema donde a una entidad se le podían asociar determinados tipos de características. Cada vez que repasábamos con el usuario la pantalla principal en la que se trabajaba con esa entidad incluía y eliminaba nuevas características, lo que provocaba que continuamente se tuviera que estar modificando el modelo de datos. También nos comentó que independientemente de las características que se terminaran incluyendo en un futuro les podría resultar interesante incluir nuevas relaciones. ¿Qué solución le dimos? Implementar las características asociada a la entidad como un casilla/valor. En ese momento terminaron los problemas. ¿Es la solución más elegante? No, ¿es la más académica? No, pero fue realmente práctica y efectiva.

Los desarrolladores tenemos la tendencia a creernos mejores de lo que realmente somos. Afortunadamente el día a día nos pone de nuevo los pies en el suelo cuando los resultados que obtenemos distan de las posibilidades que teníamos.

Alejarnos del día a día ya sea porque vamos escalando en la organización o porque se realizan tareas que no están relacionadas con proyectos supone alejarnos de lo que nos pone los pies en el suelo y esa arrogancia crece y no parece tener freno.

La arrogancia también llega cuando no asumimos los errores (siempre es culpa de otro o simplemente los ignoro) o cuando se tiene una buena racha de resultados (probablemente hayas tenido que ver en ello pero no serás el único responsable).

La arrogancia crea distancia con los demás tanto si pertenecen a tu equipo como si se trata de la otra parte en una relación cliente/proveedor. Si eres bueno no hace falta ser arrogante para que te respeten.

La arrogancia te hace bajar las defensas, es lo que tiene creerte invulnerable. Cuando bajas la tensión y cuando disminuyes la atención es cuando mas posibilidades hay de cometer errores. Es una demostración más de que la arrogancia no te engrandece sino que te empequeñece.

Un ejemplo de esto último lo tenemos en la siguiente cita de Dave Thomas: “Si asumes que puedes producir un software libre de errores, tu actitud cambia cuando lo escribes. Tiendes a ser arrogante o por lo menos complaciente con el código que escribes”.