Archive for the 'Arquitectura de Software' Category

Arquitectura y Desarrollo Agil

Saturday, November 8th, 2014

Hace unos días apareció un hilo de discusión interesante en la lista foro-agiles sobre si la arquitectura emerge. Hubo varios aportes y distintas posturas, los invito a leer por ahí todo lo que se escribió y expuso.

Quisiera esta en mi blog, escribir algo sobre el tema. Primero, algo de contexto. Voy a escribir sobre:

– Proyecto profesional o personal
– Ejecutado por un equipo ágil o por uno mismo
– Proyecto donde el principal entregable es software

Al poner lo ágil en el contexto, estoy asumiendo que vamos a abrazar el cambio, uno de los pilares de lo ágil. Se ha visto que en el desarrollo de software es difícil basarse en algo fijo, sino que lo que se va desarrollando se va descubriendo, desplegando, y mejorando a medida que se va construyendo. Es también difícil tener todo definido de antemano. Otro de los puntos que voy a poner en claro, es que lo que necesitamos es basarnos en los casos de uso, por lo menos en gran parte. Escribí sobre el tema en TDD y Casos de Uso. Recuerdo de ahí alguna cita de @unclebobmartin:

The center of your application is not the database. Nor is it one or more of the frameworks you may be using. The center of your application are the use cases of your application.

It makes me crazy when I hear a software developer describe his system as a “Tomcat system using Spring and Hibernate using Oracle”. The very wording puts the frameworks and the database at the center.

What do you think the architecture of that system would look like? Do you think you’d find the use cases at the center of the design? Or would you find the source code arranged to fit nicely into the pattern of the frameworks? Would you find business objects that looked suspiciously like database rows? Would the schema and the frameworks pollute everything?

Here’s what an application should look like. The use cases should be the highest level and most visible architectural entities. The use cases are at the center. Always! Databases and frameworks are details! You don’t have to decide upon them up front. You can push them off until later, once you’ve got all the use cases and business rules figured out, written, and tested.

Amen!!! Si no tenemos en claro los casos de uso, no podemos tomar grandes decisiones, y menos de arquitectura. Sé que parece que en muchos sistemas los casos de uso parecen estar dados desde el principio, pero en mi experiencia profesional, no veo que haya sido así. Lo que uno presupone, por ejemplo, en un Sprint 0, no termina siendo el caso a las pocas semanas de desarrollo. Es por eso que la arquitectura no es algo que se pueda plantear convenientemente desde el principio, sino que es algo que tenemos que ir desplegando a medida que tengamos más masticados, digeridos, analizados, incorporados los casos de uso que vamos implementando.

“Arquitectura” es un término amplio. Veamos de poner algún ejemplo, para poner un contexto más definido. Supongo que tenemos que nuestro cliente es una petrolera, y tenemos que desarrollar un sistema que recibe mensajes de uno o dos sistemas, que luego pueden ser más, y necesitamos procesarlos, por ejemplo, dado un mensaje que indique que hay un nuevo pozo de perforación, entregar los nuevos datos a dos o tres sistemas que ya están funcionando, y prever que se pueda entregar a otros sistemas que vayan apareciendo. Uno podría verse tentado desde el comienzo: “Bien, es un caso para implementar con un Service Bus”. O “bien, es un caso para implementar usando Storm de Java”, o “acá hay que poner un BPM”. En mi experiencia, semenjante tipo de decisiones son tempranas, y hasta incorrectas o al menos, nos van a desviar de los casos de uso a implementar. Si tuviera que hacerlo yo solo, o si convenzo a mi equipo de la postura que estoy promoviendo en este post, lo haría: “Primero los casos de uso, simple proceso de mensajes, en un simple programa”. Solamente cuando tenga ya uno o varios casos de uso concretos implementados, podría ver cuál es la carga de mensajes (¿10 por día, 100000 por segundo?), la dificultad o facilidad de acceso a los sistemas finales ya existentes, la importancia (o no) de procesar un mensaje en menos de un minuto o en una semana, descubrir una “ley de Pareto”: el 80% de lo importante viene en el 20% de los mensajes, y se cubren con este y este otro caso de uso, etc… Sólo luego de haberse empapado de los casos de uso, y haber implementados algunos, podrá verse más en claro las necesidades de arquitectura que tenemos.

Pero alguien podrá decir ¿no es más trabajo? Así, parece que primero implementamos un caso de uso, y luego tenemos que reimplementarlo al cambiar la arquitectura. De nuevo, mi experiencia indica: la primera implementación es un “baby step” que sirve para ir aproximándonos al problema, sin “bajada de línea” previa. Y luego, seguimos mejorando la implementación, cambiando decisiones de arquitectura. Si realmente abrazamos lo ágil (por ejemplo, adoptando disciplinas como Test-Driven Development), los cambios no cuestan, y las decisiones diferidas no implican un costo, apenas algún esfuerzo. Y si luego vemos que una decisión de arquitectura no es la mejor, porque aparecen nuevos contextos, nuevos casos de uso, nuevas fuerzas, SI ABRAZAMOS LO AGIL, el cambio de implementación, y el cambio de decisión, tampoco debería tener un gran costo.

Eso es lo que veo que tiene que hacer el rol de arquitecto (hablo de rol, y no de puesto): saber diferir decisiones, y saber tomar decisiones diferidas que se puedan cambiar. Por más seguro que estemos “X es el camino a seguir (sea X BPM, MapReduce, Actor model, procesamiento distribuido usando colas… )” SI ABRAZAMOS LO AGIL debemos tomar decisiones CAMBIABLES y DIFERIBLES. Algunas de esas decisiones involucran lo que se llama (ampliamente, insisto) “arquitectura”.

Ahora bien, SI NO ABRAZAMOS lo ágil, y no adoptamos las disciplinas técnicas, duras y blandas que permiten encarar el cambio y el desarrollo evolutivo, entonces sí, vamos a tener problemas en la decisiones diferidas. Cada cambio nos va a costar, cosa que en el pasado “Waterfall” se quería evitar DEFINIENDO la mayor parte del sistema de antemano.

He visto sistemas, que por adoptar una decisión temprana, terminan perdiendo el rumbo. Todo el equipo queda con inercia, y todo caso de uso de uso lo quiere solucionar usando la decisión temprana, que se tomó como LA SOLUCION. Por ejemplo, si la decisión fue “vamos a usar Hadoop”, por más que los casos de uso que vengan clamen por otro tipo de solución, el equipo sigue mapeando todo problema a un Map Reduce distribuido.

Pero si diferimos las decisiones, tenemos más cintura. Ya el propio diferimiento permite que cuando se tome una decisión, el sistema no esté anquilosado, dirigido, congelado solamente a esa decisión. Aunque al final la decisión diferida sea la misma que nos dictaba nuestro “pequeño arquitecto yomelasetodas” desde el principio, el haber implementado gran parte de la solución sin haber tomado la decisión de arquitectura, permite armar un sistema más claro, más simple, donde elementos de arquitectura aparecen claramente por aparecer nuevas fuerzas que tenemos que tomar en cuenta, más que por sesudas ideas en general en el aire tomadas al comienzo. Y por lo que ví en estos años del tercer milenio, esa adopción diferida le da más calidad de “si surgen nuevas fuerzas o casos, podemos cambiar la decisión”, nos da un sistema más adaptable a cualquier cambio que aparezca en el futuro. Porque también eso es algo bueno para el rol de arquitecto: estar advertido que lo que estamos armando, si tiene éxito, va a evolucionar. En vez de hacerlo flexible desde el vamos, es mejor hacerlo cambiable, algo que veo que se va ejercitando con cada decisión diferida.

Imagen tomada de Swarm Intelligence. Me gustó la idea y la imagen, pero vean que abandono el adjetivo “emergente” en lo que escribí luego del primer párrafo, porque da a entender como que la arquitectura aparece sin intervención del equipo, por simple dinámica compleja.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez