Prefacio

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

Quizá te preguntes quiénes somos y por qué escribimos este libro.

Al final del último libro de Harry,Test-Driven Development with Python (O'Reilly), se encontró haciendo un montón de preguntas sobre arquitectura, como por ejemplo: ¿Cuál es la mejor forma de estructurar tu aplicación para que sea fácil de probar? Más concretamente, ¿para que tu lógica de negocio principal esté cubierta por pruebas unitarias, y para que minimices el número de pruebas de integración y de extremo a extremo que necesitas? Hizo vagas referencias a la "Arquitectura Hexagonal" y a los "Puertos y Adaptadores" y al "Núcleo Funcional, Cáscara Imperativa", pero si fuera sincero, tendría que admitir que no eran cosas que realmente entendiera o hubiera hecho en la práctica.

Y entonces tuvo la suerte de encontrarse con Bob, que tiene las respuestas a todas estas preguntas.

Bob acabó siendo arquitecto de software porque nadie más en su equipo se dedicaba a ello. Resultó ser bastante malo en ello, pero tuvo la suerte de encontrarse con Ian Cooper, que le enseñó nuevas formas de escribir y pensar sobre el código.

Gestionar la complejidad, resolver problemas empresariales

Ambos trabajamos para MADE.com, una empresa europea de comercio electrónico que vende muebles por Internet; allí, aplicamos las técnicas de este libro para construir sistemas distribuidos que modelan problemas empresariales del mundo real. Nuestro dominio de ejemplo es el primer sistema que Bob construyó para MADE, y este libro es un intento de poner por escrito todo lo que tenemos que enseñar a los nuevos programadores cuando se incorporan a uno de nuestros equipos.

MADE.com gestiona una cadena de suministro global de socios transportistas y fabricantes. Para mantener los costes bajos, intentamos optimizar la entrega de existencias a nuestros almacenes para no tener mercancías sin vender tiradas por ahí.

En el mejor de los casos, el sofá que quieres comprar llegará a puerto el mismo día que decidas comprarlo, y te lo enviaremos directamente a casa sin almacenarlo nunca. Conseguir el momento adecuado es un complicado acto de equilibrismo cuando las mercancías tardan tres meses en llegar por barco contenedor. Por el camino, las cosas se rompen o se estropean con el agua, las tormentas provocan retrasos inesperados, los socios logísticos manipulan mal las mercancías, falta documentación, los clientes cambian de opinión y modifican sus pedidos, etc.

Resolvemos esos problemas construyendo software inteligente que represente los tipos de operaciones que tienen lugar en el mundo real, de modo que podamos automatizar la mayor parte posible del negocio.

¿Por qué Python?

Si estás leyendo este libro, probablemente no necesitemos convencerte de que Python es genial, así que la verdadera pregunta es: "¿Por qué necesita la comunidad Python un libro como éste?". La respuesta tiene que ver con la popularidad y madurez de Python: aunque Python es probablemente el lenguaje de programación de más rápido crecimiento del mundo y se acerca a la cima de las tablas de popularidad absoluta, apenas está empezando a asumir el tipo de problemas en los que el mundo de C# y Java lleva años trabajando. Las startups se convierten en verdaderas empresas; las aplicaciones web y las automatizaciones con scripts se están convirtiendo (susurradlo) en software empresarial.

En el mundo de Python, a menudo citamos el Zen de Python: "Debería haber una -y preferiblemente sólo una- forma obvia de hacerlo".1 Por desgracia, a medida que crece el tamaño del proyecto, la forma más obvia de hacer las cosas no siempre es la que te ayuda a gestionar la complejidad y la evolución de los requisitos.

Ninguna de las técnicas y patrones que tratamos en este libro es nueva, pero sí lo son en su mayoría para el mundo de Python. Y este libro no sustituye a los clásicos en este campo, comoDomain-Driven Designde Eric Evans o Patterns of Enterprise Application Architecture de Martin Fowler (ambos publicados por Addison-Wesley Professional), a los que nos referimos a menudo y que te animamos a leer.

Pero todos los ejemplos de código clásicos en la literatura tienden a estar escritos en Java o C++/#, y si eres una persona de Python y no has usado ninguno de esos lenguajes en mucho tiempo (o de hecho nunca), esos listados de código pueden ser bastante... difíciles. Hay una razón por la que la última edición de ese otro texto clásico,Refactoring de Fowler (Addison-Wesley Professional), está en JavaScript.

TDD, DDD y Arquitectura Dirigida por Eventos

Por orden de notoriedad, conocemos tres herramientas para gestionar la complejidad:

  1. El desarrollo dirigido por pruebas (TDD) nos ayuda a construir código que es correcto y nos permite refactorizar o añadir nuevas funciones, sin miedo a la regresión. Pero puede ser difícil sacar el máximo partido de nuestras pruebas: ¿Cómo nos aseguramos de que se ejecutan lo más rápido posible? ¿Que obtengamos la máxima cobertura y retroalimentación de pruebas unitarias rápidas y sin dependencias, y que tengamos el mínimo número de pruebas de extremo a extremo más lentas y defectuosas?

  2. El diseño orientado al dominio (DDD) nos pide que centremos nuestros esfuerzos en construir un buen modelo del dominio empresarial, pero ¿cómo nos aseguramos de que nuestros modelos no se vean entorpecidos por problemas de infraestructura y no se vuelvan difíciles de cambiar?

  3. Los (micro)servicios débilmente acoplados e integrados mediante mensajes (a veces llamadosmicroservicios reactivos) son una respuesta bien establecida a la gestión de la complejidad en múltiples aplicaciones o dominios empresariales. Pero no siempre es obvio cómo hacer que encajen con las herramientas establecidas del mundo Python -Flask, Django, Celery, etc.-.

Nota

No te desanimes si no trabajas con microservicios (o no te interesan). La gran mayoría de los patrones que discutimos, incluido gran parte del material de arquitectura basada en eventos, es absolutamente aplicable en una arquitectura monolítica.

Nuestro objetivo con este libro es presentar varios patrones arquitectónicos clásicos y mostrar cómo soportan el TDD, el DDD y los servicios basados en eventos. Esperamos que sirva de referencia para implementarlos de forma pitónica, y que la gente pueda utilizarlo como un primer paso para seguir investigando en este campo.

Quién debería leer este libro

He aquí algunas cosas que suponemos sobre ti, querido lector:

  • Has estado cerca de algunas aplicaciones Python razonablemente complejas.

  • Has visto algunas de las dificultades que conlleva intentar gestionar esa complejidad.

  • No tienes por qué saber nada de DDD ni de ninguno de los patrones clásicos de arquitectura de aplicaciones.

Estructuramos nuestras exploraciones de los patrones arquitectónicos en torno a una aplicación de ejemplo, construyéndola capítulo a capítulo. En el trabajo utilizamos TDD, por lo que tendemos a mostrar primero los listados de pruebas, seguidos de la implementación. Si no estás acostumbrado a trabajar primero con las pruebas, puede resultar un poco extraño al principio, pero esperamos que pronto te acostumbres a ver el código "en uso" (es decir, desde fuera) antes de ver cómo se construye por dentro.

Utilizamos algunos marcos y tecnologías específicos de Python, como Flask, SQLAlchemy y pytest, así como Docker y Redis. Si ya estás familiarizado con ellas, no te vendrá mal, pero no creemos que sea necesario. Uno de nuestros principales objetivos con este libro es construir una arquitectura para la que las opciones tecnológicas específicas se conviertan en detalles de implementación menores.

Breve resumen de lo que aprenderás

El libro está dividido en dos partes; aquí tienes un vistazo a los temas que trataremos y a los capítulos en los que aparecen.

Parte I, Construir una arquitectura para apoyar el modelado de dominios

Modelado de dominios y DDD (Capítulos 1 y 7)

En algún nivel, todo el mundo ha aprendido la lección de que los problemas empresariales complejos deben reflejarse en código, en forma de un modelo del dominio. Pero, ¿por qué siempre parece tan difícil hacerlo sin enredarse con problemas de infraestructura, nuestros marcos web o cualquier otra cosa? En el primer capítulo damos una visión general del modelado del dominio y DDD, y mostramos cómo empezar con un modelo que no tenga dependencias externas, y pruebas unitarias rápidas. Más adelante volvemos a los patrones DDD para discutir cómo elegir el agregado adecuado, y cómo esta elección se relaciona con cuestiones de integridad de los datos.

Patrones de Repositorio, Capa de Servicio y Unidad de Trabajo (Capítulos 2, 4 y 5)

En estos tres capítulos presentamos tres patrones estrechamente relacionados y que se refuerzan mutuamente, que respaldan nuestra ambición de mantener el modelo libre de dependencias extrañas. Construimos una capa de abstracción en torno al almacenamiento persistente, y construimos una capa de servicio para definir los puntos de entrada a nuestro sistema y capturar los casos de uso principales. Mostramos cómo esta capa facilita la construcción de puntos de entrada finos a nuestro sistema, ya sea una API de Flask o una CLI.

Algunas reflexiones sobre las pruebas y las abstracciones (Capítulos 3 y 6)

Tras presentar la primera abstracción (el patrón Repositorio), aprovechamos la oportunidad para un debate general sobre cómo elegir abstracciones, y cuál es su papel a la hora de elegir cómo se acopla nuestro software. Después de presentar el patrón Capa de Servicio, hablamos un poco sobre cómo conseguir una pirámide de pruebasy escribir pruebas unitarias en el nivel de abstracción más alto posible.

Parte II, Arquitectura dirigida por eventos

Arquitectura basada en eventos (Capítulos 8-11)

Introducimos otros tres patrones que se refuerzan mutuamente: los patrones Eventos de dominio, Bus de mensajes y Manejador. Los eventos de dominio son un vehículo para captar la idea de que algunas interacciones con un sistema son desencadenantes de otras. Utilizamos un bus de mensajes para permitir que las acciones desencadenen eventos y llamen a los manejadores apropiados. Pasamos a discutir cómo pueden utilizarse los eventos como patrón para la integración entre servicios en una arquitectura de microservicios. Por último, distinguimos entre órdenes y eventos. Nuestra aplicación es ahora fundamentalmente un sistema de procesamiento de mensajes.

Segregación de la responsabilidad de la consulta de comandos(capítulo 12)

Presentamos un ejemplo de segregación de responsabilidades comando-consulta, con y sin eventos.

Inyección de dependencia(capítulo 13)

Ordenamos nuestras dependencias explícitas e implícitas e implementamos un sencillo marco de inyección de dependencias.

Contenido adicional

¿Cómo puedo llegar desde aquí?(Epílogo)

Implementar patrones arquitectónicos siempre parece fácil cuando se muestra un ejemplo sencillo, partiendo de cero, pero muchos de vosotros probablemente os preguntaréis cómo aplicar estos principios al software existente. En el epílogo daremos algunos consejos y enlaces a otras lecturas.

Ejemplo de código y codificación

Estás leyendo un libro, pero probablemente estarás de acuerdo con nosotros cuando decimos que la mejor forma de aprender sobre código es codificando. Aprendimos la mayor parte de lo que sabemos emparejándonos con gente, escribiendo código con ellos y aprendiendo haciendo, y nos gustaría recrear esa experiencia en la medida de lo posible para ti en este libro.

Por ello, hemos estructurado el libro en torno a un único proyecto de ejemplo (aunque a veces incluimos otros ejemplos). Iremos construyendo este proyecto a medida que avancen los capítulos, como si te hubieras emparejado con nosotros y te fuéramos explicando lo que hacemos y por qué en cada paso.

Pero para familiarizarte realmente con estos patrones, tienes que trastear con el código y hacerte una idea de cómo funciona. Encontrarás todo el código en GitHub; cada capítulo tiene su propia rama. También puedes encontrar una lista de las ramas en GitHub.

Aquí tienes tres formas de codificar junto con el libro:

  • Empieza tu propio repositorio e intenta crear la aplicación como nosotros, siguiendo los ejemplos de los listados del libro y, de vez en cuando, buscando pistas en nuestro repositorio. Sin embargo, una advertencia: si has leído el libro anterior de Harry y has codificado con él, te darás cuenta de que este libro requiere que descubras más cosas por tu cuenta; puede que tengas que apoyarte bastante en las versiones de trabajo de GitHub.

  • Intenta aplicar cada patrón, capítulo a capítulo, a tu propio proyecto (preferiblemente pequeño/de juguete), y comprueba si puedes hacer que funcione para tu caso de uso. Esto supone un alto riesgo/alta recompensa (¡y además un alto esfuerzo!). Puede que te lleve bastante trabajo conseguir que las cosas funcionen para las particularidades de tu proyecto, pero, por otro lado, es probable que aprendas lo máximo.

  • Para que te esfuerces menos, en cada capítulo esbozamos un "Ejercicio para el lector" y te indicamos una ubicación de GitHub donde puedes descargarte código parcialmente terminado del capítulo con algunas partes que te faltan para que lo escribas tú mismo.

Sobre todo si tienes intención de aplicar algunos de estos patrones en tus propios proyectos, trabajar con un ejemplo sencillo es una forma estupenda de practicar con seguridad.

Consejo

Como mínimo, haz un git checkout del código de nuestro repositorio mientras lees cada capítulo. Poder entrar y ver el código en el contexto de una aplicación real en funcionamiento te ayudará a resolver muchas dudas sobre la marcha, y hará que todo sea más real. Encontrarás instrucciones sobre cómo hacerlo al principio de cada capítulo.

Licencia

El código (y la versión en línea del libro) está bajo una licencia Creative Commons CC BY-NC-ND, lo que significa que eres libre de copiarlo y compartirlo con quien quieras, con fines no comerciales, siempre que des la atribución correspondiente. Si quieres reutilizar cualquier contenido de este libro y tienes alguna duda sobre la licencia, ponte en contacto con O'Reilly en

La edición impresa tiene una licencia diferente; consulta la página de copyright.

Convenciones utilizadas en este libro

En este libro se utilizan las siguientes convenciones tipográficas:

Cursiva

Indica nuevos términos, URL, direcciones de correo electrónico, nombres de archivo y extensiones de archivo.

Constant width

Se utiliza en los listados de programas, así como dentro de los párrafos para referirse a elementos del programa como nombres de variables o funciones, bases de datos, tipos de datos, variables de entorno, sentencias y palabras clave.

Constant width bold

Muestra comandos u otros textos que deben ser tecleados literalmente por el usuario.

Constant width italic

Muestra el texto que debe sustituirse por valores proporcionados por el usuario o por valores determinados por el contexto.

Consejo

Este elemento significa un consejo o sugerencia.

Nota

Este elemento significa una nota general.

Advertencia

Este elemento indica una advertencia o precaución.

Aprendizaje en línea O'Reilly

Nota

Durante más de 40 años, O'Reilly Media ha proporcionado formación tecnológica y empresarial, conocimientos y perspectivas para ayudar a las empresas a alcanzar el éxito.

Nuestra red única de expertos e innovadores comparten sus conocimientos y experiencia a través de libros, artículos, conferencias y nuestra plataforma de aprendizaje online. La plataforma de aprendizaje en línea de O'Reilly te ofrece acceso bajo demanda a cursos de formación en directo, rutas de aprendizaje en profundidad, entornos de codificación interactivos y una amplia colección de textos y vídeos de O'Reilly y de más de 200 editoriales. Para más información, visita http://oreilly.com.

Cómo contactar con O'Reilly

Dirige tus comentarios y preguntas sobre este libro a la editorial:

  • O'Reilly Media, Inc.
  • 1005 Gravenstein Highway Norte
  • Sebastopol, CA 95472
  • 800-998-9938 (en Estados Unidos o Canadá)
  • 707-829-0515 (internacional o local)
  • 707-829-0104 (fax)

Tenemos una página web para este libro, donde se enumeran erratas, ejemplos y cualquier información adicional. Puedes acceder a esta página en https://oreil.ly/architecture-patterns-python.

Envía un correo electrónico para comentar o hacer preguntas técnicas sobre este libro.

Para más información sobre nuestros libros, cursos, conferencias y noticias, consulta nuestro sitio web en http://www.oreilly.com.

Encuéntranos en Facebook: http://facebook.com/oreilly

Síguenos en Twitter: http://twitter.com/oreillymedia

Míranos en YouTube: http://www.youtube.com/oreillymedia

Agradecimientos

A nuestros revisores técnicos, David Seddon, Ed Jung y Hynek Schlawack: no os merecemos en absoluto. Todos sois increíblemente dedicados, concienzudos y rigurosos. Cada uno de vosotros es inmensamente inteligente, y vuestros diferentes puntos de vista fueron útiles y complementarios entre sí. Gracias de todo corazón.

Muchas gracias también a nuestros lectores de la versión anticipada por sus comentarios y sugerencias: Ian Cooper, Abdullah Ariff, Jonathan Meier, Gil Gonçalves, Matthieu Choplin, Ben Judson, James Gregory, Łukasz Lechowicz, Clinton Roy, Vitorino Araújo, Susan Goodbody, Josh Harwood, Daniel Butler, Liu Haibin, Jimmy Davies, Ignacio Vergara Kausel, Gaia Canestrani, Renne Rocha, pedroabi, Ashia Zawaduk, Jostein Leira, Brandon Rhodes, y muchos más; nuestras disculpas si te hemos omitido en esta lista.

Súper-mega-gracias a nuestro editor, Corbin Collins, por sus amables indicaciones y por ser un incansable defensor del lector. Del mismo modo, muchísimas gracias al personal de producción, Katherine Tozer, Sharon Wilkey, Ellen Troutman-Zaig y Rebecca Demarest, por vuestra dedicación, profesionalidad y atención al detalle. Este libro ha mejorado inconmensurablemente gracias a vosotras.

Los errores que pueda haber en el libro son nuestros, naturalmente.

1 python -c "import this"

Get Patrones de Arquitectura con Python now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.