archivo

Archivo de la etiqueta: Martin Fowler

Me parece muy interesante la siguiente cita de Martin Fowler: “Cuando aprendes una nueva técnica que incrementa sensiblemente tu productividad, resulta difícil darnos cuenta cuándo no aplicarla”.

Nos pasa a todos que cuando la aplicación de una determinada práctica y estrategia nos produce buenos resultados, queremos empezar a utilizarla en todos los proyectos. Esta idea, en esencia, es la que está detrás de todos los enfoques orientados a procesos: aplicar procedimientos que permitan de manera repetible conseguir unos determinados resultados.

Por ejemplo, cuando empezamos a aplicar prácticas de diversas metodologías o enfoques ágiles y vemos que encajan con la dinámica de un proyecto de desarrollo de software, el paso siguiente es reflexionar cómo podemos aplicarlas en el resto de nuestros proyectos, ¿cuándo sobrepasamos el límite? lo hacemos en el momento en que por encima de las características y el contexto del proyecto lo que nos importa es aplicar el método o las prácticas.

En ese preciso momento empezamos a dejar de ser ágiles y convertirnos en esclavos de procesos, enfoques o prácticas, es decir, en lugar de seguir evolucionando en nuestra forma de entender el software involucionamos hacia nuestro estado de partida.

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.

Nuestro trabajo no es conseguir imposibles.

Trabajamos con un presupuesto y tiempo limitado, es decir, trabajamos con unas restricciones. Se pueden y se deben ajustar si es necesario pero teniendo en cuenta que el chicle no se puede estirar indefinidamente.

También es frecuente que en el desarrollo normal de un proyecto nos encontremos en un momento dado con más tareas que las que podemos llevar a cabo ya sea a título individual o a nivel de equipo de proyecto.

Esto nos lleva tanto a nivel general del proyecto como a nivel de un momento determinado del mismo a una priorización de las tareas. Para ello es necesario que el área usuaria decida con criterio qué es lo más importante (teniendo en cuenta que todo tiene un coste) hasta que la dinámica de trabajo esté consolidada considerarán que todo es importante, crítico y urgente y aunque así sea (que no lo es) no tendrán más remedio que hacerlo (a veces cuesta que lo entiendan pero mejor así que darles unas expectativas que no vamos a poder cumplir). Una buena estrategia para la asignación de prioridades es la asignación por parte del usuario de un grado de importancia a la tarea del cero en adelante (la menor importancia es el cero) y sin tener la posibilidad de repetir un valor.

Hay que tener en cuenta que si aplicamos un enfoque evolutivo en el desarrollo de software el usuario irá poco a poco dándole forma a la idea general que tenía en la cabeza, la importancia de empezar por lo más prioritario permite que no se invierta el tiempo en realizar tareas secundarias dependientes de otras primarias y que podrían ser desechadas o modificadas si cambia la principal.

En eso consiste desarrollar con intención.

La visión de este problema por parte de Ken Beck y Martin Fowler la reflejan en el libro “Planning Extreme Programming” y es la siguiente (traducción libre): “Cuando estás saturado, no lo veas como que no tienes suficiente tiempo sino como si tuvieras demasiadas cosas que hacer. No podemos conseguir más tiempo pero sí tenemos la posibilidad de hacer menos, al menos por el momento”.

Me parece muy interesante la siguiente cita de Martin Fowler (traducción libre): “Cuando escribes muchos tests normalmente llegas a la conclusión de que nunca es suficiente. He leído a menudo libros sobre testing y mi reacción ha sido la de huir de la gran cantidad de cosas que hay que hacer para poder hacer ese trabajo… Obtienes muchos beneficios incluso si solo haces pequeñas tareas de testing.”

Realmente no se trata de hacer un testing intensivo sino de aproximarse lo máximo posible a lo que realmente requiere el sistema (en unos casos será más y en otros menos) apuntando hacia los puntos que se consideren críticos en el mismo. Tampoco se trata de hacer un despliegue de medios y técnicas que lo mismo suponen más esfuerzo que el beneficio final sino de saber enfocarlas de manera adecuada a lo que se necesita.

El testing como parte del proceso de desarrollo que es, tiene que adaptarse al contexto, a sus cambios y a la propia naturaleza del producto.

Puedes tener un proceso que defina las líneas generales a tener en cuenta en el testing y por supuesto un bagaje profesional (experiencia), unos conocimientos (técnica) y unas herramientas que te sirvan de base para a partir de ellas adaptar tu trabajo (o el de un equipo) a las necesidades del proceso de desarrollo (porque no solo se debe hacer testing al final) y del sistema.

Esta visión sobre cómo realizar el testing difiere de cómo se está aplicando en muchos proyectos en los cuales el proceso es mucho más rígido y en donde la distancia entre el equipo de proyecto y el de testing es mucho mayor.

Hace poco tuve la oportunidad de leer una entrevista que se realizó a Andy Hunt y Dave Thomas en el año 2003 que giraba alrededor de conceptos tratados en su libro: “The Pragmatic Programmer” y que me permitió darme cuenta de que el término DRY (Don’t repeat yourself) y que hacían uso en su libro iba más allá de la duplicación de código.

Por ejemplo, en el artículo que escribí denominado: “Desarrollo de software. Martin Fowler. Un buen diseño pasa por reducir o eliminar el código duplicado“, el concepto lo aplicaba en relación al código duplicado, algo que no es erróneo porque forma parte del DRY pero que no representa toda su semántica.

¿A que se refieren con el DRY? Pues a evitar la duplicidad de cualquier componente software o no de un proyecto de desarrollo de software, como dicen estos autores (traducción libre): “Toda pieza de conocimiento (entidad) en un proceso de desarrollo debería tener una única representación” de manera que esto va más allá del código duplicado, extendiéndose a objetos de bases de datos, elementos documentales, funcionalidades, etc…

Todos conocemos las consecuencias de las duplicidades:

– Trabajo de más innecesario que se podría haber utilizado en tareas que requerían un mayor esfuerzo o en otras que hubieran sido de interés como por ejemplo refactorizar, automatizar testing, desarrollo de funcionalidades que no pudieron ser abordadas, etc…

– Mayor esfuerzo para mantener coherentes las duplicidades.

Hay muchos desarrolladores que aplican TDD en sus desarrollos o, al menos, desarrollan pruebas unitarias para el software que están implementando.

Sobre ambos aspectos TDD (las pruebas unitarias se construyen antes) o las pruebas unitarias en general hay defensores y detractores y como suele suceder en tantos aspectos, no hay una verdad absoluta, sino que la aplicación o no de estas estrategias dependen del contexto en que se realiza el desarrollo, del tipo de sistema y del equipo de programadores.

Pese a que hablo de contexto incluso en situaciones favorables existen reticencias por muchos desarrolladores que lo consideran una pérdida de tiempo o una carga que llevar encima desde que se implementan, sin embargo quienes lo utilizan y lo consideran como una actividad más dentro de la programación lo suelen aplicar prácticamente en cualquier contexto.

No voy a defender a unos o a otros, cada cual tiene su criterio. Desde mi punto de vista la posibilidad de realizar testing unitario y su automatización supuso en su día una revolución en el desarrollo de software y en el mantenimiento de sistemas porque todo lo que sea establecer controles que permitan construir sistemas más robustos y entregar productos con menos errores debería ser bienvenido

Martin Fowler como buen defensor de estas prácticas realizó la siguiente reflexión sobre los frameworks de pruebas unitarias: “Nunca en el campo de desarrollo de software tantos le debieron tanto a tan pocas líneas de código”.

Si el cambio es inherente al desarrollo de software e inherente a la propia evolución de las organizaciones y de si contexto y entendemos el mismo como algo inevitable, la mejor estrategia es estar preparado para poder responder cuando esos cambios se produzcan en lugar de responder cuando ya se hayan producido.

Puede parecer lo mismo, pero no lo es, al menos en el desarrollo de software, donde todos sabemos que los cambios sobre lo planificado son más costosos de llevar a cabo cuanto más tarde se traten, por ese motivo, las modificaciones en el sistema deben producirse lo más cerca posible del momento en que cambian las condiciones establecidas.

Martin Fowler y Jim Highsmith tienen en cuenta esta circunstancia cuando afirman que: “Facilitar el cambio es más efectivo que intentar prevenirlo. Aprende a confiar en nuestra habilidad para responder a eventos impredecibles es más importante que confiar en nuestra habilidad de planificar ante el desastre. Los procesos ágiles aprovechan el cambio para proporcionar al cliente una ventaja competitiva”.

Es importante tener en cuenta lo que afirman Fowler y Highsmith: la rápida adaptación al cambio y la aplicación de metodologías ágiles como instrumento, proporcionan una ventaja competitiva.