La innovación, nuestra razón de ser
En posts anteriores os he hablado de la importancia de la adaptabilidad y el mantenimiento. En este post me gustaría centrarme en los aspectos relacionados con la ingeniería existente bajo este proceso, en concreto del punto de vista de la ingeniería de software.
En primer lugar, me gusta pensar que los productos software que construimos no son sino una serie de sistemas y componentes interrelacionados, podríamos discutir sobre el lenguaje de programación o si usamos funciones u objetos. Pero, en realidad, eso no es excesivamente importante. El factor crítico es que cada uno de ellos debería interpretarse como una unidad de funcionamiento. La verdad es que tanto el concepto de sistema como el de unidad de funcionamiento están discutidos hasta la saciedad en toda la literatura existente sobre ingeniería de software. No obstante, me gusta destacar esta aproximación en lugar de hablar de APIS o servicios puesto que, por una parte, me ayuda a pensar en cómo se deberían comportar cada uno de los componentes software y, por otra parte, la idea de sistema, sus dependencias, su capacidad de ser modelado y simulado se alinean con mi educación en otro campo de la ingeniería.
En cualquier caso, este concepto de unidad es importantísimo. Imaginemos una máquina compleja compuesta de varios componentes o incluso subsistemas. No sé, pongamos, por ejemplo, que nuestra máquina consta de varios sistemas de engranajes y un motor eléctrico. Lógicamente, lo que queremos es que el sistema en su conjunto funcione bien, lo cual necesariamente supone que cada una de las piezas también lo haga e incluso que los engranajes, pudieran ser utilizados en máquinas distintas a las que estoy evaluando, respetando, así, una serie de reglas y especificaciones. Cuando hablamos de software, hablamos de los mismos conceptos e ideas, seguimos una serie de estrategias de diseño que nos permitan la adecuada reutilización de los sistemas o componentes desarrollados.
El problema se origina cuando intentamos explicar como los sistemas de software deben construirse, como debemos aislar cada uno de los componentes o como podemos conseguir la reutilización de los mismos. La verdad es que no es fácil, adquirir una completa compresión de este problema requiere que el instructor cuente con el conocimiento preciso y que el alumno tenga la madurez suficiente como para adquirir los conceptos.
No podemos negar que hemos desarrollado patrones, principios de modelado como SOLID y herramientas como TDD que tratan, precisamente, de ofrecer un camino a seguir para el desarrollo de sistemas. Pero, ¿un desarrollador no suficientemente maduro es capaz de entender lo que todo esto puede ofrecerle?. Desde mi punto de vista, no sin una adecuada mentorización, trasladando lo que es correcto y lo que no y apostando por una enseñanza en base a ejemplos.
A fin de clarificar mi punto de vista, me gustaría céntrame en un caso concreto, un subsistema en el que estamos trabajando en este momento. En particular, un Bot para Whatsapp y Telegram, en realidad nada demasiado complejo puesto que es un sistema de preguntas dirigidas. La dificultad no viene, por tanto, de lo qué es sino de la adecuada descomposición del sistema y el testeo de cada una de las partes involucradas. Imaginemos por un momento que somos desarrolladores junior y nos tenemos que enfrentar a este problema. ¿cómo lo haríamos? Podríamos tener la suerte de que nuestro jefe de equipo nos sugiriera empezar por Telegram para luego continuar con la implementación de Whatsapp. Desafortunadamente, desde el punto de vista del diseño del sistema esta recomendación sería un desastre. ¿Por qué? Pues porque, como os he comentado, somos desarrolladores junior y, probablemente, seguiríamos una aproximación similar a la siguiente:
Si somos suficientemente senior seguramente estaremos inquietos ante la idea de semejante "código" puesto que, entre otros problemas, esa estrategia conduciría a una duplicidad de código y una reimplementación de Whatsapp desde cero. El problema no es sólo del junior, sino que también se basa en una deficiente comunicación de objetivos o seguimiento por parte del líder técnico o del jefe de proyecto. Una comunicación más efectiva, desde el punto de vista de la arquitectura del sistema, debería enfocarse en trasladar la necesidad de construir los siguientes bloques:
En concreto,
La verdad es que podríamos pensar que un sistema software construido de esta manera es complejo. Bueno, la verdad, es que lo es. Más aun si consideramos que cada uno de los componentes individuales deberían ser escritos teniendo en cuenta ideas similares, incluyendo aislamiento o diseño basado en comportamiento. Las ventajas pudieran parecer sutiles pero en realidad son importantes.
Por otra parte, cualquier sistema tiene un cierto grado de complejidad. Si volvemos a la analogía del sistema de engranajes, saber lo que hace uno de ellos no quiere decir que sepamos crear un reloj automático. Ignorar la complejidad de este tipo de trabajo, la ingeniería que lo sustenta sólo conduce a sistemas inmantenibles y a costes mayores que los esperados inicialmente.