Arquitectura Hexagonal
La arquitectura de software se refiere al conjunto de reglas que decidimos como equipo al definir cómo diseñamos nuestro software.
- the set of design decisions that must be made early
- the decisions that you wish you could get right eary
- the decisions that are hard to change
– Martin Fowler, "Making Architecture Matter"
Design Payoff Line
Complejidad esencial vs. Complejidad accidental
Tipos de arquitecturas
- Old School ("a batalla", sin arquitectura)
- MVC
- Arquitecturas limpias (arquitectura hexagonal)
Arquitecturas limpias
Arquitectura hexagonal
Capa de dominio
A la que pertenece lo relacionado con el problema específico del mundo real que tratamos de resolver desarrollando software
Entidad: Objeto del modelo con identidad propia, distinguible de otros objetos con los mismos atributos (ej.: usuarios).
Value Object: Clase que se identifica por el valor que representa, no por su identidad (ej.: números, fechas, monedas, URLs). Por ejemplo, podrían ser value objects para nosotros dos productos que cuesten 5€, por ser idénticos en cuanto a precio.
Capa de aplicación
Engloba los "casos de uso" o "servicios de aplicación" que representan de forma atómica las funcionalidades del sistema.
Los casos de uso pueden hacer de "barrera transaccional" (o suceden o no suceden, no se quedan a medias) con el sistema de persistencia.
Capa de infraestructura
Es código que cambia en función de decisiones externas (ej.: librerías).
Regla de dependencia
Las capas de fuera conocen lo que hay inmediatamente dentro, pero las capas de dentro no saben nada sobre lo que hay fuera.
Principio de Inversión de Dependencias
Las cosas más importantes (dominio) no deben depender de las cosas menos importantes (infraestructura: frameworks o librerías para el acceso a datos, red, framework de vistas utilizado, etc.).
El principio de inversión de dependencias dice que los módulos de alto nivel no deberían depender de los de bajo nivel, ni las abstracciones de detalles.¹ – Robert C. Martin ("Uncle Bob")
ej.: abstracción: $Invoice
Repository
Queremos conseguir que los Casos de Uso dependan de algo abstracto
ej.: que no dependa de qué base de datos usamos, sino que directamente tengamos un invoiceRepository.save(invoice)
¿Por qué hacer una abstracción cuando solo tienes una implementación? Porque el coste a futuro de cambiar eso es mucho más caro si no hacemos la abstracción de primeras.
Patrón de diseño de Inyección de Dependencias
Un objeto (cliente) recibe otro objeto (servicio) del cual depende.¹ Lo que busca este patrón de diseño es extraer la responsabilidad de creación de instancias de un componente para delegarla en otro. – Martin Fowler
Estructura de carpetas
src/
├── core/
│ ├── domain/
│ ├── infrastructure/
│ └── services/
└── ui/ # ui/ es infraestructura, pero la sacan fuera por ser
│ # muy grande e incluso desacoplada en cuanto a lenguaje
├── components/
├── theme/
└── views/