Be Software Architecture Wise
Be Wise Apps

Read in English · Lire en français · Auf Deutsch lesen

Capítulo 3 de 12 · Intermedio

Principios y fundamentos de diseño

Toda arquitectura se construye a partir de las mismas pocas ideas sobre la estructura: cómo dividir un sistema en partes, cuánto deben saber esas partes unas de otras, en qué dirección deben apuntar sus dependencias y cómo mantener el conjunto tan simple como permita el problema. Este capítulo enseña esas ideas a todas las escalas, desde una clase de Python hasta un componente y una flota de servicios: modularidad, acoplamiento y cohesión, ocultación de información, gestión de dependencias, SOLID, connascence, la ley de Conway, la simplicidad y las métricas que miden la estructura. Está pensado para desarrolladores que quieren razonar sobre el diseño con precisión y para arquitectos que necesitan un vocabulario común para las revisiones.

Introducción en video al capítulo 3

6 min · narrado en inglés, con subtítulos
Solo escuchar (audio)
Leer la transcripción

Te damos la bienvenida al Capítulo 3: Principios y fundamentos de diseño. Toda arquitectura se construye a partir de las mismas pocas ideas sobre la estructura. Cómo dividir un sistema en partes, cuánto deben saber esas partes unas de otras, en qué dirección deben apuntar sus dependencias y cómo mantener el conjunto tan simple como permita el problema. Este capítulo enseña esas ideas.

El Capítulo 2 describió las cualidades que debe ofrecer una arquitectura. La mayoría de ellas, y la modificabilidad por encima de todas, dependen menos de una tecnología concreta que de la estructura. Un equipo puede elegir el framework más de moda y aun así acabar con un sistema en el que cada cambio toca diez sitios. Estos principios son ideas antiguas. La ocultación de información data de mil novecientos setenta y dos, y la ley de Conway de mil novecientos sesenta y ocho. Han sobrevivido porque describen algo que no cambia: el costo de un cambio depende de lo lejos que tenga que llegar ese cambio. Lo que ha cambiado es la escala. El principio que te dice que mantengas privados los campos de una clase también te dice que mantengas privada la base de datos de un servicio. Por eso cada sección muestra cada idea dos veces: en un pequeño fragmento de código y a la escala de los componentes y los servicios.

Este capítulo está pensado para desarrolladores que quieren razonar sobre el diseño con precisión. También está pensado para arquitectos que necesitan un vocabulario común para las revisiones de diseño. Ayuda saber leer ejemplos breves de Python. Se apoya en los atributos de calidad del Capítulo 2, que estos principios ayudan a lograr. Conviene haber leído la sección cero punto tres, sobre cómo organizar el código, y la sección dos punto seis, sobre cómo diseñar para el cambio. Y conduce al Capítulo 4, que muestra cómo describir una estructura para que otros puedan entenderla y cuestionarla.

Las cuatro primeras secciones sientan las bases. La sección tres punto uno se pregunta qué es un módulo y dónde deben ir sus límites. David Parnas demostró que dividir un sistema por pasos de procesamiento fracasa, y que dividirlo por cambios probables funciona. La sección tres punto dos te da el vocabulario para juzgar los límites: los niveles clásicos de acoplamiento y cohesión, y los tipos de acoplamiento que solo aparecen entre servicios. La sección tres punto tres examina la propia interfaz: la ocultación de información, los contratos, las abstracciones con fugas y por qué acaba habiendo dependencias de todo comportamiento visible de una interfaz popular. La sección tres punto cuatro pasa a la dirección: hacia dónde deben apuntar las dependencias, cómo medir la estabilidad, cómo romper ciclos y cómo comprobar todo esto automáticamente.

Este diagrama de la sección tres punto dos muestra el vocabulario en acción, en una refactorización real. A la izquierda está el diseño anterior: un módulo de pedidos y un módulo de facturación. Pedidos llama directamente a Facturación y le pasa un indicador que selecciona uno de dos comportamientos. Así que Pedidos tiene que conocer ese indicador, y no puede aceptar un pedido si Facturación va lenta o está fallando. Peor aún, los dos módulos usan la misma tabla de pedidos. Cualquier cambio en su estructura, sus códigos de estado o sus reglas de IVA tiene que hacerse en los dos módulos a la vez. A la derecha está el diseño posterior. Pedidos publica un evento Order Placed en un intermediario de mensajes, con exactamente los datos que necesita Facturación. Facturación se suscribe, y cada servicio es propietario de sus propios datos. El acoplamiento no ha desaparecido: Facturación sigue dependiendo del significado de ese evento. Pero ahora es explícito, estrecho y versionado, que es lo que significa en la práctica el acoplamiento débil.

Las cuatro secciones siguientes se apoyan en esas bases. La sección tres punto cinco trata los cinco principios SOLID, cada uno mostrado en código y entre servicios, junto con las críticas que reciben cuando se aplican de forma mecánica. La sección tres punto seis presenta la connascence, una medida más fina del acoplamiento, con un conjunto claro de reglas para hacerlo más débil y más local. La sección tres punto siete amplía la mirada a la organización: la ley de Conway, la evidencia que la respalda y la aritmética de las vías de comunicación. La sección tres punto ocho cierra con la simplicidad y la medición: la complejidad propia del problema y la complejidad que añadimos nosotros, el precio de mantener opciones abiertas y los límites de todas las métricas.

Esta es la ley de Conway en una sola imagen. A la izquierda hay una organización. Un equipo de pago y un equipo de catálogo tienen que pasar por un equipo compartido de administradores de bases de datos para cada cambio de esquema. A la derecha está el sistema que construyen: un servicio de pago y un servicio de catálogo que leen y escriben en una base de datos compartida. La estructura del sistema copia la estructura de comunicación. Así que, cuando diseñas un sistema, también estás diseñando quién necesita hablar con quién, y lo contrario es igual de cierto.

Leídas juntas, las ocho secciones forman un solo argumento. El cambio es el costo dominante del software, así que una buena estructura es aquella en la que los cambios probables se mantienen locales. Todos los principios del capítulo son formas de conseguirlo. Por eso también los principios a veces entran en conflicto, y por eso ninguno es absoluto. La habilidad profesional consiste en preguntarse, para un cambio que es probable en este sistema, hasta dónde tendría que llegar y qué principio acorta esa distancia al menor costo.

Si eres nuevo en el diseño, lee las secciones en orden. Cada una empieza con una breve explicación cotidiana. Leer todo el capítulo lleva unas tres horas. Si eres un ingeniero con experiencia, quizá prefieras empezar por los ejemplos prácticos, como la tienda en línea de la sección tres punto uno o el cálculo de métricas de la sección tres punto cuatro. Están pensados para debatirlos. Cada sección termina con unas cuantas preguntas de autoevaluación. Respóndelas mentalmente antes de mirar. Cuando estés listo, haz la prueba opcional del capítulo: veinte preguntas de opción múltiple y dos respuestas escritas, en unos cuarenta y cinco minutos. La nota de aprobado es el ochenta por ciento.

Ese es el mapa del Capítulo 3. Empieza por la sección tres punto uno, sobre la modularidad, donde veremos cómo dividir un sistema para que los cambios que esperas se queden dentro de una sola parte. Nos vemos allí.

Descargar el capítulo (PDF)Leer en la app

De un vistazo

Aprenderás a

  • Explicar el criterio de Parnas para descomponer un sistema en módulos y aplicarlo para comparar dos descomposiciones candidatas.
  • Clasificar las dependencias con los niveles clásicos de acoplamiento y cohesión, e identificar el acoplamiento temporal, de despliegue y semántico entre servicios.
  • Distinguir la ocultación de información del encapsulamiento, especificar una interfaz como un contrato y diseñar API estables que tengan en cuenta las abstracciones con fugas y la ley de Hyrum.
  • Calcular la inestabilidad, el grado de abstracción y la distancia a la secuencia principal, y usarlos junto con los principios de dependencias acíclicas, de dependencias estables y de abstracciones estables para corregir estructuras de dependencias.
  • Aplicar los principios SOLID y los principios de cohesión de componentes a escala de clase, de componente y de servicio, y reconocer cuándo se están aplicando de forma dogmática.
  • Usar la connascence para describir la fuerza, la localidad y el grado del acoplamiento, y elegir refactorizaciones que lo debiliten.
  • Explicar la ley de Conway, la evidencia que la respalda y la maniobra inversa de Conway, y calcular las vías de comunicación de un equipo.
  • Separar la complejidad esencial de la accidental, calcular la complejidad ciclomática y convertir reglas estructurales en funciones de aptitud sin caer en la ley de Goodhart.

Antes de empezar

Capítulos 0 a 2, en especial la Sección 0.3 (organizar el código), la Sección 1.7 (deuda técnica) y la Sección 2.6 (modificabilidad). Ayuda saber leer ejemplos breves de Python.

Tiempo

Unas 3 horas de lectura; 45 minutos para la prueba.

Términos clave

modularidad · ocultación de información · acoplamiento · cohesión · acoplamiento aferente y eferente · abstracción · diseño por contrato · Ley de Hyrum · Principio de dependencias acíclicas · inestabilidad y grado de abstracción · SOLID · connascence · Ley de Conway · complejidad accidental

Por qué principios, y por qué a todas las escalas

El Capítulo 2 describió las cualidades que debe ofrecer una arquitectura. La mayoría de ellas, y la modificabilidad por encima de todas, dependen menos de una tecnología concreta que de la estructura: cómo se divide un sistema en partes, qué sabe cada parte de las demás y en qué dirección van las dependencias entre ellas. Un equipo puede elegir el framework más de moda y la mejor plataforma en la nube y aun así acabar con un sistema en el que cada cambio toca diez sitios, porque las partes se cortaron por los lugares equivocados. Los principios de este capítulo son el conocimiento acumulado durante más de cincuenta años sobre cómo cortarlas bien.

Son ideas antiguas, y eso es una fortaleza. La ocultación de información data de 1972; el acoplamiento y la cohesión, del trabajo sobre diseño estructurado de finales de la década de 1960 y de la de 1970; la ley de Conway, de 1968. Han sobrevivido porque describen algo que no cambia: el costo de un cambio depende de lo lejos que tenga que llegar ese cambio. Lo que ha cambiado es la escala a la que los aplican los arquitectos. El mismo principio que te dice que mantengas privados los campos de una clase te dice que mantengas privada la base de datos de un servicio; el mismo razonamiento que prohíbe un ciclo de dependencias entre dos paquetes prohíbe dos servicios que solo se pueden lanzar juntos. Por eso cada sección muestra cada idea dos veces: en un pequeño fragmento de código y a la escala de los componentes y los servicios.

Cómo está organizado el capítulo

Las cuatro primeras secciones sientan las bases. La Sección 3.1 se pregunta qué es un módulo y dónde deben ir sus límites, usando el ejemplo KWIC de David Parnas para mostrar por qué falla descomponer por pasos de procesamiento y por qué funciona descomponer por cambios probables, y separa los módulos lógicos de las unidades físicas que se compilan y se despliegan. La Sección 3.2 ofrece el vocabulario para juzgar los límites: los niveles clásicos de acoplamiento y cohesión, el acoplamiento aferente y eferente, y los tipos de acoplamiento que solo aparecen entre servicios. La Sección 3.3 examina la propia interfaz: ocultación de información frente a encapsulamiento, contratos, abstracciones con fugas, módulos profundos y la ley de Hyrum. La Sección 3.4 pasa a la dirección: los principios de Robert C. Martin para las dependencias entre componentes, las métricas de inestabilidad y de grado de abstracción, cómo romper ciclos, la organización en capas y cómo comprobar todo esto automáticamente.

Las cuatro secciones siguientes se apoyan en ellas. La Sección 3.5 trata los cinco principios SOLID y los principios de cohesión de componentes, cada uno mostrado tanto en código como entre servicios, junto con las críticas que reciben cuando se aplican de forma mecánica. La Sección 3.6 presenta la connascence, una medida más fina del acoplamiento con un conjunto claro de reglas para hacerlo más débil y más local. La Sección 3.7 amplía la mirada a la organización: la ley de Conway, la evidencia que la respalda, la aritmética de las vías de comunicación y la maniobra inversa de Conway. La Sección 3.8 cierra con la simplicidad y la medición: la complejidad esencial y la complejidad accidental, KISS, YAGNI y DRY bien entendidos, el precio de mantener opciones abiertas, métricas estructurales como la complejidad ciclomática y los límites de todas las métricas.

Una idea por debajo de todos ellos

Leídas juntas, las ocho secciones forman un solo argumento. El cambio es el costo dominante del software, así que una buena estructura es aquella en la que los cambios probables se mantienen locales. Todos los principios del capítulo son formas de conseguirlo. Parnas dice que hay que poner cada cambio probable dentro de un módulo. El acoplamiento y la cohesión dicen que hay que mantener juntas las cosas que cambian juntas y separadas las que cambian por separado. La ocultación de información dice que hay que asegurarse de que lo que puede cambiar sea invisible desde fuera. Los principios de dependencias dicen que hay que dirigir las dependencias hacia lo que menos cambia. La connascence dice que hay que mantener cualquier acuerdo fuerte entre dos fragmentos de código lo más cerca posible. La ley de Conway añade que las personas forman parte de la estructura: un cambio que necesita que dos equipos se pongan de acuerdo no es local, se organice como se organice el código.

Ese argumento también explica por qué los principios a veces entran en conflicto y por qué ninguno es absoluto. Eliminar la duplicación puede aumentar el acoplamiento; añadir interfaces para invertir una dependencia puede hacer que un módulo sea menos profundo; dividir un componente para mejorar la cohesión puede crear un salto de red. La habilidad profesional no consiste en aplicar todos los principios en todas partes, sino en preguntarse, para un cambio concreto que es probable en un sistema concreto, hasta dónde tendría que llegar ese cambio y qué principio acorta esa distancia al menor costo.

Cómo usar este capítulo

Quienes son nuevos en el diseño pueden leer las secciones en orden; cada una empieza con una breve explicación cotidiana y remite a la Sección 0.3, donde se presentaron por primera vez los conceptos básicos. Los ingenieros con experiencia quizá prefieran empezar por los ejemplos prácticos: la descomposición de la tienda en línea de la Sección 3.1, la refactorización de pedidos y facturación de la Sección 3.2, la interfaz de pagos de la Sección 3.3 y el cálculo de métricas de la Sección 3.4 están pensados para debatirlos. Los principios de este capítulo se usan en el resto del curso: los estilos arquitectónicos de los Capítulos 5 y 6 son, en gran medida, respuestas distintas a las preguntas de dónde poner los límites y hacia dónde apuntan las dependencias, y el Capítulo 11 convierte las comprobaciones automáticas presentadas aquí en una práctica de gobernanza mediante funciones de aptitud.

Las 8 secciones

3.1 · Intermedio · 22 minModularidadQué es un módulo a cualquier escala, por qué dividimos los sistemas en módulos, la regla de Parnas de descomponer según los cambios probables, los módulos lógicos frente a los de despliegue, la granularidad y cómo hacer cumplir los límites en el código.Leer →3.2 · Intermedio · 24 minAcoplamiento y cohesiónLas dos medidas más antiguas de una buena estructura: los niveles clásicos de acoplamiento y cohesión, el acoplamiento aferente y eferente, las formas adicionales de acoplamiento en los sistemas distribuidos y las tácticas para reducirlo, con un ejemplo práctico de refactorización.Leer →3.3 · Intermedio · 24 minOcultación de informaciónPor qué los módulos deben ocultar decisiones, en qué se diferencia la ocultación de información del encapsulamiento, las interfaces como contratos y el diseño por contrato, las abstracciones con fugas, los módulos profundos, la ley de Hyrum y cómo mantener estables las API entre componentes.Leer →3.4 · Intermedio · 25 minDependenciasHacia dónde deben apuntar las dependencias y por qué: los principios de dependencias acíclicas, de dependencias estables y de abstracciones estables de Robert C. Martin, las métricas de inestabilidad, grado de abstracción y distancia, cómo romper ciclos, la organización en capas y las comprobaciones automáticas de dependencias.Leer →3.5 · Intermedio · 26 minSOLID a escalaLos cinco principios SOLID explicados con precisión, cada uno mostrado en Python y luego a escala de componentes y de servicios, más los principios de cohesión REP, CCP y CRP, su triángulo de tensiones y las críticas honestas a SOLID.Leer →3.6 · Intermedio · 22 minConnascenceLa connascence de Meilir Page-Jones pone nombre a los acuerdos ocultos entre las partes de un sistema, los clasifica por fuerza y los valora por localidad y grado, desde los parámetros posicionales hasta la temporización entre servicios.Leer →3.7 · Intermedio · 22 minLey de ConwayLa observación de Melvin Conway de 1968 según la cual los sistemas copian la estructura de comunicación de las organizaciones que los diseñan, la evidencia de la investigación, la aritmética de las vías de comunicación, la maniobra inversa de Conway y la carga cognitiva del equipo.Leer →3.8 · Intermedio · 25 minSimplicidad y mediciónLa complejidad esencial y la accidental, KISS, YAGNI, DRY como conocimiento y no como texto, la reversibilidad como opción, y cómo medir la estructura con la complejidad ciclomática, LCOM, el acoplamiento de cambio y las funciones de aptitud sin caer en la ley de Goodhart.Leer →

Prueba del capítulo

Comprueba lo que has entendido del capítulo 3

Opcional: 20 preguntas de opción múltiple y 2 respuestas escritas breves, elegidas de nuevo cada vez de un banco de 72 preguntas. Nota de aprobado: 80%. Superar todas las pruebas de capítulo y después la evaluación final da derecho al Certificado de Finalización Be Wise.

Haz la prueba del capítulo 3 en la app

Lecturas recomendadas