Table of Contents
Así como el año pasado, este año he tenido la oportunidad de asistir a la consueta edición de la conferencia DDD Europe 2018, que tiene lugar en la ciudad de Amsterdam.
Como cada año, tengo que decir que la calidad tanto de los ponientes como del público en la conferencia DDD Europe es muy alta, estando muy por encima de la calidad de las ponencias que estamos acostumbrados a asistir en los eventos para desarrolladores y arquitectos de software.
No obstante, resaltan algunas ponencias a mi parecer muy poco productivas. Estas son, en mi opinión, las ponencias de la conferencia DDD Europe que tienden a alejarse demasiado del mundo del desarrollo e incluso del mundo técnico en general.
Un ejemplo emblemático de lo que acabo de describir, desde mi perspectiva, fue la ponencia titulada “from legacy chaos to the promised land of DDD”, de la cual me esperaba una reseña de patrones estratégicos para evolucionar un sistema monolítico hacia una correcta aplicación de las lógicas del Domain Driven Design.
Desgraciadamente, después de las presentaciones de las dos ponientes, la sesión se centró mucho en la historia del equipo llevado por una de las ponientes y en su experiencia de reconciliación con el mismo.
No estoy aquí negando, ni mucho menos, la importancia de la cultura del equipo en una situación de evolución de un sistema crítico como el llevado por la poniente.
El problema es que creo firmemente que en temas de dinámicas humanas cada equipo es único, así que es extremadamente difícil (si no imposible) extrapolar “recetas” válidas universalmente, salvo por las más obvias.
Así que la ponencia misma, así como todas las análogas, han sido básicamente inútiles para la finalidad formativa por la cual asistía a la conferencia DDD Europe.
A continuación divido en dos artículos de dos ponencias cada una las cuatro exposiciones más interesantes de la conferencia DDD Europe desde mi punto de vista. En esta primera entrega desarrollo la idea de la primera exposición: – The sistemics of the Liskov Substitution Principle y la segunda : Autonomy & Asynchrony: the key to design reliable systems.
Ponencias más interesantes de la conferencia DDD Europe
1).The sistemics of the Liskov Substitution Principle
By Romeu Moura
La ponencia subraya el uso de la palabra sistemics, en el sentido que voy a detallar más adelante.
Empieza considerando las finalidades del paradigma de Orientación a Objetos:
- encapsulation
- decoupling
- coherence (una forma de SRP?)
- cohesion
A la inteligente pregunta del público buscando la razón por la que dejar fuera conceptos como inheritance de la lista anterior, Romeu responde que esta es sólo un medio para conquistar los objetivos anteriores, análogamente a la relación entre ley (medio) y sociedad ética (objetivo).
Posteriormente, una interpretación de la semántica del principio de Liskov: a un sistema tiene que permitirsele sustituir algunas de sus partes, cambiando así su comportamiento, pero sin romper su funcionamiento.
Siguen varios ejemplos significativos de su aplicación, empezando por operaciones matemáticas (una división entre enteros no es isomorfa a una suma de los mismos, ya que es no es un cierre matemático), acabando con los ejemplos clásicos de covariancia y contravariancia con listas de animales, que también tenemos en el presente blog.
A destacar:
- La relación entre Liskov y el principio de Interface Segregation:
- Una interfaz grande está más sujeta a posibles rupturas de las pre y post condiciones establecidas por el principio de Liskov
- Si la interfaz sugiere una ruptura del principio de cohesión temporal, cada implementador está obligado a contravenir Liskov
- Los ejemplos están todos desarrollados en Java en metodología Type-Driven Development, definiendo los tipos del contrato de cada método anteriormente a su implementación, para guiar la misma.
Apoyamos por completo el uso de dicha metodología.
La reflexión final, la más valiosa de la ponencia de la conferencia DDD Europe, es relativa al uso de la palabra systemics.
Aconsejando el libro “Thinking in systems”, de Donella, Romeu introduce elementos de teoría de sistemas para intentar una definición de sistema.
Sin acabar con una definición única, resulta claro que un sistema:
- es más que la simple suma de las partes que lo componen (principio holístico)
- tiene que permitir la evolución de su comportamiento mediante la sustitución de una o más de sus partes, sin alterar sin embargo su funcionamiento global
Valiosa y muy profunda es la consideración de que lo anterior expuesto vale también en negativo: un mal sistema no se mejora simplemente sustituyendo sus partes.
De aquí la frase emblemática:
“If you remake awful software from scratch without changing the culture that created it: you’ll remake awful software.”
Una pequeña reflexión: apoyamos por completo la frase expuesta.
Quien nos conoce ( Apiumhub ) sabe que somos muy escépticos delante de las re-escrituras desde cero, en general.
Mucho de nuestro trabajo, tanto a nivel de consultoría como de colaboración en desarrollo está orientada a unos cambios graduales de cultura del software.
Esto último no es necesariamente por nuestra exclusiva aportación, sino en colaboración con los equipos de clientes/partners/colaboradores, y gracias a las aportaciones de todos.
Un último ejemplo, llevado por Romeu, relativo a la historia: la revolución Francesa acabó con la monarquía, pasando pero por un despotismo “ilustrado”, síntoma de que el sistema seguía siendo el mismo a pesar de haber quitado la persona del Rey.
2). Autonomy & Asynchrony: the key to design reliable systems
Una ponencia que viene dada por una trabajadora de Particular Software.
Para los que no conozcan Particular Software, es la empresa detrás de NServiceBus, un excelente service bus para tecnología .NET.
La empresa está fundada por Udi Dahan.
Por esta razón, las expectativas son muy altas, ya que para quien escribe no existe a día de hoy mejor cultura arquitectural que la propagada por Udi Dahan.
La ponencia de la conferencia DDD Europe hace una reseña estructurada de los patrones para conseguir sistemas fiables, sin los costes prohibitivos del uso de transacciones distribuidas:
- Asincronía
- Al mismo principio nos referimos al detallar el antipatrón “the knot”. Usando el slogan “remove temporal coupling”, se centra el concepto de que cada vez que un componente depende de forma síncrona de otros componentes, se pone un freno importante a (entre otras):
- escalabilidad y quality of service leveraging (para escalar 1 componente tengo que escalar todos)
- fiabilidad (reacción a cadena de puntos de fallo)
- eficiencia (ralentización del sistema entero por sobrecarga de 1 componente)
- desacoplamiento y escalabilidad funcional (cambiar un componente o añadir uno nuevo afecta a todos)
- trazabilidad (difícil entender el punto de fallo)
- Al mismo principio nos referimos al detallar el antipatrón “the knot”. Usando el slogan “remove temporal coupling”, se centra el concepto de que cada vez que un componente depende de forma síncrona de otros componentes, se pone un freno importante a (entre otras):
- EDA/Coreography
usar un estilo arquitectural basado en eventos Pub/Sub permite el total desacoplamiento entre componentes, y habilita la escalabilidad funcional. - Sincronización de mensajes
En un sistema asíncrono, no se puede asegurar el orden correcto de los mensajes.
El patrón propuesto es el patrón saga, en sus dos formas:- orchestration
- coreographyIndicamos, para completar, dos soluciones alternativas o complementarias a saga al problema de la sincronización:
- Resequencer
- Message sequence number, enviado por parte del productor del mensaje, y controlado por el consumidor
- Dead letter queue
En caso se produzca un fallo, los sistemas de colas tienen que ocuparse de la lógica de reintentos.
Para evitar el problema de los poison messages, a un determinado número de reintentos, el mensaje viene puesto en una dead letter queue, monitorizada de forma continua, para el análisis de causa raíz. - Duplicidad de mensajes (idempotence, idempotence, idempotence!)
Así como con el orden, los sistemas asíncronos no pueden asegurar la unicidad del mensaje. El sistema tiene que proporcionar, en todas sus partes, idempotencia de procesamiento. Hay dos casos:- cuando la lógica de negocio permite idempotencia mediante el uso de upserts. Por ejemplo, una lógica de updates.
- cuando la lógica no lo permite, como en el caso de CreateOrder. En estos casos el productor tiene que asignar un messageId único, y el consumidor no tiene que procesar mensajes ya procesados.
Dicho patrón tiene el nombre de idempotent consumer.
- Trazabilidad de mensajes (“where is my message?”)
Para saber en todo momento dónde está el mensaje, o donde ha fallado un procesamiento, hay que acumular en los headers del mensaje todos los servicios que han procesado el mismo, a partir del primer mensaje. - Deployments
Se ha remarcado mucho el concepto de que incluso antes que empezar con sistemas asíncronos, hay que poner en marcha los sistemas de deployments automáticos, trazables y fiables. Es una precondición imprescindible para todo lo demás. - Side by side
los sistemas asíncronos, event-driven, soportados por bus de mensajería, tienen la capacidad de poder desplegar nuevas versiones de componentes al lado de las anteriores, con finalidad de testeo en producción, sin interrumpir el servicio.
Para poder hacer esto, hay que respetar la compatibilidad hacia atrás, sea con el patrón tolerant reader, sea por uso de versionado de esquema. - Resiliencia
Finalmente, se aconseja usar (en entorno de test) el patrón chaos monkey: reiniciar aleatoriamente componentes y servicios para medir cómo esto afecta al funcionamiento (y al rendimiento) del sistema. Es también conocido como test de resiliencia, y hay corporaciones que lo hacen de forma sistemática también en entornos de producción (Netflix).
Estos son los puntos más críticos que subrayé de las dos primeras ponencias de la conferencia DDD Europe. Ahora me gustaría leer vuestra opinión y reflexión antes de compartir mi opinión sobre la 3a y 4a ponencia.
Si este artículo sobre conferencia DDD Europe te gustó, te puede interesar:
Arquitectura de microservicios vs arquitectura monolítica
Scala generics I: clases genéricas y type bounds
Scala generics II: covarianza y contravarianza
Principio de responsabilidad única
Sobre Dioses y procrastinación
Arquitectura de microservicios
Simular respuestas del servidor con Nodejs
Suscríbete a nuestro newsletter para estar al día de los eventos, meet ups y demás artículos!
Author
-
Christian Ciceri is a software architect and cofounder at Apiumhub, a software development company known for software architecture excellence. He began his professional career with a specific interest in object-oriented design issues, with deep studies in code-level and architectural-level design patterns and techniques. He is a former practitioner of Agile methodologies, particularly eXtreme programming, with experience in practices like TDD, continuous integration, build pipelines, and evolutionary design. He has always aimed for widespread technological knowledge; that’s why he has been exploring a huge range of technologies and architectural styles, including Java, .NET, dynamic languages, pure scripting languages, native C++ application development, classical layering, domain-centric, classical SOA, and enterprise service buses. In his own words: “A software architect should create a working ecosystem that allow steams to have scalable, predictable, and cheaper production. Christian is a public speaker and author of the book “Software Architecture Metrics”, which he co-authored together with Neal Ford, Eoion Woods, Andrew Harmel-Law, Dave Farley, Carola Lilienthal, Michael Keeling, Alexander von Zitzewitz, Joao Rosa, Rene Weiß.
Ver todas las entradas