S.O.L.I.D.

Un artículo de Rafa G. Blanes

¿Cómo conseguir que un proyecto software sea mantenible y que se pueda modificar con sencillez?

Esta pregunta tiene muchas respuestas, según la naturaleza del mismo proyecto, claro. No obstante, existen una serie de principios que, de seguirlos, la vida (y estructura) de un proyecto puede cambiar de una forma radical.

Demasiado a menudo veo proyectos, sin ir más lejos, muchos repositorios en GitHub, en los que es imposible discernir cómo se han implementado los principios de diseño más básicos en ingeniería del software, y no es que esté mal, claro, todo depende de la vida que vaya a tener ese proyecto.

No hace falta que conozcamos al detalle todos y cada uno de los patrones de diseño que más o menos son conocidos y aceptados por la industria y muy bien explicados en libros clásicos como este, pero, desde luego, si lo que queremos es que nuestro proyecto pueda ser mejorado continuamente sin demasiada dificultad, entonces sí que hay que seguir unas mínimas normas de desarrollo.

Aquí es donde entran los principios S.O.L.I.D.

Si tu proyecto tienen clases o funciones extraordinariamente largas del orden de cientos de líneas de código, si hay métodos con innumerables if o con muchos bloques anidados, o hay métodos o funciones con muchos parámetros, entonces tu aplicación camina hacia una solución espagueti difícil de mantener y evolucionar. 

Si es así, sigue leyendo...

Best Practices

Artículo disponible en epub y pdf:

Cómo usar repositorios de datosCómo usar repositorios de datos epub

 

 

Me llama mucho la atención cómo a lo largo de los años puedo haber trabajado en aplicaciones con .NET en C#, con javascript utilizando Angular y NodeJS, y también con PHP cuando estaba más centrado a hacer módulos en Drupal, y cómo con todos esos lenguajes con sus respectivos entornos de desarrollo se pueden aplicar las mismas buenas prácticas.

Hay veces que éstas se refieren a procedimientos de trabajo o al modo de estructurar un proyecto, otras hacen referencia a aplicar patrones de diseño e incluso antipatrones para detectar precisamente lo que no se hace bien. En otras ocasiones, son sencillamente prácticas habituales que hace la mayoría de la gente que usa una tecnología en particular (de ahí, por ejemplo, los proyectos de scaffolding).

Un buen proyecto software debe oler a buenas prácticas, de principio a fin, desde la arquitectura del mismo hasta la evolución de las funcionalidades que se le van añadiendo poco a poco.

Nada peor que una aplicación, proyecto o sistema en el que no se pueda ver claramente cómo están implementadas esas buenas prácticas.

Y es que además tienen algo en común: la mayoría de ellas son fáciles de implementar.

Y como me gusta escribir... pues voy a ir hablando de ellas, de aquellas con las que yo directamente he visto que tienen más impacto en la mejora de la calidad de un proyecto software.

Un aviso a navegantes: en muchas ocasiones los beneficios de estas recomendaciones no se ven claramente, ni siquiera en el corto plazo, y su impacto positivo a medio y largo plazo es más una cuestión sutil que sólo se aprende cuando has cometido todos los errores posibles y entonces se hace la luz y dices algo como, "ahora sí que lo entiendo".

Para mí la implementación de repositorios de datos es una de las prácticas más útiles en cualquier proyecto software.

No me gusta repetir trabajo ni tareas pesadas que se hacen una y otra vez y que de algún modo se pueden automatizar o al menos indicar lo pasos a realizar para que la siguiente vez no pierdas tanto el tiempo en recordar cómo se hacía ésto o aquéllo. Si te encuentras en esta situación a menudo, que sepas que puedes evitarlo.

Si es verdad que debemos poner el foco en aquello que aporta valor, en las tareas verdaderamente creativas y productivas, entonces tenemos que encontrar la forma de no tener que reinventar la rueda continuamente. No estoy hablando de tareas que hay que hacer sí o sí (como un parte de trabajo) y hablo en sentido general, no sólo desde el punto de vista del desarrollo de software, sino de hacer todo lo posible para que estas tareas ocupen el menor tiempo posible y, sobre todo, no tengamos que pensar reiteradamente cómo se hacían.

Voy a poner varios ejemplos:

  • El proceso de publicar una nueva noticia en la web, ya sabes, crear el contenido, fijar bien la url, revisar el contenido, comprobar la estructura del mismo, revisar faltas de ortografía o de expresión, pedir la aprobación del mismo si es necesario, etc. Son varios pasos, sí, pero si este trabajo lo haces una vez cada varios meses, terminar olvidándolo y preguntándote ¿cómo había que poner el formato de las url?
  • Si mantienes varias webs, como es mi caso, y además todas con Drupal, y dado que no las actualizo continuamente (actualizaciones de módulos, mejoras de diseño, etc.), puedes encontrarte con que cada vez que vas a actualizar una, tienes que volver a investigar cómo se hacía esto o aquello, como por ejemplo, cómo y dónde guardar una copia de seguridad, cómo etiquetar la nueva versión de la web en GIT o similar, cómo comprobar que la nueva actualización no ha roto nada, cómo desplegar para que no te quede ningún cabo suelto, comprobar la seguridad, etc.
  • Llevo dos años usando la herramienta Scrivener para la creación de libros. Su proceso de compilación genera un fichero en format eBook, pdf, docx, etc. Sin embargo, después de generar el fichero tienes que comprobar varias cosas según tu flujo de trabajo y el propósito que tengas. Por ejemplo, si generas un eBook para Kindle, tienes (o deberías), revisar que el epub pasa las pruebas de validación con una herramienta como epubcheck, después tienes (o deberías) abrirlo con la herramienta Kindle Previewer y revisar página a página, y no digamos le proceso de publicación en Amazon.

En fin, son trabajos que realizas que requieren de varios pasos para su realización. Salvo que tengas una memoria prodigiosa, cada vez que los vayas a enfrentar algo se te quedará en el tintero.

¿Resultado? No se terminará del todo bien y se tardará más en realizarlo, aparte de lo tedioso que resulta tener que investigar algo porque lo has olvidado... Y si te fijas bien, parte de tu trabajo lo pasas realizando tareas que bien podrían estar bajo el paraguas de un procedimiento.

Productivity

Me encanta prototipar, probar conceptos, ideas y ponerlas en marcha sencillamente para validarlas o por profundizar en tecnologías que me gustan. Esto creo que es uno de los vicios de muchos desarrolladores, la necesidad sana de aprender cómo funciona tal framework, cómo desplegar con Heroku o cómo funciona el mecanismo de plugins de cualquier software, por poner algunos ejemplos.

Ahora bien, si queremos probar una idea no podemos perdernos en los detalles y desviarnos así del asunto relevante que queremos conseguir. No obstante, veo lo fácil que es perderse en esos detalles y no centrarse en lo importante realmente, lo que aporta valor al proyecto, producto o idea que estamos probando.

De ahí el conocido mantra en nuestra profesión de poner el foco completamente en la funcionalidad particular de un proyecto de modo que la general debe ser cubierta por el entorno a usar en forma de librerías reutilizables, plugins, extensiones, plantillas, etc, cualquier cosa, en definitiva, reutilizable.

Es como si se nos planteara realizar una plataforma para la gestión empresarial y decidiéramos hacerlo todo desde cero y no contar con algunos de los productos que ya existen como base en el mercado. Sería, cuanto menos, inviable en términos de tiempo y esfuerzo.

Sin embargo no siempre pensamos en adquirir alguna solución de tipo comercial ya existente y comenzar a partir de ella y, de nuevo, caemos en el error de reinvertar la rueda una y otra vez, sin evaluar realmente el coste de esto. Una cosa es investigar e implementar por simple gusto o curiosidad en tu tiempo libre y otra muy distinta justificar decisiones en tu compañía que supongan costes extra que se pueden evitar.

Vicio, mala práctica o pura ignorancia, este es uno de los déficits habituales de muchos desarrolladores que, además, es de camino inverso: no saber seleccionar componentes del mercado o de código abierto y también no saber desacoplar lo suficiente lo que se hace para reutilizarlo en un futuro.

Wunderlist sampleComo muchas veces he cometado en este blog, trabajar bien, generar un resultado de calidad en tiempo y sin necesidad de que los equipos de trabajo estén estresados continuamente, es más una cuestión de organización que de excesos de horas delante del ordenador. Cuando las horas extras dejan de ser puntuales y pasan a ser crónicas, evidencian un problema grave de planificación y productividad, no hay más.

No obstante, veo continuamente cómo se sigue abusando del correo electrónico para gestionar tareas con una lista interminable de replies y cómo se usa el Outlook o el Gmail como almacén documental; también veo a menudo cómo se usa el excel como herramienta para planificar el trabajo...

Digamos que aunque hablamos mucho de la sociedad del conocimiento y que todos tenemos acceso a ordenadores, portátiles, smartphones, etc., ciertas cosas se siguen haciendo igual que en los noventa, es decir, que apenas se sale del correo electrónico y el paquete ofimático de turno.

A estas alturas, gestionar las tareas de un equipo usando exclusivamente el correo y hojas en excel, no es que esté obsoleto, sino que revela una falta de productividad o una inercia total de la gente que los usa abusivamente sin querer encontrar opciones más apropiadas y más ágiles. Lo siento si tu jefe o manager se organiza así, toda su desorganización terminará afectándote de un modo u otro.

Hay que sustituir el uso (abuso) de esas herramientas por otras cuyo propósito es el de gestionar proyectos o tareas y además tienes que definir tus propios flujos de trabajo. El uso de cualquier herramienta para gestionar tareas viene después de que tengas claro cómo organizas tu trabajo (flujos de trabajo).

La cuestión no es en realidad qué tareas hacer en cada momento o en los próximos días o semanas, sino de qué modo gestionas tu tiempo.

En software ocurre que no hay una misma respuesta para cada situación, para cada proyecto en el que cambia el número de personas involucradas en el equipo, la complejidad del mismo proyecto e incluso las tecnologías usadas. No obstante, lo que sí es cierto en todos los casos es que si se deja para el final el despliegue del sistema en un entorno lo más parecido o idéntico al de producción, nos encontraremos con muchos, muchísimos problemas.

Hay que desplegar en un entorno de producción lo más parecido al del cliente final tan pronto como se tenga alguna funcionalidad terminada pero completa, aunque sea simple.

Incluso si contamos con un entorno de integración fantástico y una gestión de la configuración para él magnífica, esto no nos garantizará que todo funcionará de maravilla en producción. Se podría escribir un libro entero sobre este tema, dependiendo de la naturaleza del proyecto e incluso del equipo, aunque me temo que casi nunca se tiene en cuenta el despliegue final hasta... ¡el final!, momento en el que nos podemos llevar muchas sorpresas.

Si no lo hacemos así, si no pensamos en el despliegue desde el principio, la brecha que nos encontraremos al final del proyecto cuando creemos que lo tenemos todo casi terminado, no hará más que agrandarse.

Un caso extremo de esto es cuando desarrollamos el proyecto en la misma máquina del cliente final..., llegando al caso de que fuera de él el proyecto requiere de una auténtica reingeniería (...) Esto, en software, es casi un pecado capital, al igual que probar contra bases de datos en producción o dispositivos que están en clientes finales. Vale sí, si hay que hacerlo, pues se hace cuando no haya más remedio, pero al menos tengamos en cuenta las consecuencias que puede tener.

Estas son las razones por las que opino que hay que publicar el proyecto en un entorno, llamémosle de pre-producción, lo antes posible.

Esta es una de las cosas más difíciles de resolver cuando afrontamos la creación de un nuevo proyecto: distinguir claramente entre qué debe hacer de cómo se debe hacer.

El "qué" está relacionado con requisitos, especificaciones, historias de usuario, todo aquello que nos haga entender lo que el cliente quiere, su problema a resolver.

El "cómo" tiene que ver con las tecnologías que van a resolver ese problema que el cliente nos plantea, en otras palabras, el cómo abarca desde las tecnologías a usar, metodología, evidencias a entregar hasta dónde se desplegaría el proyecto final.

Hay una confusión tremenda entre esa separación de conceptos, hasta el punto de tener que forzar o usar mal tecnologías mal elegidas para el propósito indicado en una sencilla especificación (cuando no se le dice a un cliente que "eso no se puede hacer").

Si ya es difícil extraer al comienzo todos los requisitos y conseguir que estos estén descritos con buena calidad y que sean entendibles, más complicado aún el elegir ese cómo a partir de todo lo anterior.

De cómo se gestione esto y las decisiones que se tomen en ese momento dependerá en gran medida la calidad del proyecto que se entregue, su coste final y su facilidad de mantenimiento y evolución. Errores en esta fase hacen que el proyecto termine en un completo fracaso o haya que tirarlo al cabo de algunos años.

Lo peor de todo es que en muchas ocasiones confundimos requisitos objetivos, indicados o no por un cliente o intermediario, con aquellas tecnologías que nos gustaría usar porque sí o bien porque son las únicas que conocemos bien y no queremos salir de nuestra zona natural de confort. 

Traducido al desarrollo de proyectos software, esto viene a ser algo así como empezar la casa por el tejado: si antes de afrontar un nuevo proyecto, sea del tipo de que sea, ya estamos diciendo que lo vamos a hacer con una base de datos en SQL Server, ya estamos levantando paredes en el laberinto que se formará durante su desarrollo, o dicho en otras palabras, en lugar de solucionar, estamos poniéndonos a nosotros mismos obstáculos.

Este no es que sea un error más, el confundir qué se tiene que hacer con cómo se debe hacer, sino que es un error paradigmático de una profesión tanto si a ella llegan gente titulada con uno u otro título académico o intrusos sin formación formal relacionada (sin ánimo de menospreciar a nadie, al fin de al cabo sólo valen el talento de cada cual y el trabajo bien hecho).

No hace mucho he tenido que retomar un desarrollo que comencé hace año y medio y que después continuó uno de mis compañeros. A veces programamos pensando que nos vamos a acordar de todos y cada uno de los detalles de lo que hacemos cuando la realidad es que a los pocos días se nos olvidan sin poder evitarlo y a los meses casi ni reconocemos que esto o aquello los hiciste tú mismo. 

Para cada clase incluimos una sección de comentarios indicando el autor de la misma y su propósito, como manera rápida de identificar esa información; en ocasiones me cuesta mucho recordar que una clase concreta la comencé yo mismo... No es mala memoria (que también, quién sabe), aunque me consuelo diciéndome que es el efecto de haber escrito miles de líneas de código en los últimos años.

Con frecuencia se cae en el error de programar para solucionar algo ahora y sin tener en cuenta que hay que solucionarlo para siempre. Pero, ¿cómo medir más o menos objetivamente que algo está mejor resuelto para el largo plazo? O nos interesamos por los resultados a corto plazo o a largo plazo, el resultado en uno y otro caso no tienen nada que ver.

Al retomar aquel proyecto pude comprobar una vez más cómo escribir software de manera limpia, clara, sencilla y con una buena cobertura de pruebas te puede salvar de malgastar días y semanas de trabajo sencillamente retomando aquello que hiciste hace mucho tiempo. Lo contrario es acumular deuda técnica que te pasará factura tarde o temprano, o lo que es peor, tendrás a un compañero acordándose de tus propias chapuzas; sí, seguramente sea ese que cuando te lo cruzas viniendo del office te mira con mala cara, quién sabe.

Del mismo modo no siempre he podido trabajar tanto en el detalle, en encontrar la mejor solución y sé de sobra el resultado: malos trabajos que se entregan y que terminan empeorando con el tiempo.

Llamamos deuda técnica a todos esos detalles que vamos dejando de lado sin resolver del todo bien pero que cuando se acumulan, terminan en una solución difícil de evolucionar y mantener. Es algo malo, muy malo, como eso de acumular karma negativo... Es la pesadilla de cualquier desarrollador: el tener que asumir un proyecto que ha hecho otro y que no hay quien lo entienda, que está cogido con pinzas.

Este comienza a convertirse en uno de mis mantras favoritos: "refactorizar o morir".

Recientemente he vuelto a poner en práctica una de las mejores virtudes de realizar este tipo de trabajo continuamente. El resultado finalmente es muy satisfactorio después de muchos momentos tipo "esto está quedando fatal", "así sólo voy a llegar a una solución muy enmarañada", etc. El desánimo cunde rápido, sobre todo si se trata de un pequeño proyecto que haces a ratos por las noches o fines de semana.

No obstante, una mínima tenacidad (y seguramente tirarlo todo a la basura y volver a empezar en algún momento), te hace llegar a una buena solución que no sólo funciona, sino que además es ampliable y evolucionable con cierta facilidad.

Se habla mucho de productividad; para mí es muy sencillo describir qué es productivo y qué no en software: las soluciones fáciles son más productivas que las inextricables que sólo pueden entender sus autores, aquello que nos permite ganar velocidad de desarrollo es más productivo y con ello conseguiremos más con menos esfuerzo. Nada más. Así de contundente y simple.

Hay quienes se procupan de mejorar el código de una aplicación en alguno de sus aspectos en algún momento del trabajo: al final, cuando ya todo funciona, de vez en cuando... Sin embargo, las ventajas de incorporar estas tareas de mejora en todo momento no siempre se aprecian como productivas, mucho menos cuando nos acercamos peligrosamente a las fechas de entrega y comenzamos a dejar cabos sueltos (de los que nos acordaremos sin duda semanas o meses más tarde).

¿Por qué refactorizar cuando lo importante de una aplicación es que le funcione al cliente? Buena pregunta, y al mismo tiempo, ingenua. Quienes aún no ven claro las virtudes de invertir tiempo en este trabajo, deben saber que lo primero que se gana es velocidad de desarrollo, por tanto, productividad.

Este verano me pidieron que evaluara una sencilla tienda online para estimar el coste y esfuerzo necesarios para añadirle nuevas características (y corregir de paso algunos detalles que no funcionaban bien) y, para mi sorpresa, me encontré con algo que es habitual en nuestro sector: aplicaciones que están mal planteadas, mal hechas, escritas de cualquier forma, a pesar de que con ella el cliente final había facturado en el último año más de veinte mil euros en pedidos.

Es ya recurrente el siguiente ejemplo: cuando compramos un coche nos interesamos por muchos de sus acabados, prestaciones y, cómo no, detalles de su mecánica interna (fabricante del motor, etc); del mismo modo para la construcción de una casa se necesita la firma de un arquitecto colegiado (al menos en España) cuya función se supone que es la de supervisar todos los aspectos técnicos de la construcción.

Me pregunto entonces por qué para un proyecto software a casi ningún cliente se le ocurre preguntar o preocuparse por la calidad del proyecto que se le entrega, sin saber en realidad que según esa calidad, el coste de evolucionar o mejorar en el futuro la aplicación será asequible y razonable o desorbitado (cuando no se termina por tirar el sistema a la basura y realizar otro de nuevo desde cero).

De este modo, en muchísimos casos en nuestra profesión, para clientes de pequeño tamaño, medianos o grandes corporaciones, se entregan aplicaciones que en realidad son una manzana envenenada que explotará más adelante en cuanto el cliente necesite modificaciones o cambios, que es lo normal para casi cualquier tipo de software.

¿Compraríamos un coche que no se puede reparar o mantener? Absurdo.

Me planteo varias preguntas en relación a esto. ¿Cómo demostrarle a un cliente la calidad del software que se le entrega?

¿Cómo destacarnos de los competidores garantizando al cliente que nuestra solución va a ser más mantenible ante cambios? Este es un tema que da para mucho y es uno de esos asuntos recurrentes con los que nos encontramos día sí, día no.

¿Estaría el cliente dispuesto a un mayor coste si se le garantiza mejor calidad interna en lo que se le ofrece? ¿Tendrían sentido auditorías externas de calidad para poder dar un producto por terminado con su correcto certificado acreditado de calidad software? Vale, sí, sé que exiten auditorías así y que se suelen usar en grandes proyectos para grandes compañías pero eso es una gota en el océano.

En el caso que comentaba al principio, un simple vistazo a la estructura de la aplicación me hacía temer lo peor...

Páginas

¿Por qué leer El Libro Negro del Programador?

Adquirir desde:
Amazon (kindle eBook / papel)
CreateSpace (papel)
PayHip (epub / mobi / pdf)

El libro negro del programador.com
Segunda Edición - 2017

Archivo

Trabajo en...