Diseño de Código Base
Diseña módulos profundos: mucho comportamiento detrás de una interfaz pequeña, colocada en una costura donde se encuentran quienes llaman y las pruebas. Apunta a apalancamiento para quienes llaman, localidad para los mantenedores y pruebas que sobrevivan a refactorizaciones.
Reglas
- La profundidad es una propiedad de la interfaz, no de la implementación. Un módulo profundo puede estar construido a partir de partes pequeñas e intercambiables; simplemente no forman parte de su interfaz. Puede tener costuras internas para sus propias pruebas, además de la costura externa en su interfaz.
- Realiza la prueba de eliminación. Imagina eliminar el módulo. Si la complejidad desaparece, era un mero pasante. Si la complejidad reaparece distribuida entre quienes llaman, entonces el módulo justifica su existencia.
- La interfaz es la superficie de prueba. Quienes llaman y las pruebas cruzan la misma costura. Si necesitas probar más allá de la interfaz, probablemente el módulo tenga la forma incorrecta.
- Un adaptador significa una costura hipotética; dos la hacen real. Agrega una costura solo donde algo realmente varía, usualmente producción y prueba.
- Reduce la interfaz. Menos métodos, parámetros más simples, más complejidad oculta en su interior.
- Acepta dependencias en lugar de crearlas. Pasa la pasarela de pago en lugar de construirla dentro de la función.
- Devuelve resultados en lugar de producir efectos secundarios cuando el diseño lo permita.
Vocabulario
Usa estos términos exactamente. No sustituyas "componente", "servicio", "API" o "límite".
- Módulo: cualquier cosa con una interfaz y una implementación, a cualquier escala: una función, clase, paquete o corte entre capas.
- Interfaz: todo lo que quien llama debe saber para usar el módulo correctamente: tipos, invariantes, orden, modos de error, configuración requerida y rendimiento. No solo la firma.
- Implementación: el código dentro de un módulo. Un adaptador pequeño puede tener una implementación grande (un repositorio Postgres), y un adaptador grande una implementación pequeña (un simulacro en memoria).
- Profundidad: apalancamiento en la interfaz, es decir, el comportamiento que quien llama o una prueba puede ejercer por unidad de interfaz que debe aprender. Un módulo es profundo cuando mucho comportamiento se encuentra detrás de una interfaz pequeña, y superficial cuando la interfaz es casi tan compleja como la implementación.
- Costura (Michael Feathers): un lugar donde el comportamiento puede cambiar sin editar ese lugar; donde vive la interfaz de un módulo. Elegir la costura es una decisión en sí misma.
- Adaptador: algo concreto que llena una interfaz en una costura. Nombra un rol, no el contenido.
- Apalancamiento: lo que quienes llaman ganan de la profundidad. Una implementación se amortiza a través de muchos puntos de llamada y pruebas.
- Localidad: lo que los mantenedores ganan de la profundidad. Cambio, bugs, conocimiento y verificación se concentran en un solo lugar.
Encuadres rechazados: profundidad como la relación entre líneas de implementación y líneas de interfaz, porque recompensa el relleno; "interfaz" como solo una palabra clave de tipo o los métodos públicos, porque es demasiado estrecho; "límite", porque choca con el contexto acotado de DDD.
Si el proyecto mantiene un glosario CONTEXT.md, utiliza sus términos de dominio junto con estos.
Profundizando más
- Para profundizar un conjunto de módulos superficiales por tipo de dependencia, lee DEEPENING.md.
- Para comparar varias interfaces radicalmente diferentes, lee DESIGN-IT-TWICE.md. Inicia tres o más subagentes, por lo que úsalo solo cuando el usuario lo solicite.